From 8ffbb328f3e1e07c429210f052ed88e9224fd3c5 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Wed, 23 Apr 2025 16:01:12 +0200 Subject: [PATCH] Enforce some more consistency with new datetime changes + add deprecation warning to iso methods --- crates/lune-std-datetime/src/date_time.rs | 22 ++++----- crates/lune-std-datetime/src/lib.rs | 12 ++--- crates/lune/src/tests.rs | 9 ++-- tests/datetime/fromIsoDate.luau | 11 ----- tests/datetime/fromRfc3339.luau | 4 +- tests/datetime/toLocalTime.luau | 32 +++---------- .../{toIsoDate.luau => toRfc3339.luau} | 48 ++++++------------- tests/datetime/toUniversalTime.luau | 32 +++---------- types/datetime.luau | 33 +++++++++---- 9 files changed, 77 insertions(+), 126 deletions(-) delete mode 100644 tests/datetime/fromIsoDate.luau rename tests/datetime/{toIsoDate.luau => toRfc3339.luau} (61%) diff --git a/crates/lune-std-datetime/src/date_time.rs b/crates/lune-std-datetime/src/date_time.rs index 3733d5f..bcb76f2 100644 --- a/crates/lune-std-datetime/src/date_time.rs +++ b/crates/lune-std-datetime/src/date_time.rs @@ -159,7 +159,7 @@ impl DateTime { } /** - Parses a time string in the ISO 8601 format, such as + Parses a time string in the RFC 3339 format, such as `1996-12-19T16:39:57-08:00`, into a new `DateTime` struct. See [`chrono::DateTime::parse_from_rfc3339`] for additional details. @@ -168,8 +168,8 @@ impl DateTime { Returns an error if the input string is not a valid RFC 3339 date-time. */ - pub fn from_iso_date(iso_date: impl AsRef) -> DateTimeResult { - let inner = ChronoDateTime::parse_from_rfc3339(iso_date.as_ref())?.with_timezone(&Utc); + pub fn from_rfc_3339(date: impl AsRef) -> DateTimeResult { + let inner = ChronoDateTime::parse_from_rfc3339(date.as_ref())?.with_timezone(&Utc); Ok(Self { inner }) } @@ -183,8 +183,8 @@ impl DateTime { Returns an error if the input string is not a valid RFC 2822 date-time. */ - pub fn from_rfc_2822_date(rfc_date: impl AsRef) -> DateTimeResult { - let inner = ChronoDateTime::parse_from_rfc2822(rfc_date.as_ref())?.with_timezone(&Utc); + pub fn from_rfc_2822(date: impl AsRef) -> DateTimeResult { + let inner = ChronoDateTime::parse_from_rfc2822(date.as_ref())?.with_timezone(&Utc); Ok(Self { inner }) } @@ -207,12 +207,12 @@ impl DateTime { } /** - Formats a time string in the ISO 8601 format, such as `1996-12-19T16:39:57-08:00`. + Formats a time string in the RFC 3339 format, such as `1996-12-19T16:39:57-08:00`. See [`chrono::DateTime::to_rfc3339`] for additional details. */ #[must_use] - pub fn to_iso_date(self) -> String { + pub fn to_rfc_3339(self) -> String { self.inner.to_rfc3339() } @@ -222,7 +222,7 @@ impl DateTime { See [`chrono::DateTime::to_rfc2822`] for additional details. */ #[must_use] - pub fn to_rfc_2822_date(self) -> String { + pub fn to_rfc_2822(self) -> String { self.inner.to_rfc2822() } } @@ -254,9 +254,9 @@ impl LuaUserData for DateTime { }, ); // Normal methods - methods.add_method("toIsoDate", |_, this, ()| Ok(this.to_iso_date())); - methods.add_method("toRfc3339", |_, this, ()| Ok(this.to_iso_date())); - methods.add_method("toRfc2822", |_, this, ()| Ok(this.to_rfc_2822_date())); + methods.add_method("toIsoDate", |_, this, ()| Ok(this.to_rfc_3339())); // FUTURE: Remove this rfc3339 alias method + methods.add_method("toRfc3339", |_, this, ()| Ok(this.to_rfc_3339())); + methods.add_method("toRfc2822", |_, this, ()| Ok(this.to_rfc_2822())); methods.add_method( "formatUniversalTime", |_, this, (format, locale): (Option, Option)| { diff --git a/crates/lune-std-datetime/src/lib.rs b/crates/lune-std-datetime/src/lib.rs index d2891a3..76337ce 100644 --- a/crates/lune-std-datetime/src/lib.rs +++ b/crates/lune-std-datetime/src/lib.rs @@ -19,14 +19,14 @@ pub use self::date_time::DateTime; */ pub fn module(lua: Lua) -> LuaResult { TableBuilder::new(lua)? - .with_function("fromIsoDate", |_, iso_date: String| { - Ok(DateTime::from_iso_date(iso_date)?) + .with_function("fromIsoDate", |_, date: String| { + Ok(DateTime::from_rfc_3339(date)?) // FUTURE: Remove this rfc3339 alias method })? - .with_function("fromRfc3339", |_, iso_date: String| { - Ok(DateTime::from_iso_date(iso_date)?) + .with_function("fromRfc3339", |_, date: String| { + Ok(DateTime::from_rfc_3339(date)?) })? - .with_function("fromRfc2822", |_, rfc_date: String| { - Ok(DateTime::from_rfc_2822_date(rfc_date)?) + .with_function("fromRfc2822", |_, date: String| { + Ok(DateTime::from_rfc_2822(date)?) })? .with_function("fromLocalTime", |_, values| { Ok(DateTime::from_local_time(&values)?) diff --git a/crates/lune/src/tests.rs b/crates/lune/src/tests.rs index 08cd239..e9ff03b 100644 --- a/crates/lune/src/tests.rs +++ b/crates/lune/src/tests.rs @@ -91,15 +91,14 @@ create_tests! { create_tests! { datetime_format_local_time: "datetime/formatLocalTime", datetime_format_universal_time: "datetime/formatUniversalTime", - datetime_from_iso_date: "datetime/fromIsoDate", - datetime_from_rfc_2822_date: "datetime/fromRfc2822", - datetime_from_rfc_3339_date: "datetime/fromRfc3339", + datetime_from_rfc_2822: "datetime/fromRfc2822", + datetime_from_rfc_3339: "datetime/fromRfc3339", datetime_from_local_time: "datetime/fromLocalTime", datetime_from_universal_time: "datetime/fromUniversalTime", datetime_from_unix_timestamp: "datetime/fromUnixTimestamp", datetime_now: "datetime/now", - datetime_to_iso_date: "datetime/toIsoDate", - datetime_to_rfc_2822_date: "datetime/toRfc2822", + datetime_to_rfc_2822: "datetime/toRfc2822", + datetime_to_rfc_3339: "datetime/toRfc3339", datetime_to_local_time: "datetime/toLocalTime", datetime_to_universal_time: "datetime/toUniversalTime", } diff --git a/tests/datetime/fromIsoDate.luau b/tests/datetime/fromIsoDate.luau deleted file mode 100644 index 618dc4b..0000000 --- a/tests/datetime/fromIsoDate.luau +++ /dev/null @@ -1,11 +0,0 @@ -local DateTime = require("@lune/datetime") - -assert( - DateTime.fromIsoDate("2023-08-26T16:56:28Z") ~= nil, - "expected DateTime.fromIsoDate() to return DateTime, got nil" -) - -assert( - DateTime.fromIsoDate("1929-12-05T23:18:23Z") ~= nil, - "expected DateTime.fromIsoDate() to return DateTime, got nil" -) diff --git a/tests/datetime/fromRfc3339.luau b/tests/datetime/fromRfc3339.luau index 0bf2187..f0143f8 100644 --- a/tests/datetime/fromRfc3339.luau +++ b/tests/datetime/fromRfc3339.luau @@ -2,10 +2,10 @@ local DateTime = require("@lune/datetime") assert( DateTime.fromRfc3339("2023-08-26T16:56:28Z") ~= nil, - "expected DateTime.fromIsoDate() to return DateTime, got nil" + "expected DateTime.fromRfc3339() to return DateTime, got nil" ) assert( DateTime.fromRfc3339("1929-12-05T23:18:23Z") ~= nil, - "expected DateTime.fromIsoDate() to return DateTime, got nil" + "expected DateTime.fromRfc3339() to return DateTime, got nil" ) diff --git a/tests/datetime/toLocalTime.luau b/tests/datetime/toLocalTime.luau index edf1c31..3e79bf4 100644 --- a/tests/datetime/toLocalTime.luau +++ b/tests/datetime/toLocalTime.luau @@ -1,30 +1,12 @@ local DateTime = require("@lune/datetime") -local values = DateTime.fromIsoDate("2023-08-27T05:54:19Z"):toLocalTime() +local values = DateTime.fromRfc3339("2023-08-27T05:54:19Z"):toLocalTime() local expectedDateTimeValues = os.date("*t", 1693115659) -assert( - values.year == expectedDateTimeValues.year, - `expected {values.year} == {expectedDateTimeValues.year}` -) -assert( - values.month == expectedDateTimeValues.month, - `expected {values.month} == {expectedDateTimeValues.month}` -) -assert( - values.day == expectedDateTimeValues.day, - `expected {values.day} == {expectedDateTimeValues.day}` -) -assert( - values.hour == expectedDateTimeValues.hour, - `expected {values.hour} == {expectedDateTimeValues.hour}` -) -assert( - values.minute == expectedDateTimeValues.min, - `expected {values.minute} == {expectedDateTimeValues.min}` -) -assert( - values.second == expectedDateTimeValues.sec, - `expected {values.second} == {expectedDateTimeValues.sec}` -) +assert(values.year == expectedDateTimeValues.year, `expected {values.year} == {expectedDateTimeValues.year}`) +assert(values.month == expectedDateTimeValues.month, `expected {values.month} == {expectedDateTimeValues.month}`) +assert(values.day == expectedDateTimeValues.day, `expected {values.day} == {expectedDateTimeValues.day}`) +assert(values.hour == expectedDateTimeValues.hour, `expected {values.hour} == {expectedDateTimeValues.hour}`) +assert(values.minute == expectedDateTimeValues.min, `expected {values.minute} == {expectedDateTimeValues.min}`) +assert(values.second == expectedDateTimeValues.sec, `expected {values.second} == {expectedDateTimeValues.sec}`) diff --git a/tests/datetime/toIsoDate.luau b/tests/datetime/toRfc3339.luau similarity index 61% rename from tests/datetime/toIsoDate.luau rename to tests/datetime/toRfc3339.luau index 6389c9a..8424a2f 100644 --- a/tests/datetime/toIsoDate.luau +++ b/tests/datetime/toRfc3339.luau @@ -1,35 +1,26 @@ local DateTime = require("@lune/datetime") local now = DateTime.now() -local nowIso = now:toIsoDate() +local nowRfc = now:toRfc3339() -- Make sure we have separator characters, T to separate date & time, + or Z to separate timezone -local dateTimeSplitIdx = string.find(nowIso, "T") -local timezoneSplitIdx = string.find(nowIso, "+") -local timezoneZeroedIdx = string.find(nowIso, "Z") +local dateTimeSplitIdx = string.find(nowRfc, "T") +local timezoneSplitIdx = string.find(nowRfc, "+") +local timezoneZeroedIdx = string.find(nowRfc, "Z") -assert(dateTimeSplitIdx ~= nil, "Missing date & time separator 'T' in iso 8601 string") -assert( - timezoneSplitIdx ~= nil or timezoneZeroedIdx ~= nil, - "Missing timezone separator '+' or 'Z' in iso date string" -) +assert(dateTimeSplitIdx ~= nil, "Missing date & time separator 'T' in RFC 3339 string") +assert(timezoneSplitIdx ~= nil or timezoneZeroedIdx ~= nil, "Missing timezone separator '+' or 'Z' in RFC 3339 string") -- Split date (before T) by dashes, split time (after T, before + or Z) -- by colons, we should then get 3 substrings for each of date & time -local dateParts = string.split(string.sub(nowIso, 1, dateTimeSplitIdx - 1), "-") -local timeParts = string.split( - string.sub( - nowIso, - dateTimeSplitIdx + 1, - ((timezoneSplitIdx or timezoneZeroedIdx) :: number) - 1 - ), - ":" -) +local dateParts = string.split(string.sub(nowRfc, 1, dateTimeSplitIdx - 1), "-") +local timeParts = + string.split(string.sub(nowRfc, dateTimeSplitIdx + 1, ((timezoneSplitIdx or timezoneZeroedIdx) :: number) - 1), ":") -assert(#dateParts == 3, "Date partial of iso 8601 should consist of 3 substrings, separated by '-'") -assert(#timeParts == 3, "Time partial of iso 8601 should consist of 3 substrings, separated by ':'") +assert(#dateParts == 3, "Date partial of RFC 3339 should consist of 3 substrings, separated by '-'") +assert(#timeParts == 3, "Time partial of RFC 3339 should consist of 3 substrings, separated by ':'") -- date should be in format YYYY:MM::DD -- time should be in format HH:MM:SS with optional fraction for seconds @@ -51,22 +42,13 @@ assert( if timezoneZeroedIdx ~= nil then -- No timezone offset - assert( - timezoneZeroedIdx == #nowIso, - "Timezone specifier 'Z' must be at the last character in iso 8601 string" - ) + assert(timezoneZeroedIdx == #nowRfc, "Timezone specifier 'Z' must be at the last character in RFC 3339 string") elseif timezoneSplitIdx ~= nil then -- Timezone offset - local timezoneParts = string.split(string.sub(nowIso, timezoneSplitIdx + 1), ":") + local timezoneParts = string.split(string.sub(nowRfc, timezoneSplitIdx + 1), ":") assert(#timezoneParts == 2, "Timezone partial should consist of 2 substings, separated by ':'") - assert( - string.match(timezoneParts[1], "^%d%d$"), - "Timezone partial should have 2 digits for hour" - ) - assert( - string.match(timezoneParts[2], "^%d%d$"), - "Timezone partial should have 2 digits for minute" - ) + assert(string.match(timezoneParts[1], "^%d%d$"), "Timezone partial should have 2 digits for hour") + assert(string.match(timezoneParts[2], "^%d%d$"), "Timezone partial should have 2 digits for minute") else error("unreachable") end diff --git a/tests/datetime/toUniversalTime.luau b/tests/datetime/toUniversalTime.luau index edf1c31..3e79bf4 100644 --- a/tests/datetime/toUniversalTime.luau +++ b/tests/datetime/toUniversalTime.luau @@ -1,30 +1,12 @@ local DateTime = require("@lune/datetime") -local values = DateTime.fromIsoDate("2023-08-27T05:54:19Z"):toLocalTime() +local values = DateTime.fromRfc3339("2023-08-27T05:54:19Z"):toLocalTime() local expectedDateTimeValues = os.date("*t", 1693115659) -assert( - values.year == expectedDateTimeValues.year, - `expected {values.year} == {expectedDateTimeValues.year}` -) -assert( - values.month == expectedDateTimeValues.month, - `expected {values.month} == {expectedDateTimeValues.month}` -) -assert( - values.day == expectedDateTimeValues.day, - `expected {values.day} == {expectedDateTimeValues.day}` -) -assert( - values.hour == expectedDateTimeValues.hour, - `expected {values.hour} == {expectedDateTimeValues.hour}` -) -assert( - values.minute == expectedDateTimeValues.min, - `expected {values.minute} == {expectedDateTimeValues.min}` -) -assert( - values.second == expectedDateTimeValues.sec, - `expected {values.second} == {expectedDateTimeValues.sec}` -) +assert(values.year == expectedDateTimeValues.year, `expected {values.year} == {expectedDateTimeValues.year}`) +assert(values.month == expectedDateTimeValues.month, `expected {values.month} == {expectedDateTimeValues.month}`) +assert(values.day == expectedDateTimeValues.day, `expected {values.day} == {expectedDateTimeValues.day}`) +assert(values.hour == expectedDateTimeValues.hour, `expected {values.hour} == {expectedDateTimeValues.hour}`) +assert(values.minute == expectedDateTimeValues.min, `expected {values.minute} == {expectedDateTimeValues.min}`) +assert(values.second == expectedDateTimeValues.sec, `expected {values.second} == {expectedDateTimeValues.sec}`) diff --git a/types/datetime.luau b/types/datetime.luau index 0df3785..4013e2c 100644 --- a/types/datetime.luau +++ b/types/datetime.luau @@ -163,11 +163,7 @@ end @param locale -- The locale the time should be formatted in @return string -- The formatting string ]=] -function DateTime.formatUniversalTime( - self: DateTime, - formatString: string?, - locale: Locale? -): string +function DateTime.formatUniversalTime(self: DateTime, formatString: string?, locale: Locale?): string return nil :: any end @@ -175,6 +171,8 @@ end @within DateTime @tag Method + **DEPRECATED**: Use `DateTime.toRfc3339` instead. + Formats this `DateTime` as an ISO 8601 date-time string. Some examples of ISO 8601 date-time strings are: @@ -207,6 +205,24 @@ function DateTime.toRfc2822(self: DateTime): string return nil :: any end +--[=[ + @within DateTime + @tag Method + + Formats this `DateTime` as an RFC 3339 date-time string. + + Some examples of RFC 3339 date-time strings are: + + - `2020-02-22T18:12:08Z` + - `2000-01-31T12:34:56+05:00` + - `1970-01-01T00:00:00.055Z` + + @return string -- The RFC 3339 formatted string +]=] +function DateTime.toRfc3339(self: DateTime): string + return nil :: any +end + --[=[ @within DateTime @tag Method @@ -270,8 +286,8 @@ export type DateTime = typeof(DateTime) -- Creates a DateTime for the current exact moment in time local now = DateTime.now() - -- Formats the current moment in time as an ISO 8601 string - print(now:toIsoDate()) + -- Formats the current moment in time as an RFC 3339 string + print(now:toRfc3339()) -- Formats the current moment in time as an RFC 2822 string print(now:toRfc2822()) @@ -415,8 +431,9 @@ end @within DateTime @tag Constructor + **DEPRECATED**: Use `DateTime.fromRfc3339` instead. + Creates a new `DateTime` from an ISO 8601 date-time string. - This function behaves the same as `fromRfc3339`. ### Errors