mirror of
https://github.com/leanprover/lean4.git
synced 2026-04-03 10:44:09 +00:00
Compare commits
19 Commits
worktree-e
...
sofia/time
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c299831f51 | ||
|
|
b3409dc0dd | ||
|
|
923dfbd037 | ||
|
|
80943ca7dd | ||
|
|
166f53f95b | ||
|
|
0330b69d71 | ||
|
|
d0a5db6838 | ||
|
|
6985f0789c | ||
|
|
35172fea61 | ||
|
|
1735d56935 | ||
|
|
ad7839176c | ||
|
|
5178995108 | ||
|
|
8f6d0aeada | ||
|
|
a355358d1c | ||
|
|
3ffd791a59 | ||
|
|
aba2a77795 | ||
|
|
13f5f9166f | ||
|
|
f51fb1e866 | ||
|
|
d05e772630 |
@@ -90,11 +90,11 @@ where
|
||||
messageMethod? msg <|> (do pending.get? (← messageId? msg))
|
||||
|
||||
local instance : ToJson Std.Time.ZonedDateTime where
|
||||
toJson dt := dt.toISO8601String
|
||||
toJson dt := Std.Time.Formats.iso8601.format dt
|
||||
|
||||
local instance : FromJson Std.Time.ZonedDateTime where
|
||||
fromJson?
|
||||
| .str s => Std.Time.ZonedDateTime.fromISO8601String s
|
||||
| .str s => Std.Time.Formats.iso8601.parse s
|
||||
| _ => throw "Expected string when converting JSON to Std.Time.ZonedDateTime"
|
||||
|
||||
structure LogEntry where
|
||||
|
||||
@@ -17,8 +17,7 @@ public import Std.Time.Zoned.Database
|
||||
|
||||
public section
|
||||
|
||||
namespace Std
|
||||
namespace Time
|
||||
namespace Std.Time
|
||||
|
||||
/-!
|
||||
# Time
|
||||
@@ -130,23 +129,30 @@ Represents spans of time and the difference between two points in time.
|
||||
# Formats
|
||||
|
||||
Format strings are used to convert between `String` representations and date/time types, like `yyyy-MM-dd'T'HH:mm:ss.sssZ`.
|
||||
The table below shows the available format specifiers. Some specifiers can be repeated to control truncation or offsets.
|
||||
When a character is repeated `n` times, it usually truncates the value to `n` characters.
|
||||
The table below shows the available format specifiers. Repeating a pattern character may change the
|
||||
text style, minimum width, or offset/fraction form, depending on the field.
|
||||
|
||||
The `number` type format specifiers, such as `h` and `K`, are parsed based on the number of repetitions.
|
||||
If the repetition count is one, the format allows values ranging from 1 up to the maximum capacity of
|
||||
the respective data type.
|
||||
The current Lean implementation follows Java's pattern language where practical, but it is not fully
|
||||
locale-sensitive. Text forms currently use English data, and localized weekday/week-of-month fields use
|
||||
the library's fixed Monday-first interpretation.
|
||||
|
||||
For numeric fields that accept both one- and two-letter forms, the single-letter form parses a
|
||||
non-padded number and the two-letter form parses a zero-padded width of two.
|
||||
|
||||
The supported formats include:
|
||||
- `G`: Represents the era, such as AD (Anno Domini) or BC (Before Christ).
|
||||
- `G`, `GG`, `GGG` (short): Displays the era in a short format (e.g., "AD").
|
||||
- `GGGG` (full): Displays the era in a full format (e.g., "Anno Domini").
|
||||
- `GGGGG` (narrow): Displays the era in a narrow format (e.g., "A").
|
||||
- `G`: Represents the era, such as BCE (Before Common Era) or CE (Common Era).
|
||||
- `G`, `GG`, `GGG` (short): Displays the era in a short format (e.g., "CE").
|
||||
- `GGGG` (full): Displays the era in a full format (e.g., "Common Era").
|
||||
- `GGGGG` (narrow): Displays the era in a narrow format (e.g., "C").
|
||||
- `y`: Represents the year of the era.
|
||||
- `y`: Represents the year in its full form, without a fixed length. It can handle years of any size, (e.g., "1", "2025", or "12345678").
|
||||
- `yy`: Displays the year in a two-digit format, showing the last two digits (e.g., "04" for 2004).
|
||||
- `yyyy`: Displays the year in a four-digit format (e.g., "2004").
|
||||
- `yyyy+`: Extended format for years with more than four digits.
|
||||
- `Y`: Represents the week-based year (ISO-like behavior around year boundaries).
|
||||
- `Y`, `YYY`, `YYYY`: Displays the week-based year (e.g., "2017").
|
||||
- `YY`: Displays the last two digits of the week-based year (e.g., "17").
|
||||
- `YYYYY+`: Extended format for week-based years with more than four digits.
|
||||
- `u`: Represents the year.
|
||||
- `u`: Represents the year in its full form, without a fixed length. It can handle years of any size, (e.g., "1", "2025", or "12345678").
|
||||
- `uu`: Two-digit year format, showing the last two digits (e.g., "04" for 2004).
|
||||
@@ -158,69 +164,94 @@ The supported formats include:
|
||||
- `MMM`: Displays the abbreviated month name (e.g., "Jul").
|
||||
- `MMMM`: Displays the full month name (e.g., "July").
|
||||
- `MMMMM`: Displays the month in a narrow form (e.g., "J" for July).
|
||||
- `L`: Represents the standalone month of the year.
|
||||
- Supports the same widths as `M`; in the current English data it formats the same values.
|
||||
- `d`: Represents the day of the month.
|
||||
- `Q`: Represents the quarter of the year.
|
||||
- `Q`, `QQ`: Displays the quarter as a number (e.g., "3", "03").
|
||||
- `QQQ` (short): Displays the quarter as an abbreviated text (e.g., "Q3").
|
||||
- `QQQQ` (full): Displays the full quarter text (e.g., "3rd quarter").
|
||||
- `QQQQQ` (narrow): Displays the quarter as a short number (e.g., "3").
|
||||
- `q`: Represents the standalone quarter of the year.
|
||||
- Supports the same widths as `Q`; in the current English data it formats the same values.
|
||||
- `w`: Represents the week of the week-based year, each week starts on Monday (e.g., "27").
|
||||
- `W`: Represents the week of the month, each week starts on Monday (e.g., "4").
|
||||
- `W`: Represents the week of the month using the library's fixed Monday-first week model (e.g., "2").
|
||||
- `E`: Represents the day of the week as text.
|
||||
- `E`, `EE`, `EEE`: Displays the abbreviated weekday name (e.g., "Tue").
|
||||
- `EEEE`: Displays the full day name (e.g., "Tuesday").
|
||||
- `EEEEE`: Displays the narrow day name (e.g., "T" for Tuesday).
|
||||
- `EEEEEE`: Displays the short two-letter weekday name (e.g., "Tu").
|
||||
- `e`: Represents the weekday as number or text.
|
||||
- `e`, `ee`: Displays the weekday as a number, starting from 1 (Monday) to 7 (Sunday).
|
||||
- `eee`, `eeee`, `eeeee`: Displays the weekday as text (same format as `E`).
|
||||
- `F`: Represents the week of the month that the first week starts on the first day of the month (e.g., "3").
|
||||
- `eeeeee`: Displays the short two-letter weekday name (e.g., "Tu").
|
||||
- `c`: Standalone weekday.
|
||||
- `c`: Displays the numeric weekday using the same Monday-to-Sunday numbering as `e`.
|
||||
- `ccc`, `cccc`, `ccccc`: Display standalone text (same values as `e` in the current English data).
|
||||
- `cccccc`: Displays the short two-letter weekday name (e.g., "Tu").
|
||||
- `F`: Represents the occurrence of the weekday within the month (e.g., the 2nd Sunday formats as `2`).
|
||||
- `a`: Represents the AM or PM designation of the day.
|
||||
- `a`, `aa`, `aaa`: Displays AM or PM in a concise format (e.g., "PM").
|
||||
- `aaaa`: Displays the full AM/PM designation (e.g., "Post Meridium").
|
||||
- `a`, `aa`, `aaa`: Displays AM/PM (e.g., "PM").
|
||||
- `aaaa`: Displays the full form (e.g., "ante meridiem", "post meridiem").
|
||||
- `aaaaa`: Displays the narrow form (e.g., "a", "p").
|
||||
- `b`: Represents the day period, extending AM/PM with noon and midnight (TR35 §4, supported in Java 16+). The `B` symbol (flexible day periods) is not supported.
|
||||
- `b`, `bb`, `bbb`: Displays a short form (e.g., "AM", "PM", "noon", "midnight").
|
||||
- `bbbb`: Displays a full form (e.g., "ante meridiem", "post meridiem", "noon", "midnight"); unlike `a`, the AM/PM spellings are lowercase here.
|
||||
- `bbbbb`: Displays a narrow form (e.g., "a", "p", "n", "mi").
|
||||
- `h`: Represents the hour of the AM/PM clock (1-12) (e.g., "12").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- `h`, `hh` are supported, matching Java.
|
||||
- `K`: Represents the hour of the AM/PM clock (0-11) (e.g., "0").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- `K`, `KK` are supported, matching Java.
|
||||
- `k`: Represents the hour of the day in a 1-24 format (e.g., "24").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- `k`, `kk` are supported, matching Java.
|
||||
- `H`: Represents the hour of the day in a 0-23 format (e.g., "0").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- `H`, `HH` are supported, matching Java.
|
||||
- `m`: Represents the minute of the hour (e.g., "30").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- `m`, `mm` are supported, matching Java.
|
||||
- `s`: Represents the second of the minute (e.g., "55").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- `s`, `ss` are supported, matching Java.
|
||||
- `S`: Represents a fraction of a second, typically displayed as a decimal number (e.g., "978" for milliseconds).
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- One or more repetitions of the character truncates to the specified number of most-significant digits; it does not round.
|
||||
- `A`: Represents the millisecond of the day (e.g., "1234").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- `n`: Represents the nanosecond of the second (e.g., "987654321").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- `N`: Represents the nanosecond of the day (e.g., "1234000000").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- `VV`: Represents the time zone ID, which could be a city-based zone (e.g., "America/Los_Angeles"), a UTC marker (`"Z"`), or a specific offset (e.g., "-08:30").
|
||||
- One or more repetitions of the character indicates the truncation of the value to the specified number of characters.
|
||||
- One or more repetitions of the character indicates zero-padding to the specified number of characters (no truncation is applied).
|
||||
- `n`: Represents the nanosecond of the second (e.g., "987654321"). This is a Lean/Java extension, not a TR35 field.
|
||||
- One or more repetitions of the character sets a minimum width via zero-padding; the value is not truncated.
|
||||
- `N`: Represents the nanosecond of the day (e.g., "1234000000"). This is a Lean/Java extension, not a TR35 field.
|
||||
- One or more repetitions of the character sets a minimum width via zero-padding; the value is not truncated.
|
||||
- `V`: Time zone ID.
|
||||
- `VV`: Displays the zone identifier/name.
|
||||
- Other counts are unsupported, matching Java.
|
||||
- `z`: Represents the time zone name.
|
||||
- `z`, `zz`, `zzz`: Shows an abbreviated time zone name (e.g., "PST" for Pacific Standard Time).
|
||||
- `zzzz`: Displays the full time zone name (e.g., "Pacific Standard Time").
|
||||
- `z`, `zz`, `zzz`: Shows a short zone name; for offset-only zones this is the numeric offset (e.g., "+09:00"), for UTC this is "UTC", otherwise the abbreviation (e.g., "PST").
|
||||
- `zzzz`: Displays the full zone name; for offset-only zones this is the numeric offset (e.g., "+09:00"), for UTC this is "Coordinated Universal Time", otherwise the full zone name (e.g., "Pacific Standard Time").
|
||||
- `v`: Generic time zone name.
|
||||
- `v`: In the current Lean timezone data this displays the stored abbreviation; for offset-only zones this is the numeric offset (e.g., "+09:00"), and for UTC it is normalized to "UTC".
|
||||
- `vvvv`: In the current Lean timezone data this displays the stored zone name/ID; for offset-only zones this is the numeric offset (e.g., "+09:00"), and for UTC it is normalized to "Coordinated Universal Time".
|
||||
- `O`: Represents the localized zone offset in the format "GMT" followed by the time difference from UTC.
|
||||
- `O`: Displays the GMT offset in a simple format (e.g., "GMT+8").
|
||||
- `OOOO`: Displays the full GMT offset, including hours and minutes (e.g., "GMT+08:00").
|
||||
- `O`: Displays the GMT offset in a short format (e.g., "GMT+8"), or "GMT" for UTC.
|
||||
- `OOOO`: Displays the full GMT offset with padded hour and minutes (e.g., "GMT+08:00"), or "GMT" for UTC.
|
||||
- `X`: Represents the zone offset. It uses 'Z' for UTC and can represent any offset (positive or negative).
|
||||
- `X`: Displays the hour offset (e.g., "-08").
|
||||
- `X`: Displays hour and optional minute offset (e.g., "-08", "-0830", or "Z").
|
||||
- `XX`: Displays the hour and minute offset without a colon (e.g., "-0830").
|
||||
- `XXX`: Displays the hour and minute offset with a colon (e.g., "-08:30").
|
||||
- `XXXX`: Displays the hour, minute, and second offset without a colon (e.g., "-083045").
|
||||
- `XXXXX`: Displays the hour, minute, and second offset with a colon (e.g., "-08:30:45").
|
||||
- `x`: Represents the zone offset. Similar to X, but does not display 'Z' for UTC and focuses only on positive offsets.
|
||||
- `x`: Displays the hour offset (e.g., "+08").
|
||||
- `XXXX`: Displays the hour and minute offset without a colon, with optional seconds (e.g., "-0830", "-083045").
|
||||
- `XXXXX`: Displays the hour and minute offset with a colon, with optional seconds (e.g., "-08:30", "-08:30:45").
|
||||
- `x`: Represents the zone offset. Similar to `X`, but never displays `'Z'` for UTC.
|
||||
- `x`: Displays hour and optional minute offset (e.g., "+00", "+0530").
|
||||
- `xx`: Displays the hour and minute offset without a colon (e.g., "+0830").
|
||||
- `xxx`: Displays the hour and minute offset with a colon (e.g., "+08:30").
|
||||
- `xxxx`: Displays the hour, minute, and second offset without a colon (e.g., "+083045").
|
||||
- `xxxxx`: Displays the hour, minute, and second offset with a colon (e.g., "+08:30:45").
|
||||
- `Z`: Always includes an hour and minute offset and may use 'Z' for UTC, providing clear differentiation between UTC and other time zones.
|
||||
- `Z`: Displays the hour and minute offset without a colon (e.g., "+0800").
|
||||
- `ZZ`: Displays "GMT" followed by the time offset (e.g., "GMT+08:00" or "Z").
|
||||
- `ZZZ`: Displays the full hour, minute, and second offset with a colon (e.g., "+08:30:45" or "Z").
|
||||
- `xxxx`: Displays the hour and minute offset without a colon, with optional seconds (e.g., "+0830", "+083045").
|
||||
- `xxxxx`: Displays the hour and minute offset with a colon, with optional seconds (e.g., "+08:30", "+08:30:45").
|
||||
- `Z`: Represents the zone offset in RFC/CLDR `Z` forms.
|
||||
- `Z`, `ZZ`, `ZZZ`: Displays hour and minute offset without colon, with optional seconds (e.g., "+0800", "+083045").
|
||||
- `ZZZZ`: Displays localized GMT form (e.g., "GMT+08:00").
|
||||
- `ZZZZZ`: Displays hour and minute offset with a colon and optional seconds, and uses `"Z"` for UTC (e.g., "Z", "+08:30", "+08:30:45").
|
||||
# Runtime Parsing
|
||||
|
||||
- `ZonedDateTime.parse` parses common zoned date-time formats with explicit offsets, but does not resolve timezone identifiers like `[Europe/Paris]`.
|
||||
- `ZonedDateTime.parseIO` resolves identifier-based inputs via the default timezone database.
|
||||
- `ZonedDateTime.fromLeanDateTimeWithIdentifierString` is pure and does not perform timezone database resolution.
|
||||
- `ZonedDateTime.fromLeanDateTimeWithIdentifierStringIO` resolves identifiers using the default timezone database.
|
||||
|
||||
# Macros
|
||||
|
||||
@@ -234,8 +265,10 @@ The `.sssssssss` can be omitted in most cases.
|
||||
- **`offset("+HH:mm")`**: Represents a timezone offset in the format `+HH:mm`, where `+` or `-` indicates the direction from UTC.
|
||||
- **`timezone("NAME/ID ZZZ")`**: Specifies a timezone using a region-based name or ID, along with its associated offset.
|
||||
- **`datespec("FORMAT")`**: Defines a compile-time date format based on the provided string.
|
||||
- **`zoned("uuuu-MM-ddTHH:mm:ss.sssssssssZZZ")`**: Represents a `ZonedDateTime` with a fixed timezone and optional nanosecond precision.
|
||||
- **`zoned("uuuu-MM-ddTHH:mm:ss.sssssssssZZZZZ")`**: Represents a `ZonedDateTime` with a fixed timezone and optional nanosecond precision.
|
||||
- **`zoned("uuuu-MM-ddTHH:mm:ss.sssssssss[IDENTIFIER]")`**: Defines an `IO ZonedDateTime`, where the timezone identifier is dynamically retrieved from the default timezone database.
|
||||
- **`zoned("uuuu-MM-ddTHH:mm:ss.sssssssss, timezone")`**: Represents an `IO ZonedDateTime`, using a specified `timezone` term and allowing optional nanoseconds.
|
||||
|
||||
-/
|
||||
|
||||
end Std.Time
|
||||
|
||||
@@ -355,6 +355,28 @@ def weekOfYear (date : PlainDate) : Week.Ordinal :=
|
||||
let w := w.truncateBottom h |>.truncateTop (Int.le_trans h₁ y.weeks.property.right)
|
||||
w
|
||||
|
||||
/--
|
||||
Returns the week-based year for a given `PlainDate`.
|
||||
-/
|
||||
def weekBasedYear (date : PlainDate) : Year.Offset :=
|
||||
let year := date.year
|
||||
let doy := date.dayOfYear
|
||||
let dow := date.weekday.toOrdinal.sub 1
|
||||
|
||||
if doy.val ≤ 3 then
|
||||
if doy.val - dow.val < -2 then
|
||||
year - 1
|
||||
else
|
||||
year
|
||||
else if doy.val ≥ 363 then
|
||||
let leap := if date.inLeapYear then 1 else 0
|
||||
if (doy.val - 363 - leap) - dow.val ≥ 0 then
|
||||
year + 1
|
||||
else
|
||||
year
|
||||
else
|
||||
year
|
||||
|
||||
instance : HAdd PlainDate Day.Offset PlainDate where
|
||||
hAdd := addDays
|
||||
|
||||
|
||||
@@ -502,6 +502,11 @@ def weekOfMonth (date : PlainDateTime) : Bounded.LE 1 5 :=
|
||||
date.date.weekOfMonth
|
||||
|
||||
/--
|
||||
Returns the week-based year for a given `PlainDateTime`.
|
||||
-/
|
||||
def weekBasedYear (date : PlainDateTime) : Year.Offset :=
|
||||
date.date.weekBasedYear
|
||||
/--
|
||||
Determines the week of the month for the given `PlainDateTime`. The week of the month is calculated based
|
||||
on the day of the month and the weekday. Each week starts on Monday because the entire library is
|
||||
based on the Gregorian Calendar.
|
||||
|
||||
@@ -23,144 +23,207 @@ set_option linter.all true
|
||||
The ISO 8601 format, used for representing date and time in a standardized
|
||||
format. The format follows the pattern `uuuu-MM-dd'T'HH:mm:ssXXX`.
|
||||
-/
|
||||
def iso8601 : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ssXXX")
|
||||
|
||||
def iso8601 : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ssXXX")
|
||||
|
||||
/--
|
||||
The americanDate format, which follows the pattern `MM-dd-uuuu`.
|
||||
-/
|
||||
def americanDate : GenericFormat .any := datespec("MM-dd-uuuu")
|
||||
def americanDate : Format Awareness.any := datespec("MM-dd-uuuu")
|
||||
|
||||
/--
|
||||
The europeanDate format, which follows the pattern `dd-MM-uuuu`.
|
||||
-/
|
||||
def europeanDate : GenericFormat .any := datespec("dd-MM-uuuu")
|
||||
def europeanDate : Format Awareness.any := datespec("dd-MM-uuuu")
|
||||
|
||||
/--
|
||||
The time12Hour format, which follows the pattern `hh:mm:ss aa` for representing time
|
||||
The time12Hour format, which follows the pattern `hh:mm:ss a` for representing time
|
||||
in a 12-hour clock format with an upper case AM/PM marker.
|
||||
-/
|
||||
def time12Hour : GenericFormat .any := datespec("hh:mm:ss aa")
|
||||
def time12Hour : Format Awareness.any := datespec("hh:mm:ss a")
|
||||
|
||||
/--
|
||||
The Time24Hour format, which follows the pattern `HH:mm:ss` for representing time
|
||||
in a 24-hour clock format.
|
||||
-/
|
||||
def time24Hour : GenericFormat .any := datespec("HH:mm:ss")
|
||||
def time24Hour : Format Awareness.any := datespec("HH:mm:ss")
|
||||
|
||||
/--
|
||||
The DateTimeZone24Hour format, which follows the pattern `uuuu-MM-dd:HH:mm:ss.SSSSSSSSS` for
|
||||
representing date, time, and time zone.
|
||||
-/
|
||||
def dateTime24Hour : GenericFormat (.only .GMT) := datespec("uuuu-MM-dd:HH:mm:ss.SSSSSSSSS")
|
||||
def dateTime24Hour : Format (.only .GMT) := datespec("uuuu-MM-dd:HH:mm:ss.SSSSSSSSS")
|
||||
|
||||
/--
|
||||
The DateTimeWithZone format, which follows the pattern `uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZ`
|
||||
for representing date, time, and time zone.
|
||||
-/
|
||||
def dateTimeWithZone : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZ")
|
||||
def dateTimeWithZone : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZ")
|
||||
|
||||
/--
|
||||
The leanTime24Hour format, which follows the pattern `HH:mm:ss.SSSSSSSSS` for representing time
|
||||
in a 24-hour clock format. It uses the default value that can be parsed with the
|
||||
notation of dates.
|
||||
-/
|
||||
def leanTime24Hour : GenericFormat .any := datespec("HH:mm:ss.SSSSSSSSS")
|
||||
def leanTime24Hour : Format Awareness.any := datespec("HH:mm:ss.SSSSSSSSS")
|
||||
|
||||
/--
|
||||
The leanTime24HourNoNanos format, which follows the pattern `HH:mm:ss` for representing time
|
||||
in a 24-hour clock format. It uses the default value that can be parsed with the
|
||||
notation of dates.
|
||||
-/
|
||||
def leanTime24HourNoNanos : GenericFormat .any := datespec("HH:mm:ss")
|
||||
def leanTime24HourNoNanos : Format Awareness.any := datespec("HH:mm:ss")
|
||||
|
||||
/--
|
||||
The leanDateTime24Hour format, which follows the pattern `uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS` for
|
||||
representing date, time, and time zone. It uses the default value that can be parsed with the
|
||||
notation of dates.
|
||||
-/
|
||||
def leanDateTime24Hour : GenericFormat (.only .GMT) := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS")
|
||||
def leanDateTime24Hour : Format (.only .GMT) := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS")
|
||||
|
||||
/--
|
||||
The leanDateTime24HourNoNanos format, which follows the pattern `uuuu-MM-dd'T'HH:mm:ss` for
|
||||
representing date, time, and time zone. It uses the default value that can be parsed with the
|
||||
notation of dates.
|
||||
-/
|
||||
def leanDateTime24HourNoNanos : GenericFormat (.only .GMT) := datespec("uuuu-MM-dd'T'HH:mm:ss")
|
||||
def leanDateTime24HourNoNanos : Format (.only .GMT) := datespec("uuuu-MM-dd'T'HH:mm:ss")
|
||||
|
||||
/--
|
||||
The leanDateTimeWithZone format, which follows the pattern `uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ`
|
||||
for representing date, time, and time zone. It uses the default value that can be parsed with the
|
||||
notation of dates.
|
||||
-/
|
||||
def leanDateTimeWithZone : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ")
|
||||
def leanDateTimeWithZone : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ")
|
||||
|
||||
/--
|
||||
The leanDateTimeWithZoneNoNanos format, which follows the pattern `uuuu-MM-dd'T'HH:mm:ssZZZZZ`
|
||||
for representing date, time, and time zone. It uses the default value that can be parsed with the
|
||||
notation of dates.
|
||||
-/
|
||||
def leanDateTimeWithZoneNoNanos : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ssZZZZZ")
|
||||
def leanDateTimeWithZoneNoNanos : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ssZZZZZ")
|
||||
|
||||
/--
|
||||
The leanDateTimeWithIdentifier format, which follows the pattern `uuuu-MM-dd'T'HH:mm:ss[z]`
|
||||
for representing date, time, and time zone. It uses the default value that can be parsed with the
|
||||
notation of dates.
|
||||
-/
|
||||
def leanDateTimeWithIdentifier : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ss'['zzzz']'")
|
||||
def leanDateTimeWithIdentifier : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss'['VV']'")
|
||||
|
||||
/--
|
||||
The leanDateTimeWithIdentifierAndNanos format, which follows the pattern `uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS'[z]'`
|
||||
for representing date, time, and time zone. It uses the default value that can be parsed with the
|
||||
notation of dates.
|
||||
-/
|
||||
def leanDateTimeWithIdentifierAndNanos : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS'['zzzz']'")
|
||||
def leanDateTimeWithIdentifierAndNanos : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS'['VV']'")
|
||||
|
||||
/--
|
||||
The leanDateTimeWithZoneAndName format, which follows the pattern
|
||||
`uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ'['VV']'` for representing date, time, timezone offset,
|
||||
and timezone identifier. This is the canonical Lean format used in `repr` for named timezones.
|
||||
-/
|
||||
def leanDateTimeWithZoneAndName : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ'['VV']'")
|
||||
|
||||
/--
|
||||
The leanDateTimeWithZoneAndNameNoNanos format, which follows the pattern
|
||||
`uuuu-MM-dd'T'HH:mm:ssZZZZZ'['zzzz']'` for representing date, time, timezone offset, and timezone
|
||||
identifier without nanoseconds.
|
||||
-/
|
||||
def leanDateTimeWithZoneAndNameNoNanos : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ssZZZZZ'['VV']'")
|
||||
|
||||
/--
|
||||
The Lean Date format, which follows the pattern `uuuu-MM-dd`. It uses the default value that can be parsed with the
|
||||
notation of dates.
|
||||
-/
|
||||
def leanDate : GenericFormat .any := datespec("uuuu-MM-dd")
|
||||
def leanDate : Format Awareness.any := datespec("uuuu-MM-dd")
|
||||
|
||||
/--
|
||||
The SQLDate format, which follows the pattern `uuuu-MM-dd` and is commonly used
|
||||
in SQL databases to represent dates.
|
||||
-/
|
||||
def sqlDate : GenericFormat .any := datespec("uuuu-MM-dd")
|
||||
def sqlDate : Format Awareness.any := datespec("uuuu-MM-dd")
|
||||
|
||||
/--
|
||||
The LongDateFormat, which follows the pattern `EEEE, MMMM d, uuuu HH:mm:ss` for
|
||||
representing a full date and time with the day of the week and month name.
|
||||
-/
|
||||
def longDateFormat : GenericFormat (.only .GMT) := datespec("EEEE, MMMM d, uuuu HH:mm:ss")
|
||||
def longDateFormat : Format (.only .GMT) := datespec("EEEE, MMMM d, uuuu HH:mm:ss")
|
||||
|
||||
/--
|
||||
The AscTime format, which follows the pattern `EEE MMM d HH:mm:ss uuuu`. This format
|
||||
is often used in older systems for logging and time-stamping events.
|
||||
-/
|
||||
def ascTime : GenericFormat (.only .GMT) := datespec("EEE MMM d HH:mm:ss uuuu")
|
||||
def ascTime : Format (.only .GMT) := datespec("EEE MMM d HH:mm:ss uuuu")
|
||||
|
||||
/--
|
||||
The RFC822 format, which follows the pattern `eee, dd MMM uuuu HH:mm:ss ZZZ`.
|
||||
This format is used in email headers and HTTP headers.
|
||||
-/
|
||||
def rfc822 : GenericFormat .any := datespec("eee, dd MMM uuuu HH:mm:ss ZZZ")
|
||||
def rfc822 : Format Awareness.any := datespec("eee, dd MMM uuuu HH:mm:ss ZZZ")
|
||||
|
||||
/--
|
||||
The RFC850 format, which follows the pattern `eee, dd-MMM-YY HH:mm:ss ZZZ`.
|
||||
The RFC850 format, which follows the pattern `eee, dd-MMM-yy HH:mm:ss ZZZ`.
|
||||
This format is an older standard for representing date and time in headers.
|
||||
-/
|
||||
def rfc850 : GenericFormat .any := datespec("eee, dd-MM-uuuu HH:mm:ss ZZZ")
|
||||
def rfc850 : Format Awareness.any := datespec("eee, dd-MMM-yy HH:mm:ss ZZZ")
|
||||
|
||||
/--
|
||||
A `MultiFormat` that parses `leanDateTimeWithZone` with or without nanoseconds.
|
||||
-/
|
||||
def leanDateTimeWithZoneAlt : MultiFormat Awareness.any :=
|
||||
.new #[leanDateTimeWithZone, leanDateTimeWithZoneNoNanos]
|
||||
|
||||
/--
|
||||
A `MultiFormat` that parses `leanDateTimeWithZoneAndName` with or without nanoseconds.
|
||||
-/
|
||||
def leanDateTimeWithZoneAndNameAlt : MultiFormat Awareness.any :=
|
||||
.new #[leanDateTimeWithZoneAndName, leanDateTimeWithZoneAndNameNoNanos]
|
||||
|
||||
/--
|
||||
A `MultiFormat` that parses `leanDateTime24Hour` with or without nanoseconds.
|
||||
-/
|
||||
def leanDateTime24HourAlt : MultiFormat (.only .GMT) :=
|
||||
.new #[leanDateTime24Hour, leanDateTime24HourNoNanos]
|
||||
|
||||
/--
|
||||
A `MultiFormat` that parses `leanTime24Hour` with or without nanoseconds.
|
||||
-/
|
||||
def leanTime24HourAlt : MultiFormat Awareness.any :=
|
||||
.new #[leanTime24Hour, leanTime24HourNoNanos]
|
||||
|
||||
/--
|
||||
A `MultiFormat` that parses `leanDateTimeWithIdentifier` with or without nanoseconds.
|
||||
-/
|
||||
def leanDateTimeWithIdentifierAlt : MultiFormat Awareness.any :=
|
||||
.new #[leanDateTimeWithIdentifier, leanDateTimeWithIdentifierAndNanos]
|
||||
|
||||
end Formats
|
||||
|
||||
namespace Format
|
||||
|
||||
/--
|
||||
Parses the input string, resolving any timezone identifier via the default timezone database.
|
||||
For formats with a timezone identifier specifier but no offset specifier (e.g.
|
||||
`uuuu-MM-dd'T'HH:mm:ss'['zzzz']'`), this performs a tzdb lookup to find the correct UTC offset.
|
||||
For all other formats this behaves identically to `parse`.
|
||||
-/
|
||||
def parseIO (format : Format Awareness.any) (input : String) : IO ZonedDateTime := do
|
||||
if format.hasIdentifierSpecifier && !format.hasOffsetSpecifier then
|
||||
match format.parseUnchecked input with
|
||||
| .error err => throw <| IO.userError err
|
||||
| .ok zdt =>
|
||||
let rules ← Database.defaultGetZoneRules zdt.timezone.name
|
||||
pure <| ZonedDateTime.ofPlainDateTime zdt.toPlainDateTime rules
|
||||
else
|
||||
IO.ofExcept (format.parse input)
|
||||
|
||||
end Format
|
||||
|
||||
namespace TimeZone
|
||||
|
||||
/--
|
||||
Parses a string into a `TimeZone` object. The input string must be in the format `"VV ZZZZZ"`.
|
||||
-/
|
||||
def fromTimeZone (input : String) : Except String TimeZone := do
|
||||
let spec : GenericFormat .any := datespec("VV ZZZZZ")
|
||||
let spec : Format Awareness.any := datespec("VV ZZZZZ")
|
||||
spec.parseBuilder (fun id off => some (TimeZone.mk off id (off.toIsoString true) false)) input
|
||||
|
||||
namespace Offset
|
||||
@@ -169,7 +232,7 @@ namespace Offset
|
||||
Parses a string representing an offset into an `Offset` object. The input string must follow the `"xxx"` format.
|
||||
-/
|
||||
def fromOffset (input : String) : Except String Offset := do
|
||||
let spec : GenericFormat .any := datespec("xxx")
|
||||
let spec : Format Awareness.any := datespec("xxx")
|
||||
spec.parseBuilder some input
|
||||
|
||||
end Offset
|
||||
@@ -181,76 +244,44 @@ namespace PlainDate
|
||||
Formats a `PlainDate` using a specific format.
|
||||
-/
|
||||
def format (date : PlainDate) (format : String) : String :=
|
||||
let format : Except String (GenericFormat .any) := GenericFormat.spec format
|
||||
let format : Except String (Format Awareness.any) := Format.spec format
|
||||
match format with
|
||||
| .error err => s!"error: {err}"
|
||||
| .ok res =>
|
||||
let res := res.formatGeneric fun
|
||||
| .G _ => some date.era
|
||||
| .y _ => some date.year
|
||||
| .Y _ => some date.weekBasedYear
|
||||
| .u _ => some date.year
|
||||
| .D _ => some (Sigma.mk date.year.isLeap date.dayOfYear)
|
||||
| .Qorq _ => some date.quarter
|
||||
| .Q _ | .q _ => some date.quarter
|
||||
| .w _ => some date.weekOfYear
|
||||
| .W _ => some date.alignedWeekOfMonth
|
||||
| .MorL _ => some date.month
|
||||
| .W _ => some date.weekOfMonth
|
||||
| .M _ | .L _ => some date.month
|
||||
| .d _ => some date.day
|
||||
| .E _ => some date.weekday
|
||||
| .eorc _ => some date.weekday
|
||||
| .e _ | .c _ => some date.weekday
|
||||
| .F _ => some date.weekOfMonth
|
||||
| _ => none
|
||||
match res with
|
||||
| some res => res
|
||||
| none => "invalid time"
|
||||
|
||||
/--
|
||||
Parses a date string in the American format (`MM-dd-uuuu`) and returns a `PlainDate`.
|
||||
-/
|
||||
def fromAmericanDateString (input : String) : Except String PlainDate := do
|
||||
Formats.americanDate.parseBuilder (fun m d y => PlainDate.ofYearMonthDay? y m d) input
|
||||
|
||||
/--
|
||||
Converts a date in the American format (`MM-dd-uuuu`) into a `String`.
|
||||
-/
|
||||
def toAmericanDateString (input : PlainDate) : String :=
|
||||
Formats.americanDate.formatBuilder input.month input.day input.year
|
||||
|
||||
/--
|
||||
Parses a date string in the SQL format (`uuuu-MM-dd`) and returns a `PlainDate`.
|
||||
-/
|
||||
def fromSQLDateString (input : String) : Except String PlainDate := do
|
||||
Formats.sqlDate.parseBuilder PlainDate.ofYearMonthDay? input
|
||||
|
||||
/--
|
||||
Converts a date in the SQL format (`uuuu-MM-dd`) into a `String`.
|
||||
-/
|
||||
def toSQLDateString (input : PlainDate) : String :=
|
||||
Formats.sqlDate.formatBuilder input.year input.month input.day
|
||||
|
||||
/--
|
||||
Parses a date string in the Lean format (`uuuu-MM-dd`) and returns a `PlainDate`.
|
||||
-/
|
||||
def fromLeanDateString (input : String) : Except String PlainDate := do
|
||||
Formats.leanDate.parseBuilder PlainDate.ofYearMonthDay? input
|
||||
|
||||
/--
|
||||
Converts a date in the Lean format (`uuuu-MM-dd`) into a `String`.
|
||||
-/
|
||||
def toLeanDateString (input : PlainDate) : String :=
|
||||
Formats.leanDate.formatBuilder input.year input.month input.day
|
||||
|
||||
/--
|
||||
Parses a `String` in the `AmericanDate` or `SQLDate` format and returns a `PlainDate`.
|
||||
-/
|
||||
def parse (input : String) : Except String PlainDate :=
|
||||
fromAmericanDateString input
|
||||
<|> fromSQLDateString input
|
||||
Formats.americanDate.parseBuilder (fun m d y => PlainDate.ofYearMonthDay? y m d) input
|
||||
<|> Formats.sqlDate.parseBuilder PlainDate.ofYearMonthDay? input
|
||||
|
||||
def leanDateString (d : PlainDate) : String :=
|
||||
Formats.leanDate.formatBuilder d.year d.month d.day
|
||||
|
||||
instance : ToString PlainDate where
|
||||
toString := toLeanDateString
|
||||
toString := leanDateString
|
||||
|
||||
instance : Repr PlainDate where
|
||||
reprPrec data := Repr.addAppParen ("date(\"" ++ toLeanDateString data ++ "\")")
|
||||
reprPrec d := Repr.addAppParen ("date(\"" ++ leanDateString d ++ "\")")
|
||||
|
||||
end PlainDate
|
||||
|
||||
@@ -260,7 +291,7 @@ namespace PlainTime
|
||||
Formats a `PlainTime` using a specific format.
|
||||
-/
|
||||
def format (time : PlainTime) (format : String) : String :=
|
||||
let format : Except String (GenericFormat .any) := GenericFormat.spec format
|
||||
let format : Except String (Format Awareness.any) := Format.spec format
|
||||
match format with
|
||||
| .error err => s!"error: {err}"
|
||||
| .ok res =>
|
||||
@@ -271,6 +302,16 @@ def format (time : PlainTime) (format : String) : String :=
|
||||
| .n _ => some time.nanosecond
|
||||
| .s _ => some time.second
|
||||
| .a _ => some (HourMarker.ofOrdinal time.hour)
|
||||
| .b _ =>
|
||||
let h := time.hour.val
|
||||
let m := time.minute.val
|
||||
let s := time.second.val
|
||||
let n := time.nanosecond.val
|
||||
some <|
|
||||
if h = 12 ∧ m = 0 ∧ s = 0 ∧ n = 0 then .noon
|
||||
else if h = 0 ∧ m = 0 ∧ s = 0 ∧ n = 0 then .midnight
|
||||
else if h < 12 then .am
|
||||
else .pm
|
||||
| .h _ => some time.hour.toRelative
|
||||
| .K _ => some (time.hour.emod 12 (by decide))
|
||||
| .S _ => some time.nanosecond
|
||||
@@ -282,58 +323,24 @@ def format (time : PlainTime) (format : String) : String :=
|
||||
| none => "invalid time"
|
||||
|
||||
/--
|
||||
Parses a time string in the 24-hour format (`HH:mm:ss`) and returns a `PlainTime`.
|
||||
-/
|
||||
def fromTime24Hour (input : String) : Except String PlainTime :=
|
||||
Formats.time24Hour.parseBuilder (fun h m s => some (PlainTime.ofHourMinuteSeconds h m s)) input
|
||||
|
||||
/--
|
||||
Formats a `PlainTime` value into a 24-hour format string (`HH:mm:ss`).
|
||||
-/
|
||||
def toTime24Hour (input : PlainTime) : String :=
|
||||
Formats.time24Hour.formatBuilder input.hour input.minute input.second
|
||||
|
||||
/--
|
||||
Parses a time string in the lean 24-hour format (`HH:mm:ss.SSSSSSSSS` or `HH:mm:ss`) and returns a `PlainTime`.
|
||||
-/
|
||||
def fromLeanTime24Hour (input : String) : Except String PlainTime :=
|
||||
Formats.leanTime24Hour.parseBuilder (fun h m s n => some <| PlainTime.ofHourMinuteSecondsNano h m s n) input
|
||||
<|> Formats.leanTime24HourNoNanos.parseBuilder (fun h m s => some <| PlainTime.ofHourMinuteSecondsNano h m s 0) input
|
||||
|
||||
/--
|
||||
Formats a `PlainTime` value into a 24-hour format string (`HH:mm:ss.SSSSSSSSS`).
|
||||
-/
|
||||
def toLeanTime24Hour (input : PlainTime) : String :=
|
||||
Formats.leanTime24Hour.formatBuilder input.hour input.minute input.second input.nanosecond
|
||||
|
||||
/--
|
||||
Parses a time string in the 12-hour format (`hh:mm:ss aa`) and returns a `PlainTime`.
|
||||
-/
|
||||
def fromTime12Hour (input : String) : Except String PlainTime := do
|
||||
let builder h m s a : Option PlainTime := do
|
||||
let value ← Internal.Bounded.ofInt? h.val
|
||||
some <| PlainTime.ofHourMinuteSeconds (HourMarker.toAbsolute a value) m s
|
||||
|
||||
Formats.time12Hour.parseBuilder builder input
|
||||
|
||||
/--
|
||||
Formats a `PlainTime` value into a 12-hour format string (`hh:mm:ss aa`).
|
||||
-/
|
||||
def toTime12Hour (input : PlainTime) : String :=
|
||||
Formats.time12Hour.formatBuilder (input.hour.emod 12 (by decide) |>.add 1) input.minute input.second (if input.hour.val ≥ 12 then HourMarker.pm else HourMarker.am)
|
||||
|
||||
/--
|
||||
Parses a `String` in the `Time12Hour` or `Time24Hour` format and returns a `PlainTime`.
|
||||
Parses a `String` in the `Time12Hour`, `Time24Hour`, or lean time (with optional nanoseconds) format
|
||||
and returns a `PlainTime`.
|
||||
-/
|
||||
def parse (input : String) : Except String PlainTime :=
|
||||
fromTime12Hour input
|
||||
<|> fromTime24Hour input
|
||||
Formats.time12Hour.parseBuilder (fun h m s a => do
|
||||
let value ← Internal.Bounded.ofInt? h.val
|
||||
some <| PlainTime.ofHourMinuteSeconds (HourMarker.toAbsolute a value) m s) input
|
||||
<|> Formats.leanTime24Hour.parseBuilder (fun h m s n => some <| PlainTime.ofHourMinuteSecondsNano h m s n) input
|
||||
<|> Formats.time24Hour.parseBuilder (fun h m s => some (PlainTime.ofHourMinuteSeconds h m s)) input
|
||||
|
||||
def leanTimeString (t : PlainTime) : String :=
|
||||
Formats.leanTime24Hour.formatBuilder t.hour t.minute t.second t.nanosecond
|
||||
|
||||
instance : ToString PlainTime where
|
||||
toString := toLeanTime24Hour
|
||||
toString := leanTimeString
|
||||
|
||||
instance : Repr PlainTime where
|
||||
reprPrec data := Repr.addAppParen ("time(\"" ++ toLeanTime24Hour data ++ "\")")
|
||||
reprPrec data := Repr.addAppParen ("time(\"" ++ leanTimeString data ++ "\")")
|
||||
|
||||
end PlainTime
|
||||
|
||||
@@ -343,99 +350,60 @@ namespace ZonedDateTime
|
||||
Formats a `ZonedDateTime` using a specific format.
|
||||
-/
|
||||
def format (data: ZonedDateTime) (format : String) : String :=
|
||||
let format : Except String (GenericFormat .any) := GenericFormat.spec format
|
||||
let format : Except String (Format Awareness.any) := Format.spec format
|
||||
match format with
|
||||
| .error err => s!"error: {err}"
|
||||
| .ok res => res.format data.toDateTime
|
||||
| .ok res => res.format data
|
||||
|
||||
/--
|
||||
Parses a `String` in the `ISO8601` format and returns a `ZonedDateTime`.
|
||||
Parses a `String` in common zoned date-time formats and returns a `ZonedDateTime`.
|
||||
This parser does not resolve timezone identifiers like `[Europe/Paris]`; use `parseIO` for that.
|
||||
-/
|
||||
def fromISO8601String (input : String) : Except String ZonedDateTime :=
|
||||
Formats.iso8601.parse input
|
||||
-- Wraps Format.parse to fix type unification (Awareness.any.type vs ZonedDateTime).
|
||||
private def parseFormat (fmt : Format Awareness.any) (input : String) : Except String ZonedDateTime :=
|
||||
fmt.parse input
|
||||
|
||||
/--
|
||||
Formats a `ZonedDateTime` value into an ISO8601 string.
|
||||
-/
|
||||
def toISO8601String (date : ZonedDateTime) : String :=
|
||||
Formats.iso8601.format date.toDateTime
|
||||
|
||||
/--
|
||||
Parses a `String` in the rfc822 format and returns a `ZonedDateTime`.
|
||||
-/
|
||||
def fromRFC822String (input : String) : Except String ZonedDateTime :=
|
||||
Formats.rfc822.parse input
|
||||
|
||||
/--
|
||||
Formats a `ZonedDateTime` value into an RFC822 format string.
|
||||
-/
|
||||
def toRFC822String (date : ZonedDateTime) : String :=
|
||||
Formats.rfc822.format date.toDateTime
|
||||
|
||||
/--
|
||||
Parses a `String` in the rfc850 format and returns a `ZonedDateTime`.
|
||||
-/
|
||||
def fromRFC850String (input : String) : Except String ZonedDateTime :=
|
||||
Formats.rfc850.parse input
|
||||
|
||||
/--
|
||||
Formats a `ZonedDateTime` value into an RFC850 format string.
|
||||
-/
|
||||
def toRFC850String (date : ZonedDateTime) : String :=
|
||||
Formats.rfc850.format date.toDateTime
|
||||
|
||||
/--
|
||||
Parses a `String` in the dateTimeWithZone format and returns a `ZonedDateTime` object in the GMT time zone.
|
||||
-/
|
||||
def fromDateTimeWithZoneString (input : String) : Except String ZonedDateTime :=
|
||||
Formats.dateTimeWithZone.parse input
|
||||
|
||||
/--
|
||||
Formats a `ZonedDateTime` value into a simple date time with timezone string.
|
||||
-/
|
||||
def toDateTimeWithZoneString (pdt : ZonedDateTime) : String :=
|
||||
Formats.dateTimeWithZone.format pdt.toDateTime
|
||||
|
||||
/--
|
||||
Parses a `String` in the lean date time format with timezone format and returns a `ZonedDateTime` object.
|
||||
-/
|
||||
def fromLeanDateTimeWithZoneString (input : String) : Except String ZonedDateTime :=
|
||||
Formats.leanDateTimeWithZone.parse input
|
||||
<|> Formats.leanDateTimeWithZoneNoNanos.parse input
|
||||
|
||||
/--
|
||||
Parses a `String` in the lean date time format with identifier and returns a `ZonedDateTime` object.
|
||||
-/
|
||||
def fromLeanDateTimeWithIdentifierString (input : String) : Except String ZonedDateTime :=
|
||||
Formats.leanDateTimeWithIdentifier.parse input
|
||||
<|> Formats.leanDateTimeWithIdentifierAndNanos.parse input
|
||||
|
||||
/--
|
||||
Formats a `DateTime` value into a simple date time with timezone string that can be parsed by the date% notation.
|
||||
-/
|
||||
def toLeanDateTimeWithZoneString (zdt : ZonedDateTime) : String :=
|
||||
Formats.leanDateTimeWithZone.formatBuilder zdt.year zdt.month zdt.day zdt.hour zdt.minute zdt.date.get.time.second zdt.nanosecond zdt.offset
|
||||
/--
|
||||
Formats a `DateTime` value into a simple date time with timezone string that can be parsed by the date% notation with the timezone identifier.
|
||||
-/
|
||||
def toLeanDateTimeWithIdentifierString (zdt : ZonedDateTime) : String :=
|
||||
Formats.leanDateTimeWithIdentifierAndNanos.formatBuilder zdt.year zdt.month zdt.day zdt.hour zdt.minute zdt.date.get.time.second zdt.nanosecond zdt.timezone.name
|
||||
|
||||
/--
|
||||
Parses a `String` in the `ISO8601`, `RFC822` or `RFC850` format and returns a `ZonedDateTime`.
|
||||
-/
|
||||
def parse (input : String) : Except String ZonedDateTime :=
|
||||
fromISO8601String input
|
||||
<|> fromRFC822String input
|
||||
<|> fromRFC850String input
|
||||
<|> fromDateTimeWithZoneString input
|
||||
<|> fromLeanDateTimeWithIdentifierString input
|
||||
parseFormat Formats.iso8601 input
|
||||
<|> parseFormat Formats.rfc822 input
|
||||
<|> parseFormat Formats.rfc850 input
|
||||
<|> parseFormat Formats.leanDateTimeWithZone input
|
||||
<|> parseFormat Formats.leanDateTimeWithZoneNoNanos input
|
||||
<|> parseFormat Formats.leanDateTimeWithZoneAndName input
|
||||
<|> parseFormat Formats.leanDateTimeWithZoneAndNameNoNanos input
|
||||
<|> parseFormat Formats.dateTimeWithZone input
|
||||
<|> parseFormat Formats.leanDateTimeWithIdentifier input
|
||||
<|> parseFormat Formats.leanDateTimeWithIdentifierAndNanos input
|
||||
|
||||
/--
|
||||
Parses a `String` in common zoned date-time formats.
|
||||
If the input uses a timezone identifier (for example, `[Europe/Paris]`), it resolves it using the default timezone database.
|
||||
-/
|
||||
def parseIO (input : String) : IO ZonedDateTime := do
|
||||
match parse input with
|
||||
| .ok zdt => pure zdt
|
||||
| .error err =>
|
||||
let identParse : Except String ZonedDateTime :=
|
||||
Formats.leanDateTimeWithIdentifier.parseUnchecked input
|
||||
<|> Formats.leanDateTimeWithIdentifierAndNanos.parseUnchecked input
|
||||
match identParse with
|
||||
| .ok zdt =>
|
||||
let rules ← Database.defaultGetZoneRules zdt.timezone.name
|
||||
pure <| ZonedDateTime.ofPlainDateTime zdt.toPlainDateTime rules
|
||||
| .error _ => throw <| IO.userError err
|
||||
|
||||
instance : ToString ZonedDateTime where
|
||||
toString := toLeanDateTimeWithIdentifierString
|
||||
toString data := Formats.leanDateTimeWithIdentifierAndNanos.format data
|
||||
|
||||
instance : Repr ZonedDateTime where
|
||||
reprPrec data := Repr.addAppParen ("zoned(\"" ++ toLeanDateTimeWithZoneString data ++ "\")")
|
||||
reprPrec data :=
|
||||
let name := data.timezone.name
|
||||
let str :=
|
||||
if name == data.timezone.offset.toIsoString true then
|
||||
Formats.leanDateTimeWithZone.format data
|
||||
else
|
||||
Formats.leanDateTimeWithZoneAndName.format data
|
||||
Repr.addAppParen ("zoned(\"" ++ str ++ "\")")
|
||||
|
||||
end ZonedDateTime
|
||||
|
||||
@@ -445,22 +413,31 @@ namespace PlainDateTime
|
||||
Formats a `PlainDateTime` using a specific format.
|
||||
-/
|
||||
def format (date : PlainDateTime) (format : String) : String :=
|
||||
let format : Except String (GenericFormat .any) := GenericFormat.spec format
|
||||
let format : Except String (Format Awareness.any) := Format.spec format
|
||||
match format with
|
||||
| .error err => s!"error: {err}"
|
||||
| .ok res =>
|
||||
let res := res.formatGeneric fun
|
||||
| .G _ => some date.era
|
||||
| .y _ => some date.year
|
||||
| .Y _ =>
|
||||
let week := date.weekOfYear
|
||||
some <|
|
||||
if date.month.val = 1 ∧ week.val ≥ 52 then
|
||||
date.year - 1
|
||||
else if date.month.val = 12 ∧ week.val = 1 then
|
||||
date.year + 1
|
||||
else
|
||||
date.year
|
||||
| .u _ => some date.year
|
||||
| .D _ => some (Sigma.mk date.year.isLeap date.dayOfYear)
|
||||
| .Qorq _ => some date.quarter
|
||||
| .Q _ | .q _ => some date.quarter
|
||||
| .w _ => some date.weekOfYear
|
||||
| .W _ => some date.alignedWeekOfMonth
|
||||
| .MorL _ => some date.month
|
||||
| .W _ => some date.weekOfMonth
|
||||
| .M _ | .L _ => some date.month
|
||||
| .d _ => some date.day
|
||||
| .E _ => some date.weekday
|
||||
| .eorc _ => some date.weekday
|
||||
| .e _ | .c _ => some date.weekday
|
||||
| .F _ => some date.weekOfMonth
|
||||
| .H _ => some date.hour
|
||||
| .k _ => some date.hour.shiftTo1BasedHour
|
||||
@@ -479,71 +456,22 @@ def format (date : PlainDateTime) (format : String) : String :=
|
||||
| none => "invalid time"
|
||||
|
||||
/--
|
||||
Parses a `String` in the `AscTime` format and returns a `PlainDateTime` object in the GMT time zone.
|
||||
-/
|
||||
def fromAscTimeString (input : String) : Except String PlainDateTime :=
|
||||
Formats.ascTime.parse input
|
||||
|>.map DateTime.toPlainDateTime
|
||||
|
||||
/--
|
||||
Formats a `PlainDateTime` value into an AscTime format string.
|
||||
-/
|
||||
def toAscTimeString (pdt : PlainDateTime) : String :=
|
||||
Formats.ascTime.format (DateTime.ofPlainDateTimeAssumingUTC pdt .UTC)
|
||||
|
||||
/--
|
||||
Parses a `String` in the `LongDateFormat` and returns a `PlainDateTime` object in the GMT time zone.
|
||||
-/
|
||||
def fromLongDateFormatString (input : String) : Except String PlainDateTime :=
|
||||
Formats.longDateFormat.parse input
|
||||
|>.map DateTime.toPlainDateTime
|
||||
|
||||
/--
|
||||
Formats a `PlainDateTime` value into a LongDateFormat string.
|
||||
-/
|
||||
def toLongDateFormatString (pdt : PlainDateTime) : String :=
|
||||
Formats.longDateFormat.format (DateTime.ofPlainDateTimeAssumingUTC pdt .UTC)
|
||||
|
||||
/--
|
||||
Parses a `String` in the `DateTime` format and returns a `PlainDateTime`.
|
||||
-/
|
||||
def fromDateTimeString (input : String) : Except String PlainDateTime :=
|
||||
Formats.dateTime24Hour.parse input
|
||||
|>.map DateTime.toPlainDateTime
|
||||
|
||||
/--
|
||||
Formats a `PlainDateTime` value into a `DateTime` format string.
|
||||
-/
|
||||
def toDateTimeString (pdt : PlainDateTime) : String :=
|
||||
Formats.dateTime24Hour.formatBuilder pdt.year pdt.month pdt.day pdt.hour pdt.minute pdt.time.second pdt.nanosecond
|
||||
|
||||
/--
|
||||
Parses a `String` in the `DateTime` format and returns a `PlainDateTime`.
|
||||
-/
|
||||
def fromLeanDateTimeString (input : String) : Except String PlainDateTime :=
|
||||
(Formats.leanDateTime24Hour.parse input <|> Formats.leanDateTime24HourNoNanos.parse input)
|
||||
|>.map DateTime.toPlainDateTime
|
||||
|
||||
/--
|
||||
Formats a `PlainDateTime` value into a `DateTime` format string.
|
||||
-/
|
||||
def toLeanDateTimeString (pdt : PlainDateTime) : String :=
|
||||
Formats.leanDateTime24Hour.formatBuilder pdt.year pdt.month pdt.day pdt.hour pdt.minute pdt.time.second pdt.nanosecond
|
||||
|
||||
/--
|
||||
Parses a `String` in the `AscTime` or `LongDate` format and returns a `PlainDateTime`.
|
||||
Parses a `String` in the `AscTime`, `LongDate`, `DateTime`, or `LeanDateTime` format and returns a `PlainDateTime`.
|
||||
-/
|
||||
def parse (date : String) : Except String PlainDateTime :=
|
||||
fromAscTimeString date
|
||||
<|> fromLongDateFormatString date
|
||||
<|> fromDateTimeString date
|
||||
<|> fromLeanDateTimeString date
|
||||
(Formats.ascTime.parse date).map DateTime.toPlainDateTime
|
||||
<|> (Formats.longDateFormat.parse date).map DateTime.toPlainDateTime
|
||||
<|> (Formats.dateTime24Hour.parse date).map DateTime.toPlainDateTime
|
||||
<|> (Formats.leanDateTime24HourAlt.parse date).map DateTime.toPlainDateTime
|
||||
|
||||
def leanPlainDateTimeString (date : PlainDateTime) : String :=
|
||||
Formats.leanDateTime24Hour.formatBuilder date.year date.month date.day date.hour date.minute date.time.second date.nanosecond
|
||||
|
||||
instance : ToString PlainDateTime where
|
||||
toString := toLeanDateTimeString
|
||||
toString := leanPlainDateTimeString
|
||||
|
||||
instance : Repr PlainDateTime where
|
||||
reprPrec data := Repr.addAppParen ("datetime(\"" ++ toLeanDateTimeString data ++ "\")")
|
||||
reprPrec data := Repr.addAppParen ("datetime(\"" ++ leanPlainDateTimeString data ++ "\")")
|
||||
|
||||
end PlainDateTime
|
||||
|
||||
@@ -553,76 +481,22 @@ namespace DateTime
|
||||
Formats a `DateTime` using a specific format.
|
||||
-/
|
||||
def format (data: DateTime tz) (format : String) : String :=
|
||||
let format : Except String (GenericFormat .any) := GenericFormat.spec format
|
||||
let format : Except String (Format Awareness.any) := Format.spec format
|
||||
match format with
|
||||
| .error err => s!"error: {err}"
|
||||
| .ok res => res.format data
|
||||
|
||||
/--
|
||||
Parses a `String` in the `AscTime` format and returns a `DateTime` object in the GMT time zone.
|
||||
-/
|
||||
def fromAscTimeString (input : String) : Except String (DateTime .GMT) :=
|
||||
Formats.ascTime.parse input
|
||||
|
||||
/--
|
||||
Formats a `DateTime` value into an AscTime format string.
|
||||
-/
|
||||
def toAscTimeString (datetime : DateTime .GMT) : String :=
|
||||
Formats.ascTime.format datetime
|
||||
|
||||
/--
|
||||
Parses a `String` in the `LongDateFormat` and returns a `DateTime` object in the GMT time zone.
|
||||
-/
|
||||
def fromLongDateFormatString (input : String) : Except String (DateTime .GMT) :=
|
||||
Formats.longDateFormat.parse input
|
||||
|
||||
/--
|
||||
Formats a `DateTime` value into a LongDateFormat string.
|
||||
-/
|
||||
def toLongDateFormatString (datetime : DateTime .GMT) : String :=
|
||||
Formats.longDateFormat.format datetime
|
||||
|
||||
/--
|
||||
Formats a `DateTime` value into an ISO8601 string.
|
||||
-/
|
||||
def toISO8601String (date : DateTime tz) : String :=
|
||||
Formats.iso8601.format date
|
||||
|
||||
/--
|
||||
Formats a `DateTime` value into an RFC822 format string.
|
||||
-/
|
||||
def toRFC822String (date : DateTime tz) : String :=
|
||||
Formats.rfc822.format date
|
||||
|
||||
/--
|
||||
Formats a `DateTime` value into an RFC850 format string.
|
||||
-/
|
||||
def toRFC850String (date : DateTime tz) : String :=
|
||||
Formats.rfc850.format date
|
||||
|
||||
/--
|
||||
Formats a `DateTime` value into a `DateTimeWithZone` format string.
|
||||
-/
|
||||
def toDateTimeWithZoneString (pdt : DateTime tz) : String :=
|
||||
Formats.dateTimeWithZone.format pdt
|
||||
|
||||
/--
|
||||
Formats a `DateTime` value into a `DateTimeWithZone` format string that can be parsed by `date%`.
|
||||
-/
|
||||
def toLeanDateTimeWithZoneString (pdt : DateTime tz) : String :=
|
||||
Formats.leanDateTimeWithZone.format pdt
|
||||
|
||||
/--
|
||||
Parses a `String` in the `AscTime` or `LongDate` format and returns a `DateTime`.
|
||||
-/
|
||||
def parse (date : String) : Except String (DateTime .GMT) :=
|
||||
fromAscTimeString date
|
||||
<|> fromLongDateFormatString date
|
||||
Formats.ascTime.parse date
|
||||
<|> Formats.longDateFormat.parse date
|
||||
|
||||
instance : Repr (DateTime tz) where
|
||||
reprPrec data := Repr.addAppParen (toLeanDateTimeWithZoneString data)
|
||||
reprPrec data := Repr.addAppParen (Formats.leanDateTimeWithZone.format data)
|
||||
|
||||
instance : ToString (DateTime tz) where
|
||||
toString := toLeanDateTimeWithZoneString
|
||||
toString data := Formats.leanDateTimeWithZone.format data
|
||||
|
||||
end DateTime
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@ private meta def convertText : Text → MacroM (TSyntax `term)
|
||||
| .short => `(Std.Time.Text.short)
|
||||
| .full => `(Std.Time.Text.full)
|
||||
| .narrow => `(Std.Time.Text.narrow)
|
||||
| .twoLetterShort => `(Std.Time.Text.twoLetterShort)
|
||||
|
||||
private meta def convertNumber : Number → MacroM (TSyntax `term)
|
||||
| ⟨padding⟩ => `(Std.Time.Number.mk $(quote padding))
|
||||
@@ -58,26 +59,40 @@ private meta def convertOffsetZ : OffsetZ → MacroM (TSyntax `term)
|
||||
private meta def convertModifier : Modifier → MacroM (TSyntax `term)
|
||||
| .G p => do `(Std.Time.Modifier.G $(← convertText p))
|
||||
| .y p => do `(Std.Time.Modifier.y $(← convertYear p))
|
||||
| .Y p => do `(Std.Time.Modifier.Y $(← convertYear p))
|
||||
| .u p => do `(Std.Time.Modifier.u $(← convertYear p))
|
||||
| .D p => do `(Std.Time.Modifier.D $(← convertNumber p))
|
||||
| .MorL p =>
|
||||
| .M p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.MorL (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.MorL (.inr $(← convertText txt)))
|
||||
| .inl num => do `(Std.Time.Modifier.M (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.M (.inr $(← convertText txt)))
|
||||
| .L p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.L (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.L (.inr $(← convertText txt)))
|
||||
| .d p => do `(Std.Time.Modifier.d $(← convertNumber p))
|
||||
| .Qorq p =>
|
||||
| .Q p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.Qorq (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.Qorq (.inr $(← convertText txt)))
|
||||
| .inl num => do `(Std.Time.Modifier.Q (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.Q (.inr $(← convertText txt)))
|
||||
| .q p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.q (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.q (.inr $(← convertText txt)))
|
||||
| .w p => do `(Std.Time.Modifier.w $(← convertNumber p))
|
||||
| .W p => do `(Std.Time.Modifier.W $(← convertNumber p))
|
||||
| .E p => do `(Std.Time.Modifier.E $(← convertText p))
|
||||
| .eorc p =>
|
||||
| .e p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.eorc (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.eorc (.inr $(← convertText txt)))
|
||||
| .inl num => do `(Std.Time.Modifier.e (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.e (.inr $(← convertText txt)))
|
||||
| .c p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.c (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.c (.inr $(← convertText txt)))
|
||||
| .F p => do `(Std.Time.Modifier.F $(← convertNumber p))
|
||||
| .a p => do `(Std.Time.Modifier.a $(← convertText p))
|
||||
| .b p => do `(Std.Time.Modifier.b $(← convertText p))
|
||||
| .h p => do `(Std.Time.Modifier.h $(← convertNumber p))
|
||||
| .K p => do `(Std.Time.Modifier.K $(← convertNumber p))
|
||||
| .k p => do `(Std.Time.Modifier.k $(← convertNumber p))
|
||||
@@ -88,8 +103,9 @@ private meta def convertModifier : Modifier → MacroM (TSyntax `term)
|
||||
| .A p => do `(Std.Time.Modifier.A $(← convertNumber p))
|
||||
| .n p => do `(Std.Time.Modifier.n $(← convertNumber p))
|
||||
| .N p => do `(Std.Time.Modifier.N $(← convertNumber p))
|
||||
| .V => `(Std.Time.Modifier.V)
|
||||
| .V p => do `(Std.Time.Modifier.V $(← convertNumber p))
|
||||
| .z p => do `(Std.Time.Modifier.z $(← convertZoneName p))
|
||||
| .v p => do `(Std.Time.Modifier.v $(← convertZoneName p))
|
||||
| .O p => do `(Std.Time.Modifier.O $(← convertOffsetO p))
|
||||
| .X p => do `(Std.Time.Modifier.X $(← convertOffsetX p))
|
||||
| .x p => do `(Std.Time.Modifier.x $(← convertOffsetX p))
|
||||
@@ -207,33 +223,40 @@ syntax "timezone(" str ")" : term
|
||||
|
||||
macro_rules
|
||||
| `(zoned( $date:str )) => do
|
||||
match ZonedDateTime.fromLeanDateTimeWithZoneString date.getString with
|
||||
let s := date.getString
|
||||
match (Formats.leanDateTimeWithZoneAlt.parse s : Except String ZonedDateTime) with
|
||||
| .ok res => do return ← convertZonedDateTime res
|
||||
| .error _ =>
|
||||
match ZonedDateTime.fromLeanDateTimeWithIdentifierString date.getString with
|
||||
| .ok res => do return ← convertZonedDateTime res (identifier := true)
|
||||
| .error res => Macro.throwErrorAt date s!"error: {res}"
|
||||
match (Formats.leanDateTimeWithZoneAndNameAlt.parse s : Except String ZonedDateTime) with
|
||||
| .ok res => do return ← convertZonedDateTime res
|
||||
| .error _ =>
|
||||
let identParse : Except String ZonedDateTime :=
|
||||
Formats.leanDateTimeWithIdentifier.parseUnchecked s
|
||||
<|> Formats.leanDateTimeWithIdentifierAndNanos.parseUnchecked s
|
||||
match identParse with
|
||||
| .ok res => do return ← convertZonedDateTime res (identifier := true)
|
||||
| .error res => Macro.throwErrorAt date s!"error: {res}"
|
||||
|
||||
| `(zoned( $date:str, $timezone )) => do
|
||||
match PlainDateTime.fromLeanDateTimeString date.getString with
|
||||
match (Formats.leanDateTime24HourAlt.parse date.getString).map DateTime.toPlainDateTime with
|
||||
| .ok res => do
|
||||
let plain ← convertPlainDateTime res
|
||||
`(Std.Time.ZonedDateTime.ofPlainDateTime $plain $timezone)
|
||||
| .error res => Macro.throwErrorAt date s!"error: {res}"
|
||||
|
||||
| `(datetime( $date:str )) => do
|
||||
match PlainDateTime.fromLeanDateTimeString date.getString with
|
||||
match (Formats.leanDateTime24HourAlt.parse date.getString).map DateTime.toPlainDateTime with
|
||||
| .ok res => do
|
||||
return ← convertPlainDateTime res
|
||||
| .error res => Macro.throwErrorAt date s!"error: {res}"
|
||||
|
||||
| `(date( $date:str )) => do
|
||||
match PlainDate.fromSQLDateString date.getString with
|
||||
match PlainDate.parse date.getString with
|
||||
| .ok res => return ← convertPlainDate res
|
||||
| .error res => Macro.throwErrorAt date s!"error: {res}"
|
||||
|
||||
| `(time( $time:str )) => do
|
||||
match PlainTime.fromLeanTime24Hour time.getString with
|
||||
match PlainTime.parse time.getString with
|
||||
| .ok res => return ← convertPlainTime res
|
||||
| .error res => Macro.throwErrorAt time s!"error: {res}"
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ private meta def convertText : Text → MacroM (TSyntax `term)
|
||||
| .short => `(Std.Time.Text.short)
|
||||
| .full => `(Std.Time.Text.full)
|
||||
| .narrow => `(Std.Time.Text.narrow)
|
||||
| .twoLetterShort => `(Std.Time.Text.twoLetterShort)
|
||||
|
||||
private meta def convertNumber : Number → MacroM (TSyntax `term)
|
||||
| ⟨padding⟩ => `(Std.Time.Number.mk $(quote padding))
|
||||
@@ -56,26 +57,40 @@ private meta def convertOffsetZ : OffsetZ → MacroM (TSyntax `term)
|
||||
private meta def convertModifier : Modifier → MacroM (TSyntax `term)
|
||||
| .G p => do `(Std.Time.Modifier.G $(← convertText p))
|
||||
| .y p => do `(Std.Time.Modifier.y $(← convertYear p))
|
||||
| .Y p => do `(Std.Time.Modifier.Y $(← convertYear p))
|
||||
| .u p => do `(Std.Time.Modifier.u $(← convertYear p))
|
||||
| .D p => do `(Std.Time.Modifier.D $(← convertNumber p))
|
||||
| .MorL p =>
|
||||
| .M p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.MorL (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.MorL (.inr $(← convertText txt)))
|
||||
| .inl num => do `(Std.Time.Modifier.M (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.M (.inr $(← convertText txt)))
|
||||
| .L p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.L (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.L (.inr $(← convertText txt)))
|
||||
| .d p => do `(Std.Time.Modifier.d $(← convertNumber p))
|
||||
| .Qorq p =>
|
||||
| .Q p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.Qorq (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.Qorq (.inr $(← convertText txt)))
|
||||
| .inl num => do `(Std.Time.Modifier.Q (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.Q (.inr $(← convertText txt)))
|
||||
| .q p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.q (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.q (.inr $(← convertText txt)))
|
||||
| .w p => do `(Std.Time.Modifier.w $(← convertNumber p))
|
||||
| .W p => do `(Std.Time.Modifier.W $(← convertNumber p))
|
||||
| .E p => do `(Std.Time.Modifier.E $(← convertText p))
|
||||
| .eorc p =>
|
||||
| .e p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.eorc (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.eorc (.inr $(← convertText txt)))
|
||||
| .inl num => do `(Std.Time.Modifier.e (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.e (.inr $(← convertText txt)))
|
||||
| .c p =>
|
||||
match p with
|
||||
| .inl num => do `(Std.Time.Modifier.c (.inl $(← convertNumber num)))
|
||||
| .inr txt => do `(Std.Time.Modifier.c (.inr $(← convertText txt)))
|
||||
| .F p => do `(Std.Time.Modifier.F $(← convertNumber p))
|
||||
| .a p => do `(Std.Time.Modifier.a $(← convertText p))
|
||||
| .b p => do `(Std.Time.Modifier.b $(← convertText p))
|
||||
| .h p => do `(Std.Time.Modifier.h $(← convertNumber p))
|
||||
| .K p => do `(Std.Time.Modifier.K $(← convertNumber p))
|
||||
| .k p => do `(Std.Time.Modifier.k $(← convertNumber p))
|
||||
@@ -86,8 +101,9 @@ private meta def convertModifier : Modifier → MacroM (TSyntax `term)
|
||||
| .A p => do `(Std.Time.Modifier.A $(← convertNumber p))
|
||||
| .n p => do `(Std.Time.Modifier.n $(← convertNumber p))
|
||||
| .N p => do `(Std.Time.Modifier.N $(← convertNumber p))
|
||||
| .V => `(Std.Time.Modifier.V)
|
||||
| .V p => do `(Std.Time.Modifier.V $(← convertNumber p))
|
||||
| .z p => do `(Std.Time.Modifier.z $(← convertZoneName p))
|
||||
| .v p => do `(Std.Time.Modifier.v $(← convertZoneName p))
|
||||
| .O p => do `(Std.Time.Modifier.O $(← convertOffsetO p))
|
||||
| .X p => do `(Std.Time.Modifier.X $(← convertOffsetX p))
|
||||
| .x p => do `(Std.Time.Modifier.x $(← convertOffsetX p))
|
||||
@@ -109,7 +125,7 @@ syntax "datespec(" str "," term ")" : term
|
||||
|
||||
private meta def formatStringToFormat (fmt : TSyntax `str) (config : Option (TSyntax `term)) : MacroM (TSyntax `term) := do
|
||||
let input := fmt.getString
|
||||
let format : Except String (GenericFormat .any) := GenericFormat.spec input
|
||||
let format : Except String (Format .any) := Format.spec input
|
||||
match format with
|
||||
| .ok res =>
|
||||
let alts ← res.string.mapM convertFormatPart
|
||||
|
||||
@@ -410,9 +410,17 @@ def weekday (dt : DateTime tz) : Weekday :=
|
||||
/--
|
||||
Determines the era of the given `DateTime` based on its year.
|
||||
-/
|
||||
@[inline]
|
||||
def era (date : DateTime tz) : Year.Era :=
|
||||
date.year.era
|
||||
|
||||
/--
|
||||
Returns the week-based year for a given `DateTime`.
|
||||
-/
|
||||
@[inline]
|
||||
def weekBasedYear (date : DateTime tz) : Year.Offset :=
|
||||
date.date.get.weekBasedYear
|
||||
|
||||
/--
|
||||
Sets the `DateTime` to the specified `desiredWeekday`.
|
||||
-/
|
||||
|
||||
@@ -15,8 +15,7 @@ public section
|
||||
namespace Std
|
||||
namespace Time
|
||||
|
||||
-- TODO (@kim-em): re-enable this once there is a mechanism to exclude `linter.indexVariables`.
|
||||
-- set_option linter.all true
|
||||
set_option linter.all true
|
||||
|
||||
/--
|
||||
Represents a date and time with timezone information.
|
||||
@@ -153,6 +152,13 @@ Getter for the `Year` inside of a `ZonedDateTime`
|
||||
def year (zdt : ZonedDateTime) : Year.Offset :=
|
||||
zdt.date.get.year
|
||||
|
||||
/--
|
||||
Returns the week-based year for a given `ZonedDateTime`.
|
||||
-/
|
||||
@[inline]
|
||||
def weekBasedYear (zdt : ZonedDateTime) : Year.Offset :=
|
||||
zdt.date.get.weekBasedYear
|
||||
|
||||
/--
|
||||
Getter for the `Month` inside of a `ZonedDateTime`
|
||||
-/
|
||||
|
||||
@@ -45,4 +45,4 @@ example : Std.LawfulBEqOrd (DateTime TimeZone.GMT) := inferInstance
|
||||
"Sat Jan 01 02:01:01 2025",
|
||||
"Sat Jan 02 01:01:01 2025",
|
||||
"Sat Feb 01 01:01:01 2025",
|
||||
"Sat Jan 01 01:01:01 2026"].map (DateTime.fromAscTimeString . |>.toOption.get!)
|
||||
"Sat Jan 01 01:01:01 2026"].map (DateTime.parse · |>.toOption.get!)
|
||||
|
||||
@@ -629,9 +629,9 @@ Std.Time.Weekday.friday
|
||||
println! repr date.weekOfYear
|
||||
println! repr date.weekOfMonth
|
||||
|
||||
println! date.toAmericanDateString
|
||||
println! date.toLeanDateString
|
||||
println! date.toSQLDateString
|
||||
println! (date.format "MM-dd-uuuu")
|
||||
println! (date.format "uuuu-MM-dd")
|
||||
println! (date.format "uuuu-MM-dd")
|
||||
|
||||
println! date.toDaysSinceUNIXEpoch
|
||||
println! date.toTimestampAssumingUTC
|
||||
|
||||
@@ -8,7 +8,7 @@ def date₁ := zoned("2014-06-16T03:03:03-03:00")
|
||||
info: "Monday, June 16, 2014 06:03:03"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval Formats.longDateFormat.format date₁.toDateTime
|
||||
#eval Formats.longDateFormat.format date₁
|
||||
|
||||
def tm := date₁.toTimestamp
|
||||
def date₂ := DateTime.ofTimestamp tm brTZ
|
||||
@@ -134,7 +134,7 @@ info: "Mon, 16 Jun 2014 03:03:03 -0300"
|
||||
#eval Formats.rfc822.format date₂
|
||||
|
||||
/--
|
||||
info: "Mon, 16-06-2014 03:03:03 -0300"
|
||||
info: "Mon, 16-Jun-14 03:03:03 -0300"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval Formats.rfc850.format date₂
|
||||
|
||||
833
tests/elab/timeFieldSymbols.lean
Normal file
833
tests/elab/timeFieldSymbols.lean
Normal file
@@ -0,0 +1,833 @@
|
||||
import Std.Time
|
||||
open Std.Time
|
||||
|
||||
-- Reference date: Sunday, July 14, 2002 23:13:12.324354679 UTC+09:00 (Q3, week 28, day 195)
|
||||
def td := zoned("2002-07-14T23:13:12.324354679+09:00")
|
||||
|
||||
-- Same date/time at UTC (for UTC timezone name tests)
|
||||
def tdUTC := zoned("2002-07-14T23:13:12.324354679+00:00")
|
||||
|
||||
-- AM hour (09:13:12 for AM/PM tests)
|
||||
def tdAM := zoned("2002-07-14T09:13:12.000000000+09:00")
|
||||
|
||||
-- Exact noon and midnight (for day-period tests)
|
||||
def tdNoon := zoned("2002-07-14T12:00:00.000000000+09:00")
|
||||
def tdMidnight := zoned("2002-07-14T00:00:00.000000000+09:00")
|
||||
def tdWeekMonth := zoned("2002-08-05T23:13:12.324354679+09:00")
|
||||
|
||||
-- Named timezone (for z/V name tests)
|
||||
def tokyoTZ : TimeZone := { offset := { second := 32400 }, name := "Asia/Tokyo", abbreviation := "JST", isDST := false }
|
||||
|
||||
def tdNamed := ZonedDateTime.ofPlainDateTime td.toPlainDateTime (TimeZone.ZoneRules.ofTimeZone tokyoTZ)
|
||||
|
||||
-- Week-based year boundary: Dec 31, 2018 is in ISO week 1 of 2019
|
||||
def tdWeekBound := ZonedDateTime.ofPlainDateTime datetime("2018-12-31T12:00:00") (TimeZone.ZoneRules.ofTimeZone TimeZone.UTC)
|
||||
|
||||
-- Additional week-based year boundary cases
|
||||
-- Jan 1, 2017 (Sunday) → ISO week 52 of 2016
|
||||
def tdWeekBound2 := ZonedDateTime.ofPlainDateTime datetime("2017-01-01T12:00:00") (TimeZone.ZoneRules.ofTimeZone TimeZone.UTC)
|
||||
-- Jan 2, 2017 (Monday) → ISO week 1 of 2017
|
||||
def tdWeekBound3 := ZonedDateTime.ofPlainDateTime datetime("2017-01-02T12:00:00") (TimeZone.ZoneRules.ofTimeZone TimeZone.UTC)
|
||||
-- Dec 31, 2019 (Tuesday) → ISO week 1 of 2020
|
||||
def tdWeekBound4 := ZonedDateTime.ofPlainDateTime datetime("2019-12-31T12:00:00") (TimeZone.ZoneRules.ofTimeZone TimeZone.UTC)
|
||||
-- Jan 1, 2021 (Friday) → ISO week 53 of 2020
|
||||
def tdWeekBound5 := ZonedDateTime.ofPlainDateTime datetime("2021-01-01T12:00:00") (TimeZone.ZoneRules.ofTimeZone TimeZone.UTC)
|
||||
-- Jan 4, 2021 (Monday) → ISO week 1 of 2021
|
||||
def tdWeekBound6 := ZonedDateTime.ofPlainDateTime datetime("2021-01-04T12:00:00") (TimeZone.ZoneRules.ofTimeZone TimeZone.UTC)
|
||||
|
||||
-- Jan 1 (day 1) for D zero-padding tests
|
||||
def tdJan1 := zoned("2002-01-01T12:00:00.000000000+09:00")
|
||||
|
||||
-- Exact noon/midnight with sub-second nanos (b bug fix verification)
|
||||
def tdNoonNano := zoned("2002-07-14T12:00:00.000000001+09:00")
|
||||
def tdMidnightNano := zoned("2002-07-14T00:00:00.000000001+09:00")
|
||||
|
||||
-- Small fractional-second values (S truncation fix verification)
|
||||
-- 10ms = 10_000_000 ns → "010..." not "100..."
|
||||
def tdTenMs := zoned("2002-07-14T23:13:12.010000000+09:00")
|
||||
-- 1ms = 1_000_000 ns → "001..."
|
||||
def tdOneMs := zoned("2002-07-14T23:13:12.001000000+09:00")
|
||||
-- 1ns = 1 ns → "000000001"
|
||||
def tdOneNs := zoned("2002-07-14T23:13:12.000000001+09:00")
|
||||
|
||||
-- PlainTime values for b-on-PlainTime tests
|
||||
def ptNoon := time("12:00:00.000000000")
|
||||
def ptMidnight := time("00:00:00.000000000")
|
||||
def ptAM := time("09:13:12.000000000")
|
||||
def ptPM := time("23:13:12.000000000")
|
||||
def ptNoonNano := time("12:00:00.000000001")
|
||||
def ptMidnightNano := time("00:00:00.000000001")
|
||||
|
||||
-- Aligned week-of-month edge cases: Aug 1/4/5/11/12 2002
|
||||
def tdAug1 := zoned("2002-08-01T12:00:00.000000000+09:00") -- Thu, W=1
|
||||
def tdAug4 := zoned("2002-08-04T12:00:00.000000000+09:00") -- Sun, W=1
|
||||
def tdAug12 := zoned("2002-08-12T12:00:00.000000000+09:00") -- Mon, W=3
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- G Era
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "AD AD AD Anno Domini A"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "G GG GGG GGGG GGGGG"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- y Year of era
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "2002 02 2002 02002 000002002"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "y yy yyyy yyyyy yyyyyyyyy"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- Y Week-based year
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "2002 02 2002 02002 000002002"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "Y YY YYYY YYYYY YYYYYYYYY"
|
||||
|
||||
-- Boundary: Dec 31, 2018 belongs to ISO week 1 of 2019
|
||||
/--
|
||||
info: "2019 19 2019"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound.format "Y YY YYYY"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- u Extended year (signed, no era flip)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "2002 02 2002 02002 000002002"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "u uu uuuu uuuuu uuuuuuuuu"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- Q / q Quarter (Q = formatting, q = standalone — same output here)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "3 03 Q3 3rd quarter 3"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "Q QQ QQQ QQQQ QQQQQ"
|
||||
|
||||
/--
|
||||
info: "3 03 Q3 3rd quarter 3"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "q qq qqq qqqq qqqqq"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- M / L Month (M = formatting, L = standalone — same output here)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "7 07 Jul July J"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "M MM MMM MMMM MMMMM"
|
||||
|
||||
/--
|
||||
info: "7 07 Jul July J"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "L LL LLL LLLL LLLLL"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- w Week of week-based year
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "28 28"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "w ww"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- W Week of month (Monday-first)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "W"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- d Day of month
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "14 14"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "d dd"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- D Day of year
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "195 195 195"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "D DD DDD"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- F Day-of-week-in-month / occurrence within the month
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "F"
|
||||
|
||||
/--
|
||||
info: "1 1"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekMonth.format "W F"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- E Day of week (text only)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "Sun Sun Sun Sunday S"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "E EE EEE EEEE EEEEE"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- e Localized day of week (count 1-2 = numeric ordinal, 3-5 = text)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "7 07 Sun Sunday S"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "e ee eee eeee eeeee"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- c Standalone day of week (count 1 = numeric, 3-5 = text)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "7 Sun Sunday S"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "c ccc cccc ccccc"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- a AM/PM marker (counts 1-3 = short, 4 = full, 5 = narrow)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "PM"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "a"
|
||||
|
||||
/--
|
||||
info: "AM"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdAM.format "a"
|
||||
|
||||
/--
|
||||
info: "PM PM PM PM p"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "a aa aaa aaaa aaaaa"
|
||||
|
||||
/--
|
||||
info: "AM AM AM AM a"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdAM.format "a aa aaa aaaa aaaaa"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- b Day period (counts 1-3 = short, 4 = full, 5 = narrow)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "PM PM PM PM p"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "b bb bbb bbbb bbbbb"
|
||||
|
||||
/--
|
||||
info: "AM AM AM AM a"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdAM.format "b bb bbb bbbb bbbbb"
|
||||
|
||||
/--
|
||||
info: "noon noon noon noon n"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdNoon.format "b bb bbb bbbb bbbbb"
|
||||
|
||||
/--
|
||||
info: "midnight midnight midnight midnight mi"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdMidnight.format "b bb bbb bbbb bbbbb"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- H Hour of day (0-23)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "23 23"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "H HH"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- h Clock hour of AM/PM (1-12)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "11 11"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "h hh"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- K Hour of AM/PM (0-11)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "11 11"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "K KK"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- k Clock hour of day (1-24)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "23 23"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "k kk"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- m Minute
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "13 13"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "m mm"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- s Second
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "12 12"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "s ss"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- S Fractional seconds (truncated from nanoseconds)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "3 32 324 3243 324354679"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "S SS SSS SSSS SSSSSSSSS"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- A Milliseconds since midnight
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "83592324 83592324 83592324 83592324 083592324"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "A AA AAA AAAA AAAAAAAAA"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- n Nanosecond (Lean/Java extension; minimum width, no truncation)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "324354679 324354679 324354679 324354679 324354679"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "n nn nnn nnnn nnnnnnnnn"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- N Nanoseconds since midnight (Lean/Java extension; minimum width, no truncation)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "83592324354679 83592324354679 83592324354679 83592324354679 83592324354679"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "N NN NNN NNNN NNNNNNNNN"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- z Time zone name (short = abbreviation/id, full = long name)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "+09:00 +09:00 +09:00 +09:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "z zz zzz zzzz"
|
||||
|
||||
/--
|
||||
info: "UTC UTC UTC Coordinated Universal Time"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdUTC.format "z zz zzz zzzz"
|
||||
|
||||
/--
|
||||
info: "JST JST JST Asia/Tokyo"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdNamed.format "z zz zzz zzzz"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- Z Zone offset
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "+0900 +0900 +0900 GMT+09:00 +09:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "Z ZZ ZZZ ZZZZ ZZZZZ"
|
||||
|
||||
/--
|
||||
info: "+0000 +0000 +0000 GMT Z"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdUTC.format "Z ZZ ZZZ ZZZZ ZZZZZ"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- O Localized GMT offset
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "GMT+9 GMT+09:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "O OOOO"
|
||||
|
||||
/--
|
||||
info: "GMT GMT"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdUTC.format "O OOOO"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- V Zone ID (`VV` only; other widths rejected to match Java)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "+09:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "VV"
|
||||
|
||||
-- UTC offset-only zone: raw "+00:00", not normalized to "UTC"
|
||||
/--
|
||||
info: "+00:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdUTC.format "VV"
|
||||
|
||||
/--
|
||||
info: "Asia/Tokyo"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdNamed.format "VV"
|
||||
|
||||
/--
|
||||
info: "error: offset 1: invalid quantity of characters for 'V': must be 2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "V"
|
||||
|
||||
/--
|
||||
info: "error: offset 3: invalid quantity of characters for 'V': must be 2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "VVV"
|
||||
|
||||
/--
|
||||
info: "error: offset 4: invalid quantity of characters for 'V': must be 2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "VVVV"
|
||||
|
||||
/--
|
||||
info: "error: offset 3: invalid quantity of characters for 'd'"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "ddd"
|
||||
|
||||
/--
|
||||
info: "error: offset 3: invalid quantity of characters for 'w'"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "www"
|
||||
|
||||
/--
|
||||
info: "error: offset 2: invalid quantity of characters for 'W'"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "WW"
|
||||
|
||||
/--
|
||||
info: "error: offset 2: invalid quantity of characters for 'F'"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "FF"
|
||||
|
||||
/--
|
||||
info: "Su"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "EEEEEE"
|
||||
|
||||
/--
|
||||
info: "Su"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "eeeeee"
|
||||
|
||||
/--
|
||||
info: "error: offset 2: invalid quantity of characters for 'c'"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "cc"
|
||||
|
||||
/--
|
||||
info: "Su"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "cccccc"
|
||||
|
||||
/--
|
||||
info: "error: offset 6: invalid quantity of characters for 'a'"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "aaaaaa"
|
||||
|
||||
/--
|
||||
info: "error: offset 3: invalid quantity of characters for 'H'"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "HHH"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- v Generic timezone name (no DST distinction; short = abbreviation, full = name)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
-- offset-only zone: short = raw offset, full = raw offset (same as z)
|
||||
/--
|
||||
info: "+09:00 +09:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "v vvvv"
|
||||
|
||||
-- UTC offset-only: normalized to "UTC"/"Coordinated Universal Time" (same as z)
|
||||
/--
|
||||
info: "UTC Coordinated Universal Time"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdUTC.format "v vvvv"
|
||||
|
||||
-- named zone: short = abbreviation, full = IANA name
|
||||
/--
|
||||
info: "JST Asia/Tokyo"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdNamed.format "v vvvv"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- X ISO 8601 offset (uses Z for UTC)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "+09 +0900 +09:00 +0900 +09:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "X XX XXX XXXX XXXXX"
|
||||
|
||||
/--
|
||||
info: "Z Z Z Z Z"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdUTC.format "X XX XXX XXXX XXXXX"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- x ISO 8601 offset (no Z for UTC)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "+09 +0900 +09:00 +0900 +09:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval td.format "x xx xxx xxxx xxxxx"
|
||||
|
||||
/--
|
||||
info: "+00 +0000 +00:00 +0000 +00:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdUTC.format "x xx xxx xxxx xxxxx"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- Y Week-based year: extended boundary cases
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
-- Jan 1, 2017 is Sunday → belongs to ISO week 52 of 2016
|
||||
/--
|
||||
info: "2016 16 2016"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound2.format "Y YY YYYY"
|
||||
|
||||
-- Jan 2, 2017 is Monday → first day of ISO week 1 of 2017
|
||||
/--
|
||||
info: "2017 17 2017"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound3.format "Y YY YYYY"
|
||||
|
||||
-- Dec 31, 2019 is Tuesday → belongs to ISO week 1 of 2020
|
||||
/--
|
||||
info: "2020 20 2020"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound4.format "Y YY YYYY"
|
||||
|
||||
-- Jan 1, 2021 is Friday → belongs to ISO week 53 of 2020
|
||||
/--
|
||||
info: "2020 20 2020"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound5.format "Y YY YYYY"
|
||||
|
||||
-- Jan 4, 2021 is Monday → first day of ISO week 1 of 2021
|
||||
/--
|
||||
info: "2021 21 2021"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound6.format "Y YY YYYY"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- w Week of year paired with Y: check they agree at boundaries
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
-- Jan 1, 2017 → Y=2016 w=52
|
||||
/--
|
||||
info: "2016 52"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound2.format "Y w"
|
||||
|
||||
-- Jan 2, 2017 → Y=2017 w=1
|
||||
/--
|
||||
info: "2017 1"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound3.format "Y w"
|
||||
|
||||
-- Dec 31, 2019 → Y=2020 w=1
|
||||
/--
|
||||
info: "2020 1"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound4.format "Y w"
|
||||
|
||||
-- Jan 1, 2021 → Y=2020 w=53
|
||||
/--
|
||||
info: "2020 53"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound5.format "Y w"
|
||||
|
||||
-- Jan 4, 2021 → Y=2021 w=1
|
||||
/--
|
||||
info: "2021 1"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekBound6.format "Y w"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- D Day of year: zero-padding with count 1/2/3 for day 1
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "1 01 001"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdJan1.format "D DD DDD"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- W Aligned week-of-month: Java ALIGNED_WEEK_OF_MONTH = (dayOfMonth-1)/7+1
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
-- Aug 1 (Thu): (1-1)/7+1 = 1 → W=1
|
||||
/--
|
||||
info: "1"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdAug1.format "W"
|
||||
|
||||
-- Aug 4 (Sun): (4-1)/7+1 = 1 → W=1
|
||||
/--
|
||||
info: "1"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdAug4.format "W"
|
||||
|
||||
-- Aug 5 (Mon): (5-1)/7+1 = 1 → W=1
|
||||
/--
|
||||
info: "1"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdWeekMonth.format "W"
|
||||
|
||||
-- Aug 12 (Mon): (12-1)/7+1 = 2 → W=2
|
||||
/--
|
||||
info: "2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdAug12.format "W"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- h / K / k Hour edge cases: midnight (H=0) and noon (H=12)
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
-- midnight: H=0, h=12, K=0, k=24
|
||||
/--
|
||||
info: "0 12 0 24"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdMidnight.format "H h K k"
|
||||
|
||||
-- noon: H=12, h=12, K=0, k=12
|
||||
/--
|
||||
info: "12 12 0 12"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdNoon.format "H h K k"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- S Fractional seconds: truncation for values < 10^8 nanoseconds
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
-- 10ms = 10_000_000 ns → left-pad to 9 → "010000000"
|
||||
/--
|
||||
info: "0 01 010 0100 010000000"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdTenMs.format "S SS SSS SSSS SSSSSSSSS"
|
||||
|
||||
-- 1ms = 1_000_000 ns → "001000000"
|
||||
/--
|
||||
info: "0 00 001 0010 001000000"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdOneMs.format "S SS SSS SSSS SSSSSSSSS"
|
||||
|
||||
-- 1ns → "000000001"
|
||||
/--
|
||||
info: "0 00 000 0000 000000001"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdOneNs.format "S SS SSS SSSS SSSSSSSSS"
|
||||
|
||||
-- zero nanoseconds → "000000000"
|
||||
/--
|
||||
info: "0 00 000 0000 000000000"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdNoon.format "S SS SSS SSSS SSSSSSSSS"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- b Day period: nanoseconds prevent noon/midnight classification
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
-- 12:00:00.000000001 → PM, not noon (non-zero nanosecond)
|
||||
/--
|
||||
info: "PM"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdNoonNano.format "b"
|
||||
|
||||
-- 00:00:00.000000001 → AM, not midnight
|
||||
/--
|
||||
info: "AM"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval tdMidnightNano.format "b"
|
||||
|
||||
-- exact noon and midnight still work
|
||||
/--
|
||||
info: "noon midnight"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval s!"{tdNoon.format "b"} {tdMidnight.format "b"}"
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
-- b Day period on PlainTime
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/--
|
||||
info: "noon"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ptNoon.format "b"
|
||||
|
||||
/--
|
||||
info: "midnight"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ptMidnight.format "b"
|
||||
|
||||
/--
|
||||
info: "AM"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ptAM.format "b"
|
||||
|
||||
/--
|
||||
info: "PM"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ptPM.format "b"
|
||||
|
||||
-- non-zero nano at noon/midnight → falls back to AM/PM
|
||||
/--
|
||||
info: "PM"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ptNoonNano.format "b"
|
||||
|
||||
/--
|
||||
info: "AM"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ptMidnightNano.format "b"
|
||||
@@ -1,17 +1,17 @@
|
||||
import Std.Time
|
||||
open Std.Time
|
||||
|
||||
def RFC1123 : GenericFormat .any := datespec("eee, dd MMM uuuu HH:mm:ss ZZZ")
|
||||
def ShortDate : GenericFormat .any := datespec("MM/dd/uuuu")
|
||||
def LongDate : GenericFormat .any := datespec("MMMM D, uuuu")
|
||||
def ShortDateTime : GenericFormat .any := datespec("MM/dd/uuuu HH:mm:ss")
|
||||
def LongDateTime : GenericFormat .any := datespec("MMMM D, uuuu h:mm aa")
|
||||
def Time24Hour : GenericFormat .any := datespec("HH:mm:ss")
|
||||
def Time12Hour : GenericFormat .any := datespec("hh:mm:ss aa")
|
||||
def FullDayTimeZone : GenericFormat .any := datespec("EEEE, MMMM dd, uuuu HH:mm:ss ZZZ")
|
||||
def CustomDayTime : GenericFormat .any := datespec("EEE dd MMM uuuu HH:mm")
|
||||
def EraDate : GenericFormat .any := datespec("MM D, uuuu G")
|
||||
def DateSmall : GenericFormat .any := datespec("uu-MM-dd")
|
||||
def RFC1123 : Format Awareness.any := datespec("eee, dd MMM uuuu HH:mm:ss ZZZ")
|
||||
def ShortDate : Format Awareness.any := datespec("MM/dd/uuuu")
|
||||
def LongDate : Format Awareness.any := datespec("MMMM D, uuuu")
|
||||
def ShortDateTime : Format Awareness.any := datespec("MM/dd/uuuu HH:mm:ss")
|
||||
def LongDateTime : Format Awareness.any := datespec("MMMM D, uuuu h:mm a")
|
||||
def Time24Hour : Format Awareness.any := datespec("HH:mm:ss")
|
||||
def Time12Hour : Format Awareness.any := datespec("hh:mm:ss a")
|
||||
def FullDayTimeZone : Format Awareness.any := datespec("EEEE, MMMM dd, uuuu HH:mm:ss ZZZ")
|
||||
def CustomDayTime : Format Awareness.any := datespec("EEE dd MMM uuuu HH:mm")
|
||||
def EraDate : Format Awareness.any := datespec("MM D, uuuu G")
|
||||
def DateSmall : Format Awareness.any := datespec("uu-MM-dd")
|
||||
|
||||
-- Dates
|
||||
|
||||
@@ -27,7 +27,7 @@ def time₂ := time("03:11:01")
|
||||
info: "Monday, June 16, 2014 03:03:03 -0300"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval FullDayTimeZone.format date₁.toDateTime
|
||||
#eval FullDayTimeZone.format date₁
|
||||
|
||||
def tm := date₁.toTimestamp
|
||||
def date₂ := DateTime.ofTimestamp tm brTZ
|
||||
@@ -197,13 +197,13 @@ info: "03:11:01 AM"
|
||||
info: "2024-08-15T14:03:47-03:00"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval dateBR₁.toISO8601String
|
||||
#eval Formats.iso8601.format dateBR₁
|
||||
|
||||
/--
|
||||
info: "2024-08-15T14:03:47Z"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval dateUTC₁.toISO8601String
|
||||
#eval Formats.iso8601.format dateUTC₁
|
||||
|
||||
/--
|
||||
info: "06/16/2014"
|
||||
@@ -297,7 +297,7 @@ def tz : TimeZone := { offset := { second := -3600 }, name := "America/Sao_Paulo
|
||||
def zoned₆ := ZonedDateTime.ofPlainDateTime (zoned₄.toPlainDateTime) (TimeZone.ZoneRules.ofTimeZone tz)
|
||||
|
||||
/--
|
||||
info: "CE CE CE Common Era C"
|
||||
info: "AD AD AD Anno Domini A"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "G GG GGG GGGG GGGGG"
|
||||
@@ -321,10 +321,10 @@ info: "195 195 195"
|
||||
#eval zoned₄.format "D DD DDD"
|
||||
|
||||
/--
|
||||
info: "14 14 014 0014 00014"
|
||||
info: "14 14"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "d dd ddd dddd ddddd"
|
||||
#eval zoned₄.format "d dd"
|
||||
|
||||
/--
|
||||
info: "7 07 Jul July J"
|
||||
@@ -339,16 +339,16 @@ info: "3 03 3rd quarter 3"
|
||||
#eval zoned₄.format "Q QQ QQQQ QQQQQ"
|
||||
|
||||
/--
|
||||
info: "28 28 028 0028"
|
||||
info: "28 28"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "w ww www wwww"
|
||||
#eval zoned₄.format "w ww"
|
||||
|
||||
/--
|
||||
info: "2 02 002 0002"
|
||||
info: "2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "W WW WWW WWWW"
|
||||
#eval zoned₄.format "W"
|
||||
|
||||
/--
|
||||
info: "Sun Sun Sun Sunday S"
|
||||
@@ -363,46 +363,46 @@ info: "7 07 Sun Sunday S"
|
||||
#eval zoned₄.format "e ee eee eeee eeeee"
|
||||
|
||||
/--
|
||||
info: "2 02 002 0002"
|
||||
info: "2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "F FF FFF FFFF"
|
||||
#eval zoned₄.format "F"
|
||||
|
||||
/--
|
||||
info: "11 11 011 0011 0011"
|
||||
info: "11 11"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "h hh hhh hhhh hhhh"
|
||||
#eval zoned₄.format "h hh"
|
||||
|
||||
/--
|
||||
info: "11 11 011 0011 000011"
|
||||
info: "11 11"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "K KK KKK KKKK KKKKKK"
|
||||
#eval zoned₄.format "K KK"
|
||||
|
||||
/--
|
||||
info: "23 23 023 0023 000023"
|
||||
info: "23 23"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "k kk kkk kkkk kkkkkk"
|
||||
#eval zoned₄.format "k kk"
|
||||
|
||||
/--
|
||||
info: "23 23 023 0023 00023"
|
||||
info: "23 23"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "H HH HHH HHHH HHHHH"
|
||||
#eval zoned₄.format "H HH"
|
||||
|
||||
/--
|
||||
info: "13 13 013 0013 00013"
|
||||
info: "13 13"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "m mm mmm mmmm mmmmm"
|
||||
#eval zoned₄.format "m mm"
|
||||
|
||||
/--
|
||||
info: "12 12 012 0012 00012"
|
||||
info: "12 12"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₄.format "s ss sss ssss sssss"
|
||||
#eval zoned₄.format "s ss"
|
||||
|
||||
|
||||
/--
|
||||
@@ -441,7 +441,7 @@ info: "+09:00 +09:00 +09:00 +09:00"
|
||||
#eval zoned₄.format "z zz zzzz zzzz"
|
||||
|
||||
/--
|
||||
info: "+00:00 +00:00 +00:00 +00:00"
|
||||
info: "UTC UTC Coordinated Universal Time Coordinated Universal Time"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval zoned₅.format "z zz zzzz zzzz"
|
||||
@@ -483,7 +483,7 @@ info: "+0900 +0900 +0900 GMT+09:00 +09:00"
|
||||
#eval zoned₄.format "Z ZZ ZZZ ZZZZ ZZZZZ"
|
||||
|
||||
/--
|
||||
info: "CE CE CE Common Era C"
|
||||
info: "AD AD AD Anno Domini A"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "G GG GGG GGGG GGGGG"
|
||||
@@ -513,10 +513,10 @@ info: "7 07 Jul J"
|
||||
#eval datetime₄.format "M MM MMM MMMMM"
|
||||
|
||||
/--
|
||||
info: "14 14 014 0014 00014"
|
||||
info: "14 14"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "d dd ddd dddd ddddd"
|
||||
#eval datetime₄.format "d dd"
|
||||
|
||||
/--
|
||||
info: "7 07 Jul July J"
|
||||
@@ -525,9 +525,9 @@ info: "7 07 Jul July J"
|
||||
#eval datetime₄.format "M MM MMM MMMM MMMMM"
|
||||
|
||||
/--
|
||||
info: "14 14 0014 0014"
|
||||
info: "14 14"
|
||||
-/#guard_msgs in
|
||||
#eval datetime₄.format "d dd dddd dddd"
|
||||
#eval datetime₄.format "d dd"
|
||||
|
||||
/--
|
||||
info: "3 03 3rd quarter 3"
|
||||
@@ -536,16 +536,16 @@ info: "3 03 3rd quarter 3"
|
||||
#eval datetime₄.format "Q QQ QQQQ QQQQQ"
|
||||
|
||||
/--
|
||||
info: "28 28 028 0028"
|
||||
info: "28 28"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "w ww www wwww"
|
||||
#eval datetime₄.format "w ww"
|
||||
|
||||
/--
|
||||
info: "2 02 002 0002"
|
||||
info: "2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "W WW WWW WWWW"
|
||||
#eval datetime₄.format "W"
|
||||
|
||||
/--
|
||||
info: "Sun Sun Sun Sunday S"
|
||||
@@ -560,46 +560,46 @@ info: "7 07 Sun Sunday S"
|
||||
#eval datetime₄.format "e ee eee eeee eeeee"
|
||||
|
||||
/--
|
||||
info: "2 02 002 0002"
|
||||
info: "2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "F FF FFF FFFF"
|
||||
#eval datetime₄.format "F"
|
||||
|
||||
/--
|
||||
info: "11 11 011 0011 0011"
|
||||
info: "11 11"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "h hh hhh hhhh hhhh"
|
||||
#eval datetime₄.format "h hh"
|
||||
|
||||
/--
|
||||
info: "11 11 011 0011 000011"
|
||||
info: "11 11"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "K KK KKK KKKK KKKKKK"
|
||||
#eval datetime₄.format "K KK"
|
||||
|
||||
/--
|
||||
info: "23 23 023 0023 000023"
|
||||
info: "23 23"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "k kk kkk kkkk kkkkkk"
|
||||
#eval datetime₄.format "k kk"
|
||||
|
||||
/--
|
||||
info: "23 23 023 0023 00023"
|
||||
info: "23 23"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "H HH HHH HHHH HHHHH"
|
||||
#eval datetime₄.format "H HH"
|
||||
|
||||
/--
|
||||
info: "13 13 013 0013 00013"
|
||||
info: "13 13"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "m mm mmm mmmm mmmmm"
|
||||
#eval datetime₄.format "m mm"
|
||||
|
||||
/--
|
||||
info: "12 12 012 0012 00012"
|
||||
info: "12 12"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "s ss sss ssss sssss"
|
||||
#eval datetime₄.format "s ss"
|
||||
|
||||
|
||||
/--
|
||||
@@ -632,41 +632,40 @@ info: "83592324354679 83592324354679 83592324354679 83592324354679 8359232435467
|
||||
#eval datetime₄.format "N NN NNN NNNN NNNNNNNNN"
|
||||
|
||||
/--
|
||||
info: "11 11 011 0011 0011"
|
||||
info: "11 11"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval time₄.format "h hh hhh hhhh hhhh"
|
||||
#eval time₄.format "h hh"
|
||||
|
||||
/--
|
||||
info: "11 11 011 0011 000011"
|
||||
info: "11 11"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval time₄.format "K KK KKK KKKK KKKKKK"
|
||||
#eval time₄.format "K KK"
|
||||
|
||||
/--
|
||||
info: "23 23 023 0023 000023"
|
||||
|
||||
info: "23 23"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval time₄.format "k kk kkk kkkk kkkkkk"
|
||||
#eval time₄.format "k kk"
|
||||
|
||||
/--
|
||||
info: "23 23 023 0023 00023"
|
||||
info: "23 23"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval time₄.format "H HH HHH HHHH HHHHH"
|
||||
#eval time₄.format "H HH"
|
||||
|
||||
/--
|
||||
info: "13 13 013 0013 00013"
|
||||
info: "13 13"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval time₄.format "m mm mmm mmmm mmmmm"
|
||||
#eval time₄.format "m mm"
|
||||
|
||||
/--
|
||||
info: "12 12 012 0012 00012"
|
||||
info: "12 12"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval time₄.format "s ss sss ssss sssss"
|
||||
#eval time₄.format "s ss"
|
||||
|
||||
|
||||
/--
|
||||
@@ -699,7 +698,7 @@ info: "83592324354679 83592324354679 83592324354679 83592324354679 8359232435467
|
||||
#eval time₄.format "N NN NNN NNNN NNNNNNNNN"
|
||||
|
||||
/--
|
||||
info: "CE CE CE Common Era C"
|
||||
info: "AD AD AD Anno Domini A"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval date₄.format "G GG GGG GGGG GGGGG"
|
||||
@@ -729,10 +728,10 @@ info: "7 07 Jul J"
|
||||
#eval date₄.format "M MM MMM MMMMM"
|
||||
|
||||
/--
|
||||
info: "14 14 014 0014 00014"
|
||||
info: "14 14"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval date₄.format "d dd ddd dddd ddddd"
|
||||
#eval date₄.format "d dd"
|
||||
|
||||
/--
|
||||
info: "7 07 Jul July J"
|
||||
@@ -741,9 +740,9 @@ info: "7 07 Jul July J"
|
||||
#eval date₄.format "M MM MMM MMMM MMMMM"
|
||||
|
||||
/--
|
||||
info: "14 14 0014 0014"
|
||||
info: "14 14"
|
||||
-/#guard_msgs in
|
||||
#eval date₄.format "d dd dddd dddd"
|
||||
#eval date₄.format "d dd"
|
||||
|
||||
/--
|
||||
info: "3 03 3rd quarter 3"
|
||||
@@ -752,16 +751,16 @@ info: "3 03 3rd quarter 3"
|
||||
#eval date₄.format "Q QQ QQQQ QQQQQ"
|
||||
|
||||
/--
|
||||
info: "28 28 028 0028"
|
||||
info: "28 28"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval date₄.format "w ww www wwww"
|
||||
#eval date₄.format "w ww"
|
||||
|
||||
/--
|
||||
info: "2 02 002 0002"
|
||||
info: "2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval date₄.format "W WW WWW WWWW"
|
||||
#eval date₄.format "W"
|
||||
|
||||
/--
|
||||
info: "Sun Sun Sun Sunday S"
|
||||
@@ -776,19 +775,19 @@ info: "7 07 Sun Sunday S"
|
||||
#eval date₄.format "e ee eee eeee eeeee"
|
||||
|
||||
/--
|
||||
info: "2 02 002 0002"
|
||||
info: "2"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval date₄.format "F FF FFF FFFF"
|
||||
#eval date₄.format "F"
|
||||
|
||||
/--
|
||||
info: "-2000 2001 BCE"
|
||||
info: "-2000 2001 BC"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₅.format "uuuu yyyy G"
|
||||
|
||||
/--
|
||||
info: "2002 2002 CE"
|
||||
info: "2002 2002 AD"
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval datetime₄.format "uuuu yyyy G"
|
||||
@@ -825,7 +824,7 @@ info: ("19343232432-01-04T01:04:03.000000000",
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let r := PlainDateTime.mk (PlainDate.ofYearMonthDayClip 19343232432 1 4) (PlainTime.mk 25 64 3 0)
|
||||
let s := r.toLeanDateTimeString
|
||||
let s := r.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS"
|
||||
let r := PlainDateTime.parse s
|
||||
(s, r, datetime("1932-01-02T05:04:03.000000000"))
|
||||
|
||||
@@ -840,7 +839,7 @@ def tuple6Mk (a : f) (b : g) (c : h) (d : i) (e : j) (k : z) := some (a, b, c, d
|
||||
Parsing Length Tests
|
||||
-/
|
||||
|
||||
def uFormat : GenericFormat .any := datespec("u uu uuuu uuuuu")
|
||||
def uFormat : Format Awareness.any := datespec("u uu uuuu uuuuu")
|
||||
|
||||
#eval do assert! (uFormat.parseBuilder tuple4Mk "1 11 1211 12311" |>.isOk)
|
||||
#eval do assert! (uFormat.parseBuilder tuple4Mk "12 11 1211 12311" |>.isOk)
|
||||
@@ -855,7 +854,7 @@ def uFormat : GenericFormat .any := datespec("u uu uuuu uuuuu")
|
||||
#eval do assert! (not <| uFormat.parseBuilder tuple4Mk "1 11 1213 111123" |>.isOk)
|
||||
#eval do assert! (not <| uFormat.parseBuilder tuple4Mk "1 367 1211 12311" |>.isOk)
|
||||
|
||||
def yFormat : GenericFormat .any := datespec("y yy yyyy yyyyy")
|
||||
def yFormat : Format Awareness.any := datespec("y yy yyyy yyyyy")
|
||||
|
||||
#eval do assert! (yFormat.parseBuilder tuple4Mk "1 11 1211 12311" |>.isOk)
|
||||
#eval do assert! (yFormat.parseBuilder tuple4Mk "12 11 1211 12311" |>.isOk)
|
||||
@@ -870,7 +869,7 @@ def yFormat : GenericFormat .any := datespec("y yy yyyy yyyyy")
|
||||
#eval do assert! (not <| yFormat.parseBuilder tuple4Mk "1 11 1213 111123" |>.isOk)
|
||||
#eval do assert! (not <| yFormat.parseBuilder tuple4Mk "1 367 1211 12311" |>.isOk)
|
||||
|
||||
def dFormat : GenericFormat .any := datespec("D DD DDD")
|
||||
def dFormat : Format Awareness.any := datespec("D DD DDD")
|
||||
|
||||
#eval do assert! (dFormat.parseBuilder tuple3Mk "1 12 123" |>.isOk)
|
||||
#eval do assert! (dFormat.parseBuilder tuple3Mk "323 12 123" |>.isOk)
|
||||
@@ -879,23 +878,23 @@ def dFormat : GenericFormat .any := datespec("D DD DDD")
|
||||
#eval do assert! (not <| dFormat.parseBuilder tuple3Mk "1 123 123" |>.isOk)
|
||||
#eval do assert! (not <| dFormat.parseBuilder tuple3Mk "367 12 123" |>.isOk)
|
||||
|
||||
def dddFormat : GenericFormat .any := datespec("d dd ddd dddd ddddd")
|
||||
def dayOfMonthFormat : Format Awareness.any := datespec("d dd")
|
||||
|
||||
#eval do assert! (dddFormat.parseBuilder tuple5Mk "1 12 031 0031 00031" |>.isOk)
|
||||
#eval do assert! (dddFormat.parseBuilder tuple5Mk "000031 12 031 0031 00031" |>.isOk)
|
||||
#eval do assert! (dayOfMonthFormat.parseBuilder tuple2Mk "1 12" |>.isOk)
|
||||
#eval do assert! (dayOfMonthFormat.parseBuilder tuple2Mk "31 31" |>.isOk)
|
||||
|
||||
#eval do assert! (not <| dddFormat.parseBuilder tuple5Mk "1 12 0031 00031" |>.isOk)
|
||||
#eval do assert! (not <| dddFormat.parseBuilder tuple5Mk "1 031 0031 000031" |>.isOk)
|
||||
#eval do assert! (not <| dayOfMonthFormat.parseBuilder tuple2Mk "1 123" |>.isOk)
|
||||
#eval do assert! (not <| dayOfMonthFormat.parseBuilder tuple2Mk "32 31" |>.isOk)
|
||||
|
||||
def wFormat : GenericFormat .any := datespec("w ww www wwww")
|
||||
def wFormat : Format Awareness.any := datespec("w ww")
|
||||
|
||||
#eval do assert! (wFormat.parseBuilder tuple4Mk "1 01 031 0031" |>.isOk)
|
||||
#eval do assert! (wFormat.parseBuilder tuple4Mk "2 01 031 0031" |>.isOk)
|
||||
#eval do assert! (wFormat.parseBuilder tuple2Mk "1 01" |>.isOk)
|
||||
#eval do assert! (wFormat.parseBuilder tuple2Mk "2 01" |>.isOk)
|
||||
|
||||
#eval do assert! (not <| wFormat.parseBuilder tuple4Mk "2 01 031 00310" |>.isOk)
|
||||
#eval do assert! (not <| wFormat.parseBuilder tuple4Mk "2 01 031 031" |>.isOk)
|
||||
#eval do assert! (not <| wFormat.parseBuilder tuple2Mk "2 031" |>.isOk)
|
||||
#eval do assert! (not <| wFormat.parseBuilder tuple2Mk "54 01" |>.isOk)
|
||||
|
||||
def qFormat : GenericFormat .any := datespec("q qq")
|
||||
def qFormat : Format Awareness.any := datespec("q qq")
|
||||
|
||||
#eval do assert! (qFormat.parseBuilder tuple2Mk "1 02" |>.isOk)
|
||||
#eval do assert! (qFormat.parseBuilder tuple2Mk "3 03" |>.isOk)
|
||||
@@ -903,15 +902,14 @@ def qFormat : GenericFormat .any := datespec("q qq")
|
||||
#eval do assert! (not <| qFormat.parseBuilder tuple2Mk "12 32" |>.isOk)
|
||||
#eval do assert! (not <| qFormat.parseBuilder tuple2Mk "000001 003" |>.isOk)
|
||||
|
||||
def WFormat : GenericFormat .any := datespec("W WW")
|
||||
def WFormat : Format Awareness.any := datespec("W")
|
||||
|
||||
#eval do assert! (WFormat.parseBuilder tuple2Mk "1 06" |>.isOk)
|
||||
#eval do assert! (WFormat.parseBuilder tuple2Mk "3 03" |>.isOk)
|
||||
#eval do assert! (WFormat.parseBuilder some "1" |>.isOk)
|
||||
#eval do assert! (WFormat.parseBuilder some "3" |>.isOk)
|
||||
|
||||
#eval do assert! (not <| WFormat.parseBuilder tuple2Mk "12 32" |>.isOk)
|
||||
#eval do assert! (not <| WFormat.parseBuilder tuple2Mk "000001 003" |>.isOk)
|
||||
#eval do assert! (not <| WFormat.parseBuilder some "12" |>.isOk)
|
||||
|
||||
def eFormat : GenericFormat .any := datespec("e ee")
|
||||
def eFormat : Format Awareness.any := datespec("e ee")
|
||||
|
||||
#eval do assert! (eFormat.parseBuilder tuple2Mk "1 07" |>.isOk)
|
||||
#eval do assert! (eFormat.parseBuilder tuple2Mk "3 03" |>.isOk)
|
||||
@@ -919,15 +917,15 @@ def eFormat : GenericFormat .any := datespec("e ee")
|
||||
#eval do assert! (not <| eFormat.parseBuilder tuple2Mk "12 32" |>.isOk)
|
||||
#eval do assert! (not <| eFormat.parseBuilder tuple2Mk "000001 003" |>.isOk)
|
||||
|
||||
def FFormat : GenericFormat .any := datespec("F FF")
|
||||
def FFormat : Format Awareness.any := datespec("F")
|
||||
|
||||
#eval do assert! (FFormat.parseBuilder tuple2Mk "1 04" |>.isOk)
|
||||
#eval do assert! (FFormat.parseBuilder tuple2Mk "3 03" |>.isOk)
|
||||
#eval do assert! (FFormat.parseBuilder some "1" |>.isOk)
|
||||
#eval do assert! (FFormat.parseBuilder some "3" |>.isOk)
|
||||
|
||||
#eval do assert! (not <| FFormat.parseBuilder tuple2Mk "12 32" |>.isOk)
|
||||
#eval do assert! (not <| FFormat.parseBuilder tuple2Mk "000001 003" |>.isOk)
|
||||
#eval do assert! (not <| FFormat.parseBuilder some "12" |>.isOk)
|
||||
#eval do assert! (not <| FFormat.parseBuilder some "6" |>.isOk)
|
||||
|
||||
def hFormat : GenericFormat .any := datespec("h hh")
|
||||
def hFormat : Format Awareness.any := datespec("h hh")
|
||||
|
||||
#eval do assert! (hFormat.parseBuilder tuple2Mk "1 09" |>.isOk)
|
||||
#eval do assert! (hFormat.parseBuilder tuple2Mk "12 12" |>.isOk)
|
||||
@@ -949,16 +947,16 @@ info: zoned("2002-07-14T14:13:12.000000000+23:59")
|
||||
info: Except.error "offset 22: invalid hour offset: 24. Must be between 0 and 23."
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ZonedDateTime.fromLeanDateTimeWithZoneString "2002-07-14T14:13:12+24:59"
|
||||
#eval Formats.leanDateTimeWithZoneAlt.parse "2002-07-14T14:13:12+24:59"
|
||||
|
||||
/--
|
||||
info: Except.error "offset 25: invalid minute offset: 60. Must be between 0 and 59."
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ZonedDateTime.fromLeanDateTimeWithZoneString "2002-07-14T14:13:12+23:60"
|
||||
#eval Formats.leanDateTimeWithZoneAlt.parse "2002-07-14T14:13:12+23:60"
|
||||
|
||||
/--
|
||||
info: Except.ok (zoned("2002-07-14T14:13:12.000000000Z"))
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ZonedDateTime.fromLeanDateTimeWithZoneString "2002-07-14T14:13:12+00:00"
|
||||
#eval Formats.leanDateTimeWithZoneAlt.parse "2002-07-14T14:13:12+00:00"
|
||||
|
||||
@@ -40,9 +40,9 @@ info: 2013-10-19T23:59:59.000000000-03:00
|
||||
#guard_msgs in
|
||||
#eval do
|
||||
let zr ← Database.defaultGetZoneRules "America/Sao_Paulo"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2013-10-19T23:59:59") zr |>.toLeanDateTimeWithZoneString}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2013-10-20T00:00:00") zr |>.toLeanDateTimeWithZoneString}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2013-10-20T00:00:01") zr |>.toLeanDateTimeWithZoneString}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2013-10-19T23:59:59") zr |>.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2013-10-20T00:00:00") zr |>.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2013-10-20T00:00:01") zr |>.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"}"
|
||||
|
||||
/-
|
||||
Java:
|
||||
@@ -59,9 +59,9 @@ info: 2019-11-03T01:59:59.000000000-05:00
|
||||
#guard_msgs in
|
||||
#eval do
|
||||
let zr ← Database.defaultGetZoneRules "America/Chicago"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2019-11-03T01:59:59") zr |>.toLeanDateTimeWithZoneString}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2019-11-03T02:00:00") zr |>.toLeanDateTimeWithZoneString}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2019-11-03T02:59:59") zr |>.toLeanDateTimeWithZoneString}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2019-11-03T01:59:59") zr |>.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2019-11-03T02:00:00") zr |>.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2019-11-03T02:59:59") zr |>.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"}"
|
||||
|
||||
/-
|
||||
Java:
|
||||
@@ -78,6 +78,6 @@ info: 2003-10-26T01:59:59.000000000-05:00
|
||||
#guard_msgs in
|
||||
#eval do
|
||||
let zr ← Database.defaultGetZoneRules "America/Monterrey"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2003-10-26T01:59:59") zr |>.toLeanDateTimeWithZoneString}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2003-10-26T02:00:00") zr |>.toLeanDateTimeWithZoneString}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2003-10-26T02:59:59") zr |>.toLeanDateTimeWithZoneString}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2003-10-26T01:59:59") zr |>.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2003-10-26T02:00:00") zr |>.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"}"
|
||||
println! "{ZonedDateTime.ofPlainDateTime datetime("2003-10-26T02:59:59") zr |>.format "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZZZZZ"}"
|
||||
|
||||
@@ -2,9 +2,9 @@ import Std.Time
|
||||
open Std.Time
|
||||
|
||||
|
||||
def ISO8601UTCAllow : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZ", { allowLeapSeconds := true })
|
||||
def ISO8601UTCNot : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZ", { allowLeapSeconds := false })
|
||||
def ISO8601UTCDef : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZ")
|
||||
def ISO8601UTCAllow : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZ", { allowLeapSeconds := true })
|
||||
def ISO8601UTCNot : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZ", { allowLeapSeconds := false })
|
||||
def ISO8601UTCDef : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZ")
|
||||
|
||||
/--
|
||||
info: Except.ok (zoned("2002-07-14T23:14:00.324354679-23:59"))
|
||||
|
||||
@@ -2,8 +2,8 @@ import Std.Time
|
||||
import Init
|
||||
open Std.Time
|
||||
|
||||
def ShortDateTime : GenericFormat .any := datespec("dd/MM/uuuu HH:mm:ss")
|
||||
def ShortDate : GenericFormat .any := datespec("dd/MM/uuuu")
|
||||
def ShortDateTime : Format Awareness.any := datespec("dd/MM/uuuu HH:mm:ss")
|
||||
def ShortDate : Format Awareness.any := datespec("dd/MM/uuuu")
|
||||
|
||||
def format (PlainDate : PlainDateTime) : String := ShortDateTime.formatBuilder PlainDate.day PlainDate.month PlainDate.year PlainDate.time.hour PlainDate.minute PlainDate.time.second
|
||||
def format₂ (PlainDate : PlainDate) : String := ShortDate.formatBuilder PlainDate.day PlainDate.month PlainDate.year
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import Std.Time
|
||||
open Std.Time
|
||||
|
||||
def ISO8601UTC : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX")
|
||||
def RFC1123 : GenericFormat .any := datespec("eee, dd MMM uuuu HH:mm:ss ZZZ")
|
||||
def ShortDate : GenericFormat .any := datespec("MM/dd/uuuu")
|
||||
def LongDate : GenericFormat .any := datespec("MMMM D, uuuu")
|
||||
def ShortDateTime : GenericFormat .any := datespec("MM/dd/uuuu HH:mm:ss")
|
||||
def LongDateTime : GenericFormat .any := datespec("MMMM dd, uuuu hh:mm aa")
|
||||
def Time24Hour : GenericFormat .any := datespec("HH:mm:ss")
|
||||
def Time12Hour : GenericFormat .any := datespec("hh:mm:ss aa")
|
||||
def FullDayTimeZone : GenericFormat .any := datespec("EEEE, MMMM dd, uuuu HH:mm:ss ZZZ")
|
||||
def CustomDayTime : GenericFormat .any := datespec("EEE dd MMM uuuu HH:mm")
|
||||
def ISO8601UTC : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX")
|
||||
def RFC1123 : Format Awareness.any := datespec("eee, dd MMM uuuu HH:mm:ss ZZZ")
|
||||
def ShortDate : Format Awareness.any := datespec("MM/dd/uuuu")
|
||||
def LongDate : Format Awareness.any := datespec("MMMM D, uuuu")
|
||||
def ShortDateTime : Format Awareness.any := datespec("MM/dd/uuuu HH:mm:ss")
|
||||
def LongDateTime : Format Awareness.any := datespec("MMMM dd, uuuu hh:mm a")
|
||||
def Time24Hour : Format Awareness.any := datespec("HH:mm:ss")
|
||||
def Time12Hour : Format Awareness.any := datespec("hh:mm:ss a")
|
||||
def FullDayTimeZone : Format Awareness.any := datespec("EEEE, MMMM dd, uuuu HH:mm:ss ZZZ")
|
||||
def CustomDayTime : Format Awareness.any := datespec("EEE dd MMM uuuu HH:mm")
|
||||
|
||||
def Full12HourWrong : GenericFormat .any := datespec("MM/dd/uuuu hh:mm:ss aa XXX")
|
||||
def Full12HourWrong : Format Awareness.any := datespec("MM/dd/uuuu hh:mm:ss a XXX")
|
||||
|
||||
-- Dates
|
||||
|
||||
@@ -30,7 +30,7 @@ info: "2014-06-16T03:03:03.000000100-03:00"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t : ZonedDateTime := ISO8601UTC.parse! "2014-06-16T03:03:03.000000100-03:00"
|
||||
ISO8601UTC.format t.toDateTime
|
||||
ISO8601UTC.format t
|
||||
|
||||
def tm := date₁.toTimestamp
|
||||
def date₂ := DateTime.ofTimestamp tm brTZ
|
||||
@@ -41,7 +41,7 @@ info: "2014-06-16T03:03:03.000000000-03:00"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t : ZonedDateTime := RFC1123.parse! "Mon, 16 Jun 2014 03:03:03 -0300"
|
||||
ISO8601UTC.format t.toDateTime
|
||||
ISO8601UTC.format t
|
||||
|
||||
def tm₃ := date₁.toTimestamp
|
||||
def date₃ := DateTime.ofTimestamp tm₃ brTZ
|
||||
@@ -52,7 +52,7 @@ info: "2014-06-16T00:00:00.000000000Z"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t : ZonedDateTime := ShortDate.parse! "06/16/2014"
|
||||
ISO8601UTC.format t.toDateTime
|
||||
ISO8601UTC.format t
|
||||
|
||||
-- the timestamp is always related to UTC.
|
||||
|
||||
@@ -73,7 +73,7 @@ info: "2024-08-15T13:28:12.000000000-03:00"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t := FullDayTimeZone.parse! "Thursday, August 15, 2024 13:28:12 -0300"
|
||||
ISO8601UTC.format t.toDateTime
|
||||
ISO8601UTC.format t
|
||||
|
||||
/--
|
||||
info: "2024-08-16T01:28:00.000000000Z"
|
||||
@@ -81,7 +81,7 @@ info: "2024-08-16T01:28:00.000000000Z"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t : ZonedDateTime := LongDateTime.parse! "August 16, 2024 01:28 AM"
|
||||
ISO8601UTC.format t.toDateTime
|
||||
ISO8601UTC.format t
|
||||
|
||||
/--
|
||||
info: "0000-12-31T22:28:12.000000000+09:00"
|
||||
@@ -105,7 +105,7 @@ info: "Thu 15 Aug 2024 16:28"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t2 : ZonedDateTime := FullDayTimeZone.parse! "Thursday, August 15, 2024 16:28:12 -0000"
|
||||
CustomDayTime.format t2.toDateTime
|
||||
CustomDayTime.format t2
|
||||
|
||||
/--
|
||||
info: "2024-08-16T13:28:00.000000000Z"
|
||||
@@ -113,7 +113,7 @@ info: "2024-08-16T13:28:00.000000000Z"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t5 : ZonedDateTime := CustomDayTime.parse! "Thu 16 Aug 2024 13:28"
|
||||
ISO8601UTC.format t5.toDateTime
|
||||
ISO8601UTC.format t5
|
||||
|
||||
/--
|
||||
info: "2024-08-16T01:28:12.000000000+09:00"
|
||||
@@ -153,7 +153,7 @@ info: "2024-08-15T14:03:47.000000000-03:00"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t : ZonedDateTime := FullDayTimeZone.parse! "Thursday, August 15, 2024 14:03:47 -0300"
|
||||
ISO8601UTC.format t.toDateTime
|
||||
ISO8601UTC.format t
|
||||
|
||||
/--
|
||||
info: "2024-08-15T14:03:47.000000000+09:00"
|
||||
@@ -161,7 +161,7 @@ info: "2024-08-15T14:03:47.000000000+09:00"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t1 : ZonedDateTime := FullDayTimeZone.parse! "Thursday, August 15, 2024 14:03:47 +0900"
|
||||
ISO8601UTC.format t1.toDateTime
|
||||
ISO8601UTC.format t1
|
||||
|
||||
/--
|
||||
info: "2014-06-16T03:03:03.000000000-03:00"
|
||||
@@ -169,7 +169,7 @@ info: "2014-06-16T03:03:03.000000000-03:00"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t2 : ZonedDateTime := FullDayTimeZone.parse! "Monday, June 16, 2014 03:03:03 -0300"
|
||||
ISO8601UTC.format t2.toDateTime
|
||||
ISO8601UTC.format t2
|
||||
|
||||
/--
|
||||
info: Except.ok "1993-05-10T10:30:23.000000000+03:00"
|
||||
@@ -177,7 +177,7 @@ info: Except.ok "1993-05-10T10:30:23.000000000+03:00"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t2 := Full12HourWrong.parse "05/10/1993 10:30:23 AM +03:00"
|
||||
(ISO8601UTC.format ·.toDateTime) <$> t2
|
||||
(ISO8601UTC.format ·) <$> t2
|
||||
|
||||
/--
|
||||
info: Except.ok "1993-05-10T22:30:23.000000000+03:00"
|
||||
@@ -185,7 +185,7 @@ info: Except.ok "1993-05-10T22:30:23.000000000+03:00"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t2 := Full12HourWrong.parse "05/10/1993 10:30:23 PM +03:00"
|
||||
(ISO8601UTC.format ·.toDateTime) <$> t2
|
||||
(ISO8601UTC.format ·) <$> t2
|
||||
|
||||
/--
|
||||
info: Except.error "offset 13: need a natural number in the interval of 1 to 12"
|
||||
@@ -193,7 +193,7 @@ info: Except.error "offset 13: need a natural number in the interval of 1 to 12"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t2 := Full12HourWrong.parse "05/10/1993 20:30:23 AM +03:00"
|
||||
(ISO8601UTC.format ·.toDateTime) <$> t2
|
||||
(ISO8601UTC.format ·) <$> t2
|
||||
|
||||
/--
|
||||
info: Except.error "offset 13: need a natural number in the interval of 1 to 12"
|
||||
@@ -201,4 +201,4 @@ info: Except.error "offset 13: need a natural number in the interval of 1 to 12"
|
||||
#guard_msgs in
|
||||
#eval
|
||||
let t2 := Full12HourWrong.parse "05/10/1993 20:30:23 PM +03:00"
|
||||
(ISO8601UTC.format ·.toDateTime) <$> t2
|
||||
(ISO8601UTC.format ·) <$> t2
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import Std.Time
|
||||
open Std.Time
|
||||
|
||||
def ISO8601UTC : GenericFormat .any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX")
|
||||
def RFC1123 : GenericFormat .any := datespec("eee, dd MMM uuuu HH:mm:ss ZZZ")
|
||||
def ShortDate : GenericFormat .any := datespec("MM/dd/uuuu")
|
||||
def LongDate : GenericFormat .any := datespec("MMMM D, uuuu")
|
||||
def ShortDateTime : GenericFormat .any := datespec("MM/dd/uuuu HH:mm:ss")
|
||||
def LongDateTime : GenericFormat .any := datespec("MMMM dd, uuuu hh:mm aa")
|
||||
def Time24Hour : GenericFormat .any := datespec("HH:mm:ss")
|
||||
def Time12Hour : GenericFormat .any := datespec("hh:mm:ss aa")
|
||||
def FullDayTimeZone : GenericFormat .any := datespec("EEEE, MMMM dd, uuuu HH:mm:ss ZZZ")
|
||||
def CustomDayTime : GenericFormat .any := datespec("EEE dd MMM uuuu HH:mm")
|
||||
def ISO8601UTC : Format Awareness.any := datespec("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX")
|
||||
def RFC1123 : Format Awareness.any := datespec("eee, dd MMM uuuu HH:mm:ss ZZZ")
|
||||
def ShortDate : Format Awareness.any := datespec("MM/dd/uuuu")
|
||||
def LongDate : Format Awareness.any := datespec("MMMM D, uuuu")
|
||||
def ShortDateTime : Format Awareness.any := datespec("MM/dd/uuuu HH:mm:ss")
|
||||
def LongDateTime : Format Awareness.any := datespec("MMMM dd, uuuu hh:mm a")
|
||||
def Time24Hour : Format Awareness.any := datespec("HH:mm:ss")
|
||||
def Time12Hour : Format Awareness.any := datespec("hh:mm:ss a")
|
||||
def FullDayTimeZone : Format Awareness.any := datespec("EEEE, MMMM dd, uuuu HH:mm:ss ZZZ")
|
||||
def CustomDayTime : Format Awareness.any := datespec("EEE dd MMM uuuu HH:mm")
|
||||
|
||||
def Full12HourWrong : GenericFormat .any := datespec("MM/dd/uuuu hh:mm:ss aa XXX")
|
||||
def Full12HourWrong : Format Awareness.any := datespec("MM/dd/uuuu hh:mm:ss a XXX")
|
||||
|
||||
-- Dates
|
||||
|
||||
|
||||
@@ -98,13 +98,13 @@ info: 0
|
||||
#eval code.v1.utLocalIndicators.size
|
||||
|
||||
/--
|
||||
info: zoned("1969-12-31T21:00:00.000000000-03:00")
|
||||
info: zoned("1969-12-31T21:00:00.000000000-03:00[America/Sao_Paulo]")
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ZonedDateTime.ofTimestamp (Timestamp.ofSecondsSinceUnixEpoch 0) rules
|
||||
|
||||
/--
|
||||
info: zoned("2012-12-10T00:35:47.000000000-02:00")
|
||||
info: zoned("2012-12-10T00:35:47.000000000-02:00[America/Sao_Paulo]")
|
||||
-/
|
||||
#guard_msgs in
|
||||
#eval ZonedDateTime.ofTimestamp (Timestamp.ofSecondsSinceUnixEpoch 1355106947) rules
|
||||
|
||||
@@ -241,6 +241,7 @@ error: Unknown constant `b`
|
||||
|
||||
Hint: Insert a fully-qualified name:
|
||||
• {name ̲(̲f̲u̲l̲l̲ ̲:̲=̲ ̲A̲.̲b̲)̲}`b`
|
||||
• {name ̲(̲f̲u̲l̲l̲ ̲:̲=̲ ̲S̲t̲d̲.̲T̲i̲m̲e̲.̲M̲o̲d̲i̲f̲i̲e̲r̲.̲b̲)̲}`b`
|
||||
• {name ̲(̲f̲u̲l̲l̲ ̲:̲=̲ ̲M̲e̲t̲a̲.̲G̲r̲i̲n̲d̲.̲A̲r̲i̲t̲h̲.̲C̲u̲t̲s̲a̲t̲.̲D̲v̲d̲S̲o̲l̲u̲t̲i̲o̲n̲.̲b̲)̲}`b`
|
||||
-/
|
||||
#guard_msgs in
|
||||
|
||||
@@ -5,7 +5,7 @@ Nat.gcd.induction' {P : Nat → Nat → Prop} (m n : Nat) (H0 : ∀ (n : Nat), P
|
||||
(H1 : ∀ (m n : Nat), 0 < m → P (n % m) m → P m n) : P m n
|
||||
something : Unit
|
||||
yetMore' : Unit
|
||||
versoDocs.lean:631:43-631:53: warning: Code element could be more specific.
|
||||
versoDocs.lean:632:43-632:53: warning: Code element could be more specific.
|
||||
|
||||
Hint: Insert a role to document it:
|
||||
• {̲l̲e̲a̲n̲}̲`-checked`
|
||||
|
||||
Reference in New Issue
Block a user