You've already forked parse_datetime
mirror of
https://github.com/uutils/parse_datetime.git
synced 2026-06-10 16:13:15 -07:00
Merge pull request #223 from yuankunzhang/support-timezone-offset-larger-than-24-hour
fix: support timezone offsets that exceed 24-hour range
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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>()
|
||||
|
||||
Reference in New Issue
Block a user