Skip to content

Commit

Permalink
raise DateNotExact error for millisecond timestamps (#67)
Browse files Browse the repository at this point in the history
* raise `DateNotExact` error for millisecond timestamps

* adjust variable names
  • Loading branch information
davidhewitt committed Jun 26, 2024
1 parent 9bbeebb commit 72f1c79
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 13 deletions.
15 changes: 6 additions & 9 deletions src/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,10 @@ impl Date {
/// assert_eq!(d.to_string(), "2022-06-07");
/// ```
pub fn from_timestamp(timestamp: i64, require_exact: bool) -> Result<Self, ParseError> {
let (timestamp_second, _) = Self::timestamp_watershed(timestamp)?;
let d = Self::from_timestamp_calc(timestamp_second)?;
if require_exact {
let time_second = timestamp_second.rem_euclid(86_400);
if time_second != 0 {
return Err(ParseError::DateNotExact);
}
let (seconds, microseconds) = Self::timestamp_watershed(timestamp)?;
let (d, remaining_seconds) = Self::from_timestamp_calc(seconds)?;
if require_exact && (remaining_seconds != 0 || microseconds != 0) {
return Err(ParseError::DateNotExact);
}
Ok(d)
}
Expand Down Expand Up @@ -287,7 +284,7 @@ impl Date {
Ok((seconds, microseconds as u32))
}

pub(crate) fn from_timestamp_calc(timestamp_second: i64) -> Result<Self, ParseError> {
pub(crate) fn from_timestamp_calc(timestamp_second: i64) -> Result<(Self, u32), ParseError> {
if timestamp_second < UNIX_1600 {
return Err(ParseError::DateTooSmall);
}
Expand All @@ -312,7 +309,7 @@ impl Date {
true => leap_year_month_day(ordinal_day),
false => common_year_month_day(ordinal_day),
};
Ok(Self { year, month, day })
Ok((Self { year, month, day }, (timestamp_second.rem_euclid(86_400)) as u32))
}

/// Parse a date from bytes, no check is performed for extract characters at the end of the string
Expand Down
4 changes: 1 addition & 3 deletions src/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,7 @@ impl DateTime {
.ok_or(ParseError::TimeTooLarge)?;
total_microsecond %= 1_000_000;
}
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 (date, time_second) = Date::from_timestamp_calc(second)?;
Ok(Self {
date,
time: Time::from_timestamp_with_config(time_second, total_microsecond, config)?,
Expand Down
12 changes: 11 additions & 1 deletion tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ fn date_comparison() {
}

#[test]
fn date_timestamp() {
fn date_timestamp_exact() {
let d = Date::from_timestamp(1_654_560_000, true).unwrap();
assert_eq!(d.to_string(), "2022-06-07");
assert_eq!(d.timestamp(), 1_654_560_000);
Expand All @@ -239,6 +239,16 @@ fn date_timestamp() {
Ok(d) => panic!("unexpectedly valid, {d}"),
Err(e) => assert_eq!(e, ParseError::DateNotExact),
}

// milliseconds
let d = Date::from_timestamp(1_654_560_000_000, true).unwrap();
assert_eq!(d.to_string(), "2022-06-07");
assert_eq!(d.timestamp(), 1_654_560_000);

match Date::from_timestamp(1_654_560_000_001, true) {
Ok(d) => panic!("unexpectedly valid, {d}"),
Err(e) => assert_eq!(e, ParseError::DateNotExact),
}
}

macro_rules! date_from_timestamp {
Expand Down

0 comments on commit 72f1c79

Please sign in to comment.