You've already forked parse_datetime
mirror of
https://github.com/uutils/parse_datetime.git
synced 2026-06-10 16:13:15 -07:00
fallible offset conversion
This commit is contained in:
+8
-3
@@ -303,7 +303,7 @@ fn with_timezone_restore(
|
||||
offset: time::Offset,
|
||||
at: DateTime<FixedOffset>,
|
||||
) -> Option<DateTime<FixedOffset>> {
|
||||
let offset: FixedOffset = chrono::FixedOffset::from(offset);
|
||||
let offset: FixedOffset = chrono::FixedOffset::try_from(offset).ok()?;
|
||||
let copy = at;
|
||||
let x = at
|
||||
.with_timezone(&offset)
|
||||
@@ -360,7 +360,9 @@ fn at_date_inner(date: Vec<Item>, mut d: DateTime<FixedOffset>) -> Option<DateTi
|
||||
},
|
||||
..
|
||||
}) => {
|
||||
let offset = offset.map(chrono::FixedOffset::from).unwrap_or(*d.offset());
|
||||
let offset = offset
|
||||
.and_then(|o| chrono::FixedOffset::try_from(o).ok())
|
||||
.unwrap_or(*d.offset());
|
||||
|
||||
d = new_date(
|
||||
year.map(|x| x as i32).unwrap_or(d.year()),
|
||||
@@ -379,7 +381,10 @@ fn at_date_inner(date: Vec<Item>, mut d: DateTime<FixedOffset>) -> Option<DateTi
|
||||
second,
|
||||
offset,
|
||||
}) => {
|
||||
let offset = offset.map(chrono::FixedOffset::from).unwrap_or(*d.offset());
|
||||
let offset = offset
|
||||
.and_then(|o| chrono::FixedOffset::try_from(o).ok())
|
||||
.unwrap_or(*d.offset());
|
||||
|
||||
d = new_date(
|
||||
d.year(),
|
||||
d.month(),
|
||||
|
||||
+21
-8
@@ -50,6 +50,8 @@ use winnow::{
|
||||
ModalResult, Parser,
|
||||
};
|
||||
|
||||
use crate::ParseDateTimeError;
|
||||
|
||||
use super::{dec_uint, relative, s};
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Default)]
|
||||
@@ -95,22 +97,33 @@ impl Offset {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Offset> for chrono::FixedOffset {
|
||||
fn from(
|
||||
impl TryFrom<Offset> for chrono::FixedOffset {
|
||||
type Error = ParseDateTimeError;
|
||||
|
||||
fn try_from(
|
||||
Offset {
|
||||
negative,
|
||||
hours,
|
||||
minutes,
|
||||
}: Offset,
|
||||
) -> Self {
|
||||
) -> Result<Self, Self::Error> {
|
||||
let secs = hours * 3600 + minutes * 60;
|
||||
|
||||
if negative {
|
||||
FixedOffset::west_opt(secs.try_into().expect("secs overflow"))
|
||||
.expect("timezone overflow")
|
||||
let offset = if negative {
|
||||
FixedOffset::west_opt(
|
||||
secs.try_into()
|
||||
.map_err(|_| ParseDateTimeError::InvalidInput)?,
|
||||
)
|
||||
.ok_or(ParseDateTimeError::InvalidInput)?
|
||||
} else {
|
||||
FixedOffset::east_opt(secs.try_into().unwrap()).unwrap()
|
||||
}
|
||||
FixedOffset::east_opt(
|
||||
secs.try_into()
|
||||
.map_err(|_| ParseDateTimeError::InvalidInput)?,
|
||||
)
|
||||
.ok_or(ParseDateTimeError::InvalidInput)?
|
||||
};
|
||||
|
||||
Ok(offset)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -266,6 +266,12 @@ mod tests {
|
||||
.and_utc();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offset_overflow() {
|
||||
assert!(parse_datetime("m+12").is_err());
|
||||
assert!(parse_datetime("24:00").is_err());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user