chore(tests): updated test suite

This commit is contained in:
Erica Marigold 2023-09-06 13:17:36 +05:30
parent 72f136f1d3
commit eb642473e3
No known key found for this signature in database
GPG key ID: 23CD97ABBBCC5ED2
15 changed files with 250 additions and 165 deletions

6
Cargo.lock generated
View file

@ -310,9 +310,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.26" version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f"
dependencies = [ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
@ -320,7 +320,7 @@ dependencies = [
"num-traits", "num-traits",
"time 0.1.45", "time 0.1.45",
"wasm-bindgen", "wasm-bindgen",
"winapi", "windows-targets 0.48.5",
] ]
[[package]] [[package]]

View file

@ -2,7 +2,7 @@ use crate::lune::builtins::datetime::date_time::Timezone;
use chrono::prelude::*; use chrono::prelude::*;
use chrono_locale::LocaleDate; use chrono_locale::LocaleDate;
#[derive(Copy, Clone)] #[derive(Copy, Clone, Debug)]
pub struct DateTimeBuilder { pub struct DateTimeBuilder {
/// The year. In the range 1400 - 9999. /// The year. In the range 1400 - 9999.
pub year: i32, pub year: i32,
@ -98,7 +98,7 @@ impl DateTimeBuilder {
{ {
let format = match format { let format = match format {
Some(fmt) => fmt.to_string(), Some(fmt) => fmt.to_string(),
None => "%Y-%m-%dT%H:%M:%SZ".to_string(), None => "%Y-%m-%dT%H:%M:%SZUTC+%z".to_string(),
}; };
let locale = match locale { let locale = match locale {
@ -106,34 +106,69 @@ impl DateTimeBuilder {
None => "en".to_string(), None => "en".to_string(),
}; };
let time = Utc
.with_ymd_and_hms(
self.year,
self.month,
self.day,
self.hour,
self.minute,
self.second,
)
.single()
.ok_or(())?;
// dbg!(
// "{}",
// match timezone {
// Timezone::Utc => time.to_rfc3339(), //.formatl((format).as_str(), locale.as_str()),
// Timezone::Local => time.with_timezone(&Local).to_rfc3339(), // .formatl((format).as_str(), locale.as_str()),
// }
// );
Ok(match timezone { Ok(match timezone {
Timezone::Utc => Utc Timezone::Utc => time.formatl((format).as_str(), locale.as_str()),
.with_ymd_and_hms( Timezone::Local => time
self.year, .with_timezone(&Local)
self.month, .formatl((format).as_str(), locale.as_str()),
self.day, }
self.hour, .to_string())
self.minute,
self.second, // .formatl((format).as_str(), locale.as_str())
) // .to_string())
.single()
.ok_or(())? // Ok(match timezone {
.formatl((format).as_str(), locale.as_str()) // Timezone::Utc => Utc
.to_string(), // .with_ymd_and_hms(
Timezone::Local => Local // self.year,
.with_ymd_and_hms( // self.month,
self.year, // self.day,
self.month, // self.hour,
self.day, // self.minute,
self.hour, // self.second,
self.minute, // )
self.second, // .single()
) // .ok_or(())?
.single() // .with_timezone(&match timezone {
.ok_or(())? // Timezone::Utc => Utc,
.formatl((format).as_str(), locale.as_str()) // Timezone::Local => Local
.to_string(), // })
}) // .formatl((format).as_str(), locale.as_str())
// .to_string(),
// Timezone::Local => Local
// .with_ymd_and_hms(
// self.year,
// self.month,
// self.day,
// self.hour,
// self.minute,
// self.second,
// )
// .single()
// .ok_or(())?
// .formatl((format).as_str(), locale.as_str())
// .to_string(),
// })
} }
pub fn build(self) -> Self { pub fn build(self) -> Self {

View file

@ -9,6 +9,7 @@ pub enum TimestampType {
} }
/// General timezone types accepted by `DateTime` methods. /// General timezone types accepted by `DateTime` methods.
#[derive(Eq, PartialEq)]
pub enum Timezone { pub enum Timezone {
Utc, Utc,
Local, Local,
@ -67,30 +68,28 @@ impl DateTime {
/// - Non-integer values are rounded down. For example, providing 2.5 hours will be equivalent to providing 2 hours, not 2 hours 30 minutes. /// - Non-integer values are rounded down. For example, providing 2.5 hours will be equivalent to providing 2 hours, not 2 hours 30 minutes.
/// - Omitted values are assumed to be their lowest value in their normal range, except for year which defaults to 1970. /// - Omitted values are assumed to be their lowest value in their normal range, except for year which defaults to 1970.
pub fn from_universal_time(date_time: Option<DateTimeBuilder>) -> Result<Self, ()> { pub fn from_universal_time(date_time: Option<DateTimeBuilder>) -> Result<Self, ()> {
if let Some(date_time) = date_time { Ok(match date_time {
let utc_time: ChronoDateTime<Utc> = Utc.from_utc_datetime(&NaiveDateTime::new( Some(date_time) => {
NaiveDate::from_ymd_opt(date_time.year, date_time.month, date_time.day).ok_or(())?, let utc_time: ChronoDateTime<Utc> = Utc.from_utc_datetime(&NaiveDateTime::new(
NaiveTime::from_hms_milli_opt( NaiveDate::from_ymd_opt(date_time.year, date_time.month, date_time.day)
date_time.hour, .ok_or(())?,
date_time.minute, NaiveTime::from_hms_milli_opt(
date_time.second, date_time.hour,
date_time.millisecond, date_time.minute,
) date_time.second,
.ok_or(())?, date_time.millisecond,
)); )
.ok_or(())?,
));
Ok(Self { Self {
unix_timestamp: utc_time.timestamp(), unix_timestamp: utc_time.timestamp(),
unix_timestamp_millis: utc_time.timestamp_millis(), unix_timestamp_millis: utc_time.timestamp_millis(),
}) }
} else { }
let utc_time = Utc::now();
Ok(Self { None => Self::now(),
unix_timestamp: utc_time.timestamp(), })
unix_timestamp_millis: utc_time.timestamp_millis(),
})
}
} }
/// Returns a new `DateTime` using the given units from a local time. The /// Returns a new `DateTime` using the given units from a local time. The
@ -102,34 +101,38 @@ impl DateTime {
/// - Non-integer values are rounded down. For example, providing 2.5 hours will be equivalent to providing 2 hours, not 2 hours 30 minutes. /// - Non-integer values are rounded down. For example, providing 2.5 hours will be equivalent to providing 2 hours, not 2 hours 30 minutes.
/// - Omitted values are assumed to be their lowest value in their normal range, except for year which defaults to 1970. /// - Omitted values are assumed to be their lowest value in their normal range, except for year which defaults to 1970.
pub fn from_local_time(date_time: Option<DateTimeBuilder>) -> Result<Self, ()> { pub fn from_local_time(date_time: Option<DateTimeBuilder>) -> Result<Self, ()> {
if let Some(date_time) = date_time { Ok(match date_time {
let local_time: ChronoDateTime<Local> = Local Some(date_time) => {
.from_local_datetime(&NaiveDateTime::new( let local_time: ChronoDateTime<Local> = Local
NaiveDate::from_ymd_opt(date_time.year, date_time.month, date_time.day) .from_local_datetime(&NaiveDateTime::new(
NaiveDate::from_ymd_opt(date_time.year, date_time.month, date_time.day)
.ok_or(())?,
NaiveTime::from_hms_milli_opt(
date_time.hour,
date_time.minute,
date_time.second,
date_time.millisecond,
)
.ok_or(())?, .ok_or(())?,
NaiveTime::from_hms_milli_opt( ))
date_time.hour, .single()
date_time.minute, .ok_or(())?;
date_time.second,
date_time.millisecond,
)
.ok_or(())?,
))
.single()
.ok_or(())?;
Ok(Self { Self {
unix_timestamp: local_time.timestamp(), unix_timestamp: local_time.timestamp(),
unix_timestamp_millis: local_time.timestamp_millis(), unix_timestamp_millis: local_time.timestamp_millis(),
}) }
} else { }
let local_time = Local::now();
Ok(Self { None => {
unix_timestamp: local_time.timestamp(), let local_time = Local::now();
unix_timestamp_millis: local_time.timestamp_millis(),
}) Self {
} unix_timestamp: local_time.timestamp(),
unix_timestamp_millis: local_time.timestamp_millis(),
}
}
})
} }
/// Returns a `DateTime` from an ISO 8601 date-time string in UTC /// Returns a `DateTime` from an ISO 8601 date-time string in UTC
@ -168,6 +171,7 @@ impl DateTime {
// Any less tedious way to get Enum member based on index? // Any less tedious way to get Enum member based on index?
// I know there's some crates available with derive macros for this, // I know there's some crates available with derive macros for this,
// would it be okay if used some of them? // would it be okay if used some of them?
date_time_constructor date_time_constructor
.with_year(date_time.year()) .with_year(date_time.year())
.with_month(match date_time.month() { .with_month(match date_time.month() {
@ -199,12 +203,12 @@ impl DateTime {
/// description. The values within this table could be passed to `from_local_time` /// description. The values within this table could be passed to `from_local_time`
/// to produce the original `DateTime` object. /// to produce the original `DateTime` object.
pub fn to_local_time(&self) -> Result<DateTimeBuilder, ()> { pub fn to_local_time(&self) -> Result<DateTimeBuilder, ()> {
Ok(Self::to_datetime_builder( Self::to_datetime_builder(
Local Local
.timestamp_opt(self.unix_timestamp, 0) .timestamp_opt(self.unix_timestamp, 0)
.single() .single()
.ok_or(())?, .ok_or(())?,
)?) )
} }
/// Converts the value of this `DateTime` object to Universal Coordinated Time (UTC). /// Converts the value of this `DateTime` object to Universal Coordinated Time (UTC).
@ -213,11 +217,15 @@ impl DateTime {
/// in this data type's description. The values within this table could be passed /// in this data type's description. The values within this table could be passed
/// to `from_universal_time` to produce the original `DateTime` object. /// to `from_universal_time` to produce the original `DateTime` object.
pub fn to_universal_time(&self) -> Result<DateTimeBuilder, ()> { pub fn to_universal_time(&self) -> Result<DateTimeBuilder, ()> {
Ok(Self::to_datetime_builder( Self::to_datetime_builder(
Utc.timestamp_opt(self.unix_timestamp, 0) Utc.timestamp_opt(self.unix_timestamp, 0)
.single() .single()
.ok_or(())?, .ok_or(())?,
)?) )
// dbg!("{:#?}", m?);
// m
} }
/// Formats a date as a ISO 8601 date-time string, returns None if the DateTime object is invalid. /// Formats a date as a ISO 8601 date-time string, returns None if the DateTime object is invalid.

View file

@ -108,14 +108,14 @@ create_tests! {
task_wait: "task/wait", task_wait: "task/wait",
datetime_now: "datetime/now", datetime_now: "datetime/now",
datetime_fromunixtimestamp: "datetime/fromunixtimestamp", datetime_from_unix_timestamp: "datetime/fromUnixTimestamp",
datetime_fromuniversaltime: "datetime/fromuniversaltime", datetime_from_universal_time: "datetime/fromUniversalTime",
datetime_touniversaltime: "datetime/touniversaltime", datetime_to_universal_time: "datetime/toUniversalTime",
datetime_fromlocaltime: "datetime/fromlocaltime", datetime_from_local_time: "datetime/fromLocalTime",
datetime_tolocaltime: "datetime/tolocaltime", datetime_to_local_time: "datetime/toLocalTime",
datetime_fromisodate: "datetime/fromisodate", datetime_from_iso_date: "datetime/fromIsoDate",
datetime_toisodate: "datetime/toisodate", datetime_to_iso_date: "datetime/toIsoDate",
datetime_formattime: "datetime/formattime", datetime_format_time: "datetime/formatTime",
} }
#[cfg(feature = "roblox")] #[cfg(feature = "roblox")]

View file

@ -0,0 +1,41 @@
local DateTime = require("@lune/datetime")
-- UTC Timezone
assert(
DateTime.fromUnixTimestamp(1693068988):formatTime("utc", "%Y-%m-%dT%H:%M:%SZ", "en")
== "2023-08-26T16:56:28Z",
"invalid ISO 8601 formatting for DateTime.formatTime() (UTC)"
)
assert(
DateTime.fromUnixTimestamp(1693068988):formatTime("utc", "%A, %d %B %Y", "fr")
== "samedi, 26 août 2023",
"expected format specifier '%A, %d %B %Y' to return 'samedi, 26 août 2023' for locale 'fr'"
)
-- FIXME: Local timezone formatTime fails due to a rust side bug
local expectedTimeString = os.date("%Y-%m-%dT%H:%M:%SZ%z", 1693932753)
-- NOTE: UTC Timezone conversions work perfectly fine, issue only for local.
-- So far I've made it so that format_time always converts to_universal_time
-- Builder object. Then in to_string, we construct a ChronoDateTime from the values
-- and convert it to the requested timezone. We then format this with our formatter
-- string.
-- For debugging, try checking what to_universal_time returns, maybe that's where
-- an incorrect DateTimeBuilder is getting returned... If that's the case, that means
-- there probably isn't any issue with to_string at all.
-- Yes, an invalid DateTimeBuilder is being returned turns out. Still don't know why actually.
print(
expectedTimeString,
DateTime.fromUnixTimestamp(1693068988):formatTime("local", "%Y-%m-%dT%H:%M:%SZ", "en")
)
assert(
DateTime.fromUnixTimestamp(1693068988):formatTime("local", "%Y-%m-%dT%H:%M:%SZ", "en")
== expectedTimeString,
"invalid ISO 8601 formatting for DateTime.formatTime() (local)"
)

View file

@ -1,16 +0,0 @@
local DateTime = require("@lune/datetime")
-- UTC Timezone
assert(
DateTime.fromUnixTimestamp(1693068988):formatTime("utc", "%Y-%m-%dT%H:%M:%SZ", "en")
== "2023-08-26T16:56:28Z",
"invalid ISO 8601 formatting for DateTime.formatTime()"
)
assert(
DateTime.fromUnixTimestamp(1693068988):formatTime("utc", "%A, %d %B %Y", "fr")
== "samedi, 26 août 2023",
"expected format specifier '%A, %d %B %Y' to return 'samedi, 26 août 2023' for locale 'fr'"
)
-- TODO: local timezone tests

View file

@ -1,7 +1,5 @@
local DateTime = require("@lune/datetime") local DateTime = require("@lune/datetime")
-- Fails due to issue with rust side implementation
assert( assert(
DateTime.fromIsoDate("2023-08-26T16:56:28Z") ~= nil, DateTime.fromIsoDate("2023-08-26T16:56:28Z") ~= nil,
"expected DateTime.fromIsoDate() to return DateTime, got nil" "expected DateTime.fromIsoDate() to return DateTime, got nil"

View file

@ -0,0 +1,45 @@
local DateTime = require("@lune/datetime")
assert(
DateTime.fromLocalTime()["unixTimestamp"] == os.time(),
"expected DateTime.fromLocalTime() with no args to return DateTime at current moment"
)
local timeValues1 = os.date("*t", 1693049188)
assert(
DateTime.fromLocalTime({
["year"] = timeValues1.year,
["month"] = timeValues1.month,
["day"] = timeValues1.day,
["hour"] = timeValues1.hour,
["minute"] = timeValues1.min,
["second"] = timeValues1.sec,
["millisecond"] = 0,
})["unixTimestamp"] == 1693049188,
"expected DateTime.fromLocalTime() with DateTimeValues arg to return 1693049188s"
)
print(DateTime.fromLocalTime({
["year"] = 2023,
["month"] = "aug",
["day"] = 26,
["hour"] = 16,
["minute"] = 56,
["second"] = 28,
["millisecond"] = 892,
})["unixTimestamp"])
local timeValues2 = os.date("*t", 1693049188.892)
assert(
DateTime.fromLocalTime({
["year"] = timeValues2.year,
["month"] = timeValues2.month,
["day"] = timeValues2.day,
["hour"] = timeValues2.hour,
["minute"] = timeValues2.min,
["second"] = timeValues2.sec,
["millisecond"] = 892,
})["unixTimestampMillis"] == 1693049188892,
"expected DateTime.fromLocalTime() with DateTimeValues arg with millis to return 1693049188892ms"
)

View file

@ -1,32 +0,0 @@
local DateTime = require("@lune/datetime")
assert(
DateTime.fromLocalTime()["unixTimestamp"] == os.time(),
"expected DateTime.fromLocalTime() with no args to return DateTime at current moment"
)
assert(
DateTime.fromLocalTime({
["year"] = 2023,
["month"] = "aug",
["day"] = 26,
["hour"] = 16,
["minute"] = 56,
["second"] = 28,
["millisecond"] = 0,
})["unixTimestamp"] == 1693049188,
"expected DateTime.fromLocalTime() with DateTimeValues arg to return 1693049188s"
)
assert(
DateTime.fromLocalTime({
["year"] = 2023,
["month"] = "aug",
["day"] = 26,
["hour"] = 16,
["minute"] = 56,
["second"] = 28,
["millisecond"] = 892,
})["unixTimestampMillis"] == 1693049188892,
"expected DateTime.fromLocalTime() with DateTimeValues arg with millis to return 1693049188892ms"
)

View file

@ -0,0 +1,30 @@
local DateTime = require("@lune/datetime")
local dateTime = (DateTime.fromIsoDate("2023-08-27T05:54:19Z") :: DateTime.DateTime):toLocalTime()
local expectedDateTimeValues = os.date("*t", 1693115659)
assert(
dateTime.year == expectedDateTimeValues.year,
`expected {dateTime.year} == {expectedDateTimeValues.year}`
)
assert(
dateTime.month == expectedDateTimeValues.month,
`expected {dateTime.month} == {expectedDateTimeValues.month}`
)
assert(
dateTime.day == expectedDateTimeValues.day,
`expected {dateTime.day} == {expectedDateTimeValues.day}`
)
assert(
dateTime.hour == expectedDateTimeValues.hour,
`expected {dateTime.hour} == {expectedDateTimeValues.hour}`
)
assert(
dateTime.minute == expectedDateTimeValues.min,
`expected {dateTime.minute} == {expectedDateTimeValues.min}`
)
assert(
dateTime.second == expectedDateTimeValues.sec,
`expected {dateTime.second} == {expectedDateTimeValues.sec}`
)

View file

@ -1,24 +0,0 @@
local DateTime = require("@lune/datetime")
local dateTime = (DateTime.fromIsoDate("2023-08-27T05:54:19Z") :: DateTime.DateTime):toLocalTime()
local expectedDateTimeValues = table.pack(
string.match(
"2023-08-27T11:24:19Z",
"(%d%d%d%d)-?(%d?%d?)-?(%d?%d?)T(%d?%d?):(%d?%d?):(%d?%d?)Z$"
)
)
local expectedYear = tonumber(expectedDateTimeValues[1])
local expectedMonth = tonumber(expectedDateTimeValues[2])
local expectedDay = tonumber(expectedDateTimeValues[3])
local expectedHour = tonumber(expectedDateTimeValues[4])
local expectedMinute = tonumber(expectedDateTimeValues[5])
local expectedSecond = tonumber(expectedDateTimeValues[6])
assert(dateTime.year == expectedYear, `expected {dateTime.year} == {expectedYear}`)
assert(dateTime.month == expectedMonth, `expected {dateTime.month} == {expectedMonth}`)
assert(dateTime.day == expectedDay, `expected {dateTime.day} == {expectedDay}`)
assert(dateTime.hour == expectedHour, `expected {dateTime.hour} == {expectedHour}`)
assert(dateTime.minute == expectedMinute, `expected {dateTime.minute} == {expectedMinute}`)
assert(dateTime.second == expectedSecond, `expected {dateTime.second} == {expectedSecond}`)