From 2ad64fd69435cbd5010476558dceb2f54b0052d7 Mon Sep 17 00:00:00 2001 From: "Chidozie C. Okafor" <39489124+doziestar@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:28:14 +0200 Subject: [PATCH 1/8] - Added `TimestampInterpretation` enum with `Auto` and `AlwaysSeconds` variants. - Updated `TimeConfig` to include a `timestamp_interpretation` field. - Modified `TimeConfigBuilder` to allow setting the `timestamp_interpretation`. --- src/time.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 10 deletions(-) diff --git a/src/time.rs b/src/time.rs index ad82b7e..e1421a1 100644 --- a/src/time.rs +++ b/src/time.rs @@ -246,9 +246,9 @@ impl Time { /// let d = Time::from_timestamp(3740, 123).unwrap(); /// assert_eq!(d.to_string(), "01:02:20.000123"); /// ``` - pub fn from_timestamp(timestamp_second: u32, timestamp_microsecond: u32) -> Result { - Time::from_timestamp_with_config( - timestamp_second, + pub fn from_timestamp(timestamp: i64, timestamp_microsecond: u32) -> Result { + Self::from_timestamp_with_config( + timestamp, timestamp_microsecond, &TimeConfigBuilder::new().build(), ) @@ -273,21 +273,32 @@ impl Time { /// assert_eq!(d.to_string(), "01:02:20.000123"); /// ``` pub fn from_timestamp_with_config( - timestamp_second: u32, + timestamp: i64, timestamp_microsecond: u32, config: &TimeConfig, ) -> Result { - let mut second = timestamp_second; - let mut microsecond = timestamp_microsecond; + let (mut second, mut microsecond) = match config.timestamp_interpretation { + TimestampInterpretation::Auto => { + if timestamp > 20_000_000_000 { + ((timestamp / 1000) as u32, ((timestamp % 1000) * 1000) as u32) + } else { + (timestamp as u32, timestamp_microsecond) + } + }, + TimestampInterpretation::AlwaysSeconds => (timestamp as u32, timestamp_microsecond), + }; + if microsecond >= 1_000_000 { second = second .checked_add(microsecond / 1_000_000) .ok_or(ParseError::TimeTooLarge)?; microsecond %= 1_000_000; } + if second >= 86_400 { return Err(ParseError::TimeTooLarge); } + Ok(Self { hour: (second / 3600) as u8, minute: ((second % 3600) / 60) as u8, @@ -442,16 +453,16 @@ impl Time { /// let t1 = Time::parse_str("15:00:00Z").unwrap(); /// /// let t2 = t1.in_timezone(7200).unwrap(); - // / assert_eq!(t2.to_string(), "17:00:00+02:00"); + /// assert_eq!(t2.to_string(), "17:00:00+02:00"); /// ``` pub fn in_timezone(&self, tz_offset: i32) -> Result { if tz_offset.abs() >= 24 * 3600 { Err(ParseError::OutOfRangeTz) } else if let Some(current_offset) = self.tz_offset { let offset = tz_offset - current_offset; - let seconds = self.total_seconds().saturating_add_signed(offset); + let seconds = self.total_seconds().saturating_add_signed(offset) as i64; let mut time = Self::from_timestamp(seconds, self.microsecond)?; - time.tz_offset = Some(offset); + time.tz_offset = Some(tz_offset); Ok(time) } else { Err(ParseError::TzRequired) @@ -587,28 +598,61 @@ impl TryFrom<&str> for MicrosecondsPrecisionOverflowBehavior { } } +/// Defines how timestamps should be interpreted +#[derive(Debug, Clone, Default, Copy, PartialEq)] +pub enum TimestampInterpretation { + /// Automatically determine if the timestamp is in seconds or milliseconds + /// based on its value (default behavior) + #[default] + Auto, + /// Always interpret timestamps as seconds, regardless of their value + AlwaysSeconds, +} + +impl TryFrom<&str> for TimestampInterpretation { + type Error = ConfigError; + fn try_from(value: &str) -> Result { + match value.to_lowercase().as_str() { + "auto" => Ok(Self::Auto), + "always_seconds" => Ok(Self::AlwaysSeconds), + _ => Err(ConfigError::UnknownTimestampInterpretationString), + } + } +} + +/// Configuration options for time parsing and handling #[derive(Debug, Clone, Default, PartialEq)] pub struct TimeConfig { + /// Defines how to handle microsecond precision overflow pub microseconds_precision_overflow_behavior: MicrosecondsPrecisionOverflowBehavior, + /// Optional timezone offset for Unix timestamps pub unix_timestamp_offset: Option, + /// Defines how timestamps should be interpreted + pub timestamp_interpretation: TimestampInterpretation, } impl TimeConfig { + /// Creates a new TimeConfigBuilder pub fn builder() -> TimeConfigBuilder { TimeConfigBuilder::new() } } +/// Builder for TimeConfig #[derive(Debug, Clone, Default)] pub struct TimeConfigBuilder { microseconds_precision_overflow_behavior: Option, unix_timestamp_offset: Option, + timestamp_interpretation: Option, } impl TimeConfigBuilder { + /// Creates a new TimeConfigBuilder with default values pub fn new() -> Self { Self::default() } + + /// Sets the microseconds precision overflow behavior pub fn microseconds_precision_overflow_behavior( mut self, microseconds_precision_overflow_behavior: MicrosecondsPrecisionOverflowBehavior, @@ -616,14 +660,41 @@ impl TimeConfigBuilder { self.microseconds_precision_overflow_behavior = Some(microseconds_precision_overflow_behavior); self } + + /// Sets the Unix timestamp offset pub fn unix_timestamp_offset(mut self, unix_timestamp_offset: Option) -> Self { self.unix_timestamp_offset = unix_timestamp_offset; self } + + /// Sets the timestamp interpretation behavior + /// + /// # Arguments + /// + /// * `timestamp_interpretation` - The TimestampInterpretation to use + /// + /// # Examples + /// + /// ``` + /// use speedate::{TimeConfigBuilder, TimestampInterpretation}; + /// + /// let config = TimeConfigBuilder::new() + /// .timestamp_interpretation(TimestampInterpretation::AlwaysSeconds) + /// .build(); + /// + /// assert_eq!(config.timestamp_interpretation, TimestampInterpretation::AlwaysSeconds); + /// ``` + pub fn timestamp_interpretation(mut self, timestamp_interpretation: TimestampInterpretation) -> Self { + self.timestamp_interpretation = Some(timestamp_interpretation); + self + } + + /// Builds the TimeConfig from the builder pub fn build(self) -> TimeConfig { TimeConfig { microseconds_precision_overflow_behavior: self.microseconds_precision_overflow_behavior.unwrap_or_default(), unix_timestamp_offset: self.unix_timestamp_offset, + timestamp_interpretation: self.timestamp_interpretation.unwrap_or_default(), } } -} +} \ No newline at end of file From 7beec8e0507c09079110561a5833c58a21e91b7f Mon Sep 17 00:00:00 2001 From: "Chidozie C. Okafor" <39489124+doziestar@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:28:41 +0200 Subject: [PATCH 2/8] Updated `DateTime::from_timestamp_with_config` to handle different interpretation modes. --- src/datetime.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/datetime.rs b/src/datetime.rs index c5de2ba..aed4233 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -1,5 +1,5 @@ use crate::numbers::{float_parse_bytes, IntFloat}; -use crate::TimeConfigBuilder; +use crate::{TimeConfigBuilder, TimestampInterpretation}; use crate::{time::TimeConfig, Date, ParseError, Time}; use std::cmp::Ordering; use std::fmt; @@ -390,7 +390,11 @@ impl DateTime { timestamp_microsecond: u32, config: &TimeConfig, ) -> Result { - let (mut second, extra_microsecond) = Date::timestamp_watershed(timestamp)?; + let (mut second, extra_microsecond) = match config.timestamp_interpretation { + TimestampInterpretation::Auto => Date::timestamp_watershed(timestamp)?, + TimestampInterpretation::AlwaysSeconds => (timestamp, 0), + }; + let mut total_microsecond = timestamp_microsecond .checked_add(extra_microsecond) .ok_or(ParseError::TimeTooLarge)?; @@ -402,7 +406,7 @@ impl DateTime { } let date = Date::from_timestamp_calc(second)?; // rem_euclid since if `timestamp_second = -100`, we want `time_second = 86300` (e.g. `86400 - 100`) - let time_second = second.rem_euclid(86_400) as u32; + let time_second = second.rem_euclid(86_400); Ok(Self { date, time: Time::from_timestamp_with_config(time_second, total_microsecond, config)?, From da4d03494440457e676178549f6b83205057b06e Mon Sep 17 00:00:00 2001 From: "Chidozie C. Okafor" <39489124+doziestar@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:30:22 +0200 Subject: [PATCH 3/8] add `test_timestamp_interpretation` --- tests/main.rs | 60 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/tests/main.rs b/tests/main.rs index f9ecc6c..078a100 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -7,7 +7,7 @@ use strum::EnumMessage; use speedate::{ float_parse_bytes, float_parse_str, int_parse_bytes, int_parse_str, Date, DateTime, Duration, IntFloat, - MicrosecondsPrecisionOverflowBehavior, ParseError, Time, TimeConfig, TimeConfigBuilder, + MicrosecondsPrecisionOverflowBehavior, ParseError, Time, TimeConfig, TimeConfigBuilder, TimestampInterpretation, }; /// macro for expected values @@ -363,7 +363,7 @@ fn time_from_timestamp_error() { Ok(_) => panic!("unexpectedly valid"), Err(e) => assert_eq!(e, ParseError::TimeTooLarge), } - match Time::from_timestamp(u32::MAX, u32::MAX) { + match Time::from_timestamp(i64::from(u32::MAX), u32::MAX) { Ok(_) => panic!("unexpectedly valid"), Err(e) => assert_eq!(e, ParseError::TimeTooLarge), } @@ -427,18 +427,22 @@ fn datetime_from_timestamp_range() { #[test] fn datetime_from_timestamp_specific() { - let dt = DateTime::from_timestamp(-11676095999, 4291493).unwrap(); + let config = TimeConfigBuilder::new() + .timestamp_interpretation(TimestampInterpretation::Auto) + .build(); + + let dt = DateTime::from_timestamp_with_config(-11676095999, 4291493, &config).unwrap(); assert_eq!(dt.to_string(), "1600-01-01T00:00:05.291493"); - let dt = DateTime::from_timestamp(-1, 1667444).unwrap(); + let dt = DateTime::from_timestamp_with_config(-1, 1667444, &config).unwrap(); assert_eq!(dt.to_string(), "1970-01-01T00:00:00.667444"); - let dt = DateTime::from_timestamp(32_503_680_000_000, 0).unwrap(); + let dt = DateTime::from_timestamp_with_config(32_503_680_000_000, 0, &config).unwrap(); assert_eq!(dt.to_string(), "3000-01-01T00:00:00"); - let dt = DateTime::from_timestamp(-11_676_096_000, 0).unwrap(); + let dt = DateTime::from_timestamp_with_config(-11_676_096_000, 0, &config).unwrap(); assert_eq!(dt.to_string(), "1600-01-01T00:00:00"); - let dt = DateTime::from_timestamp(1_095_216_660_480, 3221223).unwrap(); + let dt = DateTime::from_timestamp_with_config(1_095_216_660_480, 3221223, &config).unwrap(); assert_eq!(dt.to_string(), "2004-09-15T02:51:03.701223"); - let d = DateTime::from_timestamp(253_402_300_799_000, 999999).unwrap(); + let d = DateTime::from_timestamp_with_config(253_402_300_799_000, 999999, &config).unwrap(); assert_eq!(d.to_string(), "9999-12-31T23:59:59.999999"); match Date::from_timestamp(253_402_300_800_000, false) { Ok(dt) => panic!("unexpectedly valid, {dt}"), @@ -446,17 +450,22 @@ fn datetime_from_timestamp_specific() { } } + #[test] fn datetime_watershed() { - let dt = DateTime::from_timestamp(20_000_000_000, 0).unwrap(); + let config = TimeConfigBuilder::new() + .timestamp_interpretation(TimestampInterpretation::Auto) + .build(); + + let dt = DateTime::from_timestamp_with_config(20_000_000_000, 0, &config).unwrap(); assert_eq!(dt.to_string(), "2603-10-11T11:33:20"); - let dt = DateTime::from_timestamp(20_000_000_001, 0).unwrap(); + let dt = DateTime::from_timestamp_with_config(20_000_000_001, 0, &config).unwrap(); assert_eq!(dt.to_string(), "1970-08-20T11:33:20.001000"); - match DateTime::from_timestamp(-20_000_000_000, 0) { + match DateTime::from_timestamp_with_config(-20_000_000_000, 0, &config) { Ok(dt) => panic!("unexpectedly valid, {dt}"), Err(e) => assert_eq!(e, ParseError::DateTooSmall), } - let dt = DateTime::from_timestamp(-20_000_000_001, 0).unwrap(); + let dt = DateTime::from_timestamp_with_config(-20_000_000_001, 0, &config).unwrap(); assert_eq!(dt.to_string(), "1969-05-14T12:26:39.999000"); } @@ -1418,6 +1427,7 @@ fn test_time_config_builder() { TimeConfig { microseconds_precision_overflow_behavior: MicrosecondsPrecisionOverflowBehavior::Error, unix_timestamp_offset: None, + timestamp_interpretation: Default::default(), } ); assert_eq!(TimeConfigBuilder::new().build(), TimeConfig::builder().build()); @@ -1443,3 +1453,29 @@ fn number_dash_err() { assert!(matches!(float_parse_bytes(b"-"), IntFloat::Err)); assert!(matches!(float_parse_bytes(b"+"), IntFloat::Err)); } + +#[test] +fn test_timestamp_interpretation() { + let auto_config = TimeConfigBuilder::new() + .timestamp_interpretation(TimestampInterpretation::Auto) + .build(); + let always_seconds_config = TimeConfigBuilder::new() + .timestamp_interpretation(TimestampInterpretation::AlwaysSeconds) + .build(); + + // Test with a timestamp that would be interpreted as milliseconds in Auto mode + let auto_dt = DateTime::from_timestamp_with_config(1654619320123, 0, &auto_config).unwrap(); + let always_seconds_result = DateTime::from_timestamp_with_config(1654619320123, 0, &always_seconds_config); + + assert_eq!(auto_dt.to_string(), "2022-06-07T16:28:40.123000"); + assert!(matches!(always_seconds_result, Err(ParseError::DateTooLarge))); + + // Test with a timestamp that would be interpreted as seconds in both modes + let auto_dt = DateTime::from_timestamp_with_config(1654619320, 0, &auto_config).unwrap(); + let always_seconds_dt = DateTime::from_timestamp_with_config(1654619320, 0, &always_seconds_config).unwrap(); + + assert_eq!(auto_dt.to_string(), "2022-06-07T16:28:40"); + assert_eq!(always_seconds_dt.to_string(), "2022-06-07T16:28:40"); +} + + From 859d30a49ae098f0719849ec4988e7d63dbd6b8f Mon Sep 17 00:00:00 2001 From: "Chidozie C. Okafor" <39489124+doziestar@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:30:45 +0200 Subject: [PATCH 4/8] feat: Add `TimestampInterpretation` enum and update `TimeConfig` --- src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index dcbc06a..0383412 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,7 @@ mod time; pub use date::Date; pub use datetime::DateTime; pub use duration::Duration; -pub use time::{MicrosecondsPrecisionOverflowBehavior, Time, TimeConfig, TimeConfigBuilder}; +pub use time::{MicrosecondsPrecisionOverflowBehavior, Time, TimeConfig, TimeConfigBuilder, TimestampInterpretation}; pub use numbers::{float_parse_bytes, float_parse_str, int_parse_bytes, int_parse_str, IntFloat}; @@ -142,6 +142,8 @@ pub enum ParseError { DateTooLarge, /// numeric times may not exceed 86,399 seconds TimeTooLarge, + + } #[derive(Debug, Display, EnumMessage, PartialEq, Eq, Clone)] @@ -149,6 +151,8 @@ pub enum ParseError { pub enum ConfigError { // SecondsPrecisionOverflowBehavior string representation, must be one of "error" or "truncate" UnknownMicrosecondsPrecisionOverflowBehaviorString, + // Unknown timestamp interpretation string, must be one of "error", "truncate" or "ignore" + UnknownTimestampInterpretationString, } /// Used internally to write numbers to a buffer for `Display` of speedate types From 27aec42fd813ea86dd80c50e4803bcd4901d5beb Mon Sep 17 00:00:00 2001 From: "Chidozie C. Okafor" <39489124+doziestar@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:45:26 +0200 Subject: [PATCH 5/8] Fix missing newline at end of file in tests/main.rs --- tests/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/main.rs b/tests/main.rs index 078a100..a121a36 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -1476,6 +1476,4 @@ fn test_timestamp_interpretation() { assert_eq!(auto_dt.to_string(), "2022-06-07T16:28:40"); assert_eq!(always_seconds_dt.to_string(), "2022-06-07T16:28:40"); -} - - +} \ No newline at end of file From bd908b804fdcc345f7af5c0fbfbdd02a06035570 Mon Sep 17 00:00:00 2001 From: "Chidozie C. Okafor" <39489124+doziestar@users.noreply.github.com> Date: Tue, 25 Jun 2024 19:02:48 +0200 Subject: [PATCH 6/8] fix newline --- .DS_Store | Bin 0 -> 6148 bytes src/datetime.rs | 3 +-- src/lib.rs | 2 -- src/time.rs | 45 ++++++++++++++++++++++----------------------- tests/main.rs | 3 +-- 5 files changed, 24 insertions(+), 29 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9411db96d46de1ae79cb116131d77ca7ea9bcad3 GIT binary patch literal 6148 zcmeHKF=_)r43uIA3~pSe+%Mz@i*a7y4}{oB6)@zS{;IsoPs@xXg3WP|CQTTDG`n-s zE;q&LWM;noJU*Ij%xncG+84vr_?$kmyJCpWGls*<>GY1J-A|Hd2-Yraun#-D9k1)p z_6quJ!!E3P^!}rGPJY``s3=RK0cba_qGY{tRc%1x~{{N)VzQ1EU>d g!*=`-NtxHU#`9h{CPq2 Result { - Self::from_timestamp_with_config( - timestamp, - timestamp_microsecond, - &TimeConfigBuilder::new().build(), - ) + Self::from_timestamp_with_config(timestamp, timestamp_microsecond, &TimeConfigBuilder::new().build()) } /// Like `from_timestamp` but with a `TimeConfig` @@ -277,33 +273,36 @@ impl Time { timestamp_microsecond: u32, config: &TimeConfig, ) -> Result { - let (mut second, mut microsecond) = match config.timestamp_interpretation { + let (seconds, additional_microseconds) = match config.timestamp_interpretation { TimestampInterpretation::Auto => { - if timestamp > 20_000_000_000 { - ((timestamp / 1000) as u32, ((timestamp % 1000) * 1000) as u32) + if timestamp.abs() > 20_000_000_000 { + (timestamp / 1000, ((timestamp % 1000) * 1000) as u32) } else { - (timestamp as u32, timestamp_microsecond) + (timestamp, 0) } - }, - TimestampInterpretation::AlwaysSeconds => (timestamp as u32, timestamp_microsecond), + } + TimestampInterpretation::AlwaysSeconds => (timestamp, 0), }; - if microsecond >= 1_000_000 { - second = second - .checked_add(microsecond / 1_000_000) - .ok_or(ParseError::TimeTooLarge)?; - microsecond %= 1_000_000; - } + let total_microseconds = timestamp_microsecond.saturating_add(additional_microseconds); + let additional_seconds = total_microseconds / 1_000_000; + let final_microseconds = total_microseconds % 1_000_000; + + let total_seconds = seconds + .checked_add(additional_seconds as i64) + .ok_or(ParseError::TimeTooLarge)?; - if second >= 86_400 { + if !(0..86_400).contains(&total_seconds) { return Err(ParseError::TimeTooLarge); } + let total_seconds = total_seconds as u32; + Ok(Self { - hour: (second / 3600) as u8, - minute: ((second % 3600) / 60) as u8, - second: (second % 60) as u8, - microsecond, + hour: (total_seconds / 3600) as u8, + minute: ((total_seconds % 3600) / 60) as u8, + second: (total_seconds % 60) as u8, + microsecond: final_microseconds, tz_offset: config.unix_timestamp_offset, }) } @@ -697,4 +696,4 @@ impl TimeConfigBuilder { timestamp_interpretation: self.timestamp_interpretation.unwrap_or_default(), } } -} \ No newline at end of file +} diff --git a/tests/main.rs b/tests/main.rs index a121a36..fafd175 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -450,7 +450,6 @@ fn datetime_from_timestamp_specific() { } } - #[test] fn datetime_watershed() { let config = TimeConfigBuilder::new() @@ -1476,4 +1475,4 @@ fn test_timestamp_interpretation() { assert_eq!(auto_dt.to_string(), "2022-06-07T16:28:40"); assert_eq!(always_seconds_dt.to_string(), "2022-06-07T16:28:40"); -} \ No newline at end of file +} From 05ce653d23ffff4de1b00703c44482ee6a9e7b62 Mon Sep 17 00:00:00 2001 From: "Chidozie C. Okafor" <39489124+doziestar@users.noreply.github.com> Date: Tue, 25 Jun 2024 19:12:47 +0200 Subject: [PATCH 7/8] feat: Add tests for enum --- tests/main.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/main.rs b/tests/main.rs index fafd175..485d801 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -1476,3 +1476,52 @@ fn test_timestamp_interpretation() { assert_eq!(auto_dt.to_string(), "2022-06-07T16:28:40"); assert_eq!(always_seconds_dt.to_string(), "2022-06-07T16:28:40"); } + +#[test] +fn test_timestamp_interpretation_try_from() { + use speedate::{ConfigError, TimestampInterpretation}; + + // Test valid inputs + assert_eq!( + TimestampInterpretation::try_from("auto"), + Ok(TimestampInterpretation::Auto) + ); + assert_eq!( + TimestampInterpretation::try_from("Auto"), + Ok(TimestampInterpretation::Auto) + ); + assert_eq!( + TimestampInterpretation::try_from("AUTO"), + Ok(TimestampInterpretation::Auto) + ); + assert_eq!( + TimestampInterpretation::try_from("always_seconds"), + Ok(TimestampInterpretation::AlwaysSeconds) + ); + assert_eq!( + TimestampInterpretation::try_from("Always_Seconds"), + Ok(TimestampInterpretation::AlwaysSeconds) + ); + assert_eq!( + TimestampInterpretation::try_from("ALWAYS_SECONDS"), + Ok(TimestampInterpretation::AlwaysSeconds) + ); + + // Test invalid inputs + assert_eq!( + TimestampInterpretation::try_from("invalid"), + Err(ConfigError::UnknownTimestampInterpretationString) + ); + assert_eq!( + TimestampInterpretation::try_from(""), + Err(ConfigError::UnknownTimestampInterpretationString) + ); + assert_eq!( + TimestampInterpretation::try_from("autoX"), + Err(ConfigError::UnknownTimestampInterpretationString) + ); + assert_eq!( + TimestampInterpretation::try_from("always_secondsX"), + Err(ConfigError::UnknownTimestampInterpretationString) + ); +} From a1214970bdf4235330333d31dff5f1e93b626811 Mon Sep 17 00:00:00 2001 From: "Chidozie C. Okafor" <39489124+doziestar@users.noreply.github.com> Date: Tue, 25 Jun 2024 19:19:57 +0200 Subject: [PATCH 8/8] Test the specific case where timestamp is divided and multiplied --- tests/main.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/main.rs b/tests/main.rs index 485d801..4cf747e 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -1475,6 +1475,13 @@ fn test_timestamp_interpretation() { assert_eq!(auto_dt.to_string(), "2022-06-07T16:28:40"); assert_eq!(always_seconds_dt.to_string(), "2022-06-07T16:28:40"); + + // Test the specific case where timestamp is divided and multiplied + let auto_dt = DateTime::from_timestamp_with_config(20_000_000_001, 0, &auto_config).unwrap(); + assert_eq!(auto_dt.to_string(), "1970-08-20T11:33:20.001000"); + + let always_seconds_dt = DateTime::from_timestamp_with_config(20_000_000_001, 0, &always_seconds_config).unwrap(); + assert_eq!(always_seconds_dt.to_string(), "2603-10-11T11:33:21"); } #[test]