Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/items/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,10 @@ impl DateTimeBuilder {
.ok()?;
}

if let Some(offset) = &self.timezone {
dt = dt.datetime().to_zoned(offset.try_into().ok()?).ok()?;
if let Some(offset) = self.timezone {
let (offset, hour_adjustment) = offset.normalize();
dt = dt.checked_add(Span::new().hours(hour_adjustment)).ok()?;
dt = dt.datetime().to_zoned((&offset).try_into().ok()?).ok()?;
}

Some(dt)
Expand Down
24 changes: 24 additions & 0 deletions src/items/timezone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,30 @@ impl Offset {
minutes,
}
}

/// Normalize the offset so that the hour field is within the accepted range.
///
/// - If the hour field is less than 24, or exactly 24 with a zero minute,
/// the offset is already normalized, and the function returns the offset
/// itself along with a zero hour adjustment.
/// - Otherwise, the hour field is reduced to 23 while preserving the minute
/// field, and the function returns the normalized offset along with the
/// hour adjustment needed to reach the original offset.
pub(super) fn normalize(self) -> (Offset, i8) {
if self.hours < 24 || (self.hours == 24 && self.minutes == 0) {
return (self, 0);
}

let hour_adjustment = (self.hours as i8 - 23) * if self.negative { 1 } else { -1 };
(
Offset {
negative: self.negative,
hours: 23,
minutes: self.minutes,
},
hour_adjustment,
)
}
}

impl TryFrom<(bool, u8, u8)> for Offset {
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ mod tests {

#[test]
fn offset_overflow() {
assert!(parse_datetime("m+14").is_err());
assert!(parse_datetime("m+25").is_err());
assert!(parse_datetime("24:00").is_err());
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ fn test_time_correction(#[case] input: &str, #[case] expected: &str) {
#[case::minus_12("12:34:56-12:00", "2022-06-11 00:34:56")]
#[case::plus_1259("12:34:56+12:59", "2022-06-09 23:35:56")]
#[case::minus_1259("12:34:56-12:59", "2022-06-11 01:33:56")]
/* TODO: https://github.com/uutils/parse_datetime/issues/149
#[case::plus_24("12:34:56+24:00", "2022-06-09 12:34:56")]
#[case::minus_24("12:34:56-24:00", "2022-06-11 12:34:56")]
#[case::plus_13("11:34:56+13:00", "2022-06-09 22:34:56")]
#[case::minus_13("12:34:56-13:00", "2022-06-11 01:34:56")]
*/
#[case::plus_36("12:34:56 m+24", "2022-06-09 00:34:56")]
#[case::minus_36("12:34:56 y-24:00", "2022-06-12 00:34:56")]
fn test_time_correction_with_overflow(#[case] input: &str, #[case] expected: &str) {
let now = "2022-06-10 00:00:00"
.parse::<DateTime>()
Expand Down
Loading