diff --git a/docs/datetime.md b/docs/datetime.md index e62a8a2..1cbc324 100644 --- a/docs/datetime.md +++ b/docs/datetime.md @@ -16,7 +16,7 @@ preferred representation of the DateTime in the current time zone: ```tomo >> DateTime.now() -= Sun Sep 29 18:20:12 2024 += Sun Sep 29 18:20:12 2024 EDT ``` For various methods, it is assumed by default that users wish to perform @@ -71,7 +71,7 @@ A new `DateTime` offset by the given amount. **Example:** ```markdown >> DateTime(2024, 9, 29, hour=19):after(days=1, minutes=30) -= Mon Sep 30 19:30:00 2024 += Mon Sep 30 19:30:00 2024 EDT ``` --- @@ -111,7 +111,7 @@ options, return a text representation of the given date in the given format. If **Usage:** ```markdown -datetime:format(format: Text = "%c", local_time : Bool = yes) -> Text +datetime:format(format: Text = "%c %Z", local_time : Bool = yes) -> Text ``` **Parameters:** @@ -278,11 +278,11 @@ integer, an error will be raised. **Example:** ```markdown >> DateTime.new(2024, 9, 29) -= Mon Sep 30 00:00:00 2024 += Mon Sep 30 00:00:00 2024 EDT # March 1642, 2020: >> DateTime(2020, 4, 1643) -= Sat Sep 28 00:00:00 2024 += Sat Sep 28 00:00:00 2024 EDT ``` --- @@ -308,7 +308,7 @@ Returns a `DateTime` object representing the current date and time. **Example:** ```markdown >> DateTime.now() -= Sun Sep 29 20:22:48 2024 += Sun Sep 29 20:22:48 2024 EDT ``` --- @@ -321,14 +321,14 @@ or a null value if the value could not be successfully parsed. **Usage:** ```markdown -DateTime.parse(text: Text, format: Text = "%c") -> DateTime? +DateTime.parse(text: Text, format: Text = "%Y-%m-%dT%H:%M:%S. %f%z") -> DateTime? ``` **Parameters:** - `text`: The text to parse. - `format`: The date format of the text being parsed (see: - [strptime](https://linux.die.net/man/3/strptime) for more info on this format) (default: `"%c"`). + [strptime](https://linux.die.net/man/3/strptime) for more info on this format) (default: `"%c %Z"`). **Returns:** If the text was successfully parsed according to the given format, return a @@ -337,7 +337,7 @@ If the text was successfully parsed according to the given format, return a **Example:** ```markdown >> DateTime.parse("2024-09-29", "%Y-%m-%d")! -= Sun Sep 29 00:00:00 2024 += Sun Sep 29 00:00:00 2024 EDT >> DateTime.parse("???", "%Y-%m-%d") = !DateTime diff --git a/environment.c b/environment.c index b9cbaa4..69710b4 100644 --- a/environment.c +++ b/environment.c @@ -267,13 +267,13 @@ env_t *new_compilation_unit(CORD libname) {"after", "DateTime$after", "func(dt:DateTime,seconds=0.0,minutes=0.0,hours=0.0,days=0,weeks=0,months=0,years=0,local_time=yes)->DateTime"}, {"date", "DateTime$date", "func(dt:DateTime,local_time=yes)->Text"}, - {"format", "DateTime$format", "func(dt:DateTime,format=\"%c\",local_time=yes)->Text"}, + {"format", "DateTime$format", "func(dt:DateTime,format=\"%Y-%m-%dT%H:%M:%S%z\",local_time=yes)->Text"}, {"from_unix_timestamp", "DateTime$from_unix_timestamp", "func(timestamp:Int64)->DateTime"}, {"get", "DateTime$get", "func(dt:DateTime,year=!&Int,month=!&Int,day=!&Int,hour=!&Int,minute=!&Int,second=!&Int,nanosecond=!&Int,weekday=!&Int, local_time=yes)"}, {"hours_till", "DateTime$hours_till", "func(now:DateTime,then:DateTime)->Num"}, {"minutes_till", "DateTime$minutes_till", "func(now:DateTime,then:DateTime)->Num"}, {"new", "DateTime$new", "func(year:Int,month:Int,day:Int,hour=0,minute=0,second=0.0)->DateTime"}, - {"parse", "DateTime$parse", "func(text:Text, format=\"%c\")->DateTime?"}, + {"parse", "DateTime$parse", "func(text:Text, format=\"%Y-%m-%dT%H:%M:%S%z\")->DateTime?"}, {"relative", "DateTime$relative", "func(dt:DateTime,relative_to=DateTime.now(),local_time=yes)->Text"}, {"seconds_till", "DateTime$seconds_till", "func(now:DateTime,then:DateTime)->Num"}, {"time", "DateTime$time", "func(dt:DateTime,seconds=no,am_pm=yes,local_time=yes)->Text"}, diff --git a/stdlib/datetime.c b/stdlib/datetime.c index a3bb42c..bc1d88e 100644 --- a/stdlib/datetime.c +++ b/stdlib/datetime.c @@ -21,7 +21,7 @@ public Text_t DateTime$as_text(const DateTime_t *dt, bool colorize, const TypeIn struct tm info; struct tm *final_info = localtime_r(&dt->tv_sec, &info); static char buf[256]; - size_t len = strftime(buf, sizeof(buf), "%c", final_info); + size_t len = strftime(buf, sizeof(buf), "%c %Z", final_info); Text_t text = Text$format("%.*s", (int)len, buf); if (colorize) text = Text$concat(Text("\x1b[36m"), text, Text("\x1b[m")); @@ -141,12 +141,18 @@ public Text_t DateTime$time(DateTime_t dt, bool seconds, bool am_pm, bool local_ public OptionalDateTime_t DateTime$parse(Text_t text, Text_t format) { struct tm info = {.tm_isdst=-1}; - char *invalid = strptime(Text$as_c_string(text), Text$as_c_string(format), &info); + const char *str = Text$as_c_string(text); + const char *fmt = Text$as_c_string(format); + if (strstr(fmt, "%Z")) + fail("The %%Z specifier is not supported for time parsing!"); + + char *invalid = strptime(str, fmt, &info); if (!invalid || invalid[0] != '\0') return NULL_DATETIME; + long offset = info.tm_gmtoff; // Need to cache this because mktime() mutates it to local timezone >:( time_t t = mktime(&info); - return (DateTime_t){.tv_sec=t}; + return (DateTime_t){.tv_sec=t + offset - info.tm_gmtoff}; } static inline Text_t num_format(long n, const char *unit) @@ -195,7 +201,7 @@ public Text_t DateTime$relative(DateTime_t dt, DateTime_t relative_to, bool loca CONSTFUNC public Int64_t DateTime$unix_timestamp(DateTime_t dt) { - return (Int64_t)(dt.tv_sec); + return (Int64_t)dt.tv_sec; } CONSTFUNC public DateTime_t DateTime$from_unix_timestamp(Int64_t timestamp)