fix: time offset can only appear after time or timezone

This commit is contained in:
yuankunzhang
2025-07-18 14:51:20 +00:00
parent 6499842e15
commit 8bebfab576
4 changed files with 20 additions and 50 deletions
+2 -5
View File
@@ -311,17 +311,14 @@ mod tests {
let result = parse(&mut "2025-05-19 +00:00 +01:00");
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("timezone cannot appear more than once"));
assert!(result.unwrap_err().to_string().contains("unexpected input"));
let result = parse(&mut "m1y");
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("time offset and timezone are mutually exclusive"));
.contains("timezone cannot appear more than once"));
let result = parse(&mut "2025-05-19 abcdef");
assert!(result.is_err());
+18 -6
View File
@@ -157,7 +157,7 @@ pub fn parse(input: &mut &str) -> ModalResult<Time> {
/// Also used by the [`combined`](super::combined) module
pub fn iso(input: &mut &str) -> ModalResult<Time> {
alt((
(hour24, timezone).map(|(hour, offset)| Time {
(hour24, timezone_num).map(|(hour, offset)| Time {
hour,
minute: 0,
second: 0.0,
@@ -168,7 +168,7 @@ pub fn iso(input: &mut &str) -> ModalResult<Time> {
_: colon,
minute: minute,
second: opt(preceded(colon, second)).map(|s| s.unwrap_or(0.0)),
offset: opt(timezone)
offset: opt(timezone_num)
}),
))
.parse_next(input)
@@ -244,7 +244,7 @@ fn second(input: &mut &str) -> ModalResult<f64> {
}
pub(crate) fn timezone(input: &mut &str) -> ModalResult<Offset> {
alt((timezone_num, timezone_name_offset)).parse_next(input)
timezone_name_offset.parse_next(input)
}
/// Parse a timezone starting with `+` or `-`
@@ -864,13 +864,25 @@ mod tests {
.expect("expect tests to succeed")
};
assert_eq!("+00:00", make_timezone(&mut "+00:00"));
assert_eq!("+00:00", make_timezone(&mut "+0000"));
assert_eq!("-00:00", make_timezone(&mut "-0000"));
assert_eq!("+00:00", make_timezone(&mut "gmt"));
assert_eq!("+01:00", make_timezone(&mut "a"));
assert_eq!("+00:00", make_timezone(&mut "utc"));
assert_eq!("-02:00", make_timezone(&mut "brst"));
assert_eq!("-03:00", make_timezone(&mut "brt"));
}
#[test]
fn test_timezone_num() {
use super::timezone_num;
let make_timezone = |input: &mut &str| {
timezone_num(input)
.map_err(|e| eprintln!("TEST FAILED AT:\n{e}"))
.map(|offset| format!("{offset}"))
.expect("expect tests to succeed")
};
assert_eq!("+00:00", make_timezone(&mut "+00:00"));
assert_eq!("+00:00", make_timezone(&mut "+0000"));
assert_eq!("-00:00", make_timezone(&mut "-0000"));
}
}
-37
View File
@@ -233,8 +233,6 @@ mod tests {
"Z+07:00",
"Z+0700",
"Z+07",
"+07",
"+7",
];
let expected = format!("{}{}", Local::now().format("%Y%m%d"), "0000+0700");
@@ -389,21 +387,6 @@ mod tests {
}
}
#[cfg(test)]
mod timeonly {
use crate::parse_datetime_at_date;
use chrono::{Local, TimeZone};
use std::env;
#[test]
fn test_time_only() {
env::set_var("TZ", "UTC");
let test_date = Local.with_ymd_and_hms(2024, 3, 3, 0, 0, 0).unwrap();
let parsed_time = parse_datetime_at_date(test_date, "9:04:30 PM +0530")
.unwrap()
.timestamp();
assert_eq!(parsed_time, 1709480070);
}
}
/// Used to test example code presented in the README.
mod readme_test {
use crate::parse_datetime;
@@ -470,8 +453,6 @@ mod tests {
"1997-01-01 00:00:00 +0000",
"1997-01-01 00:00:00 +00",
"199701010000 +0000",
"199701010000UTC+0000",
"199701010000Z+0000",
"1997-01-01 00:00 +0000",
"1997-01-01 00:00:00 +0000",
"1997-01-01T00:00:00+0000",
@@ -538,8 +519,6 @@ mod tests {
"1997-01-01 00:00:00 +0000 +1 year",
"1997-01-01 00:00:00 +00 +1 year",
"199701010000 +0000 +1 year",
"199701010000UTC+0000 +1 year",
"199701010000Z+0000 +1 year",
"1997-01-01T00:00:00Z +1 year",
"1997-01-01 00:00 +0000 +1 year",
"1997-01-01 00:00:00 +0000 +1 year",
@@ -602,22 +581,6 @@ mod tests {
}
}
#[test]
fn test_time_only() {
use chrono::{FixedOffset, Local};
std::env::set_var("TZ", "UTC");
let offset = FixedOffset::east_opt(5 * 60 * 60 + 1800).unwrap();
let expected = Local::now()
.date_naive()
.and_hms_opt(21, 4, 30)
.unwrap()
.and_local_timezone(offset)
.unwrap();
let actual = crate::parse_datetime("9:04:30 PM +0530").unwrap();
assert_eq!(actual, expected);
}
#[test]
fn test_weekday_only() {
use chrono::{Datelike, Days, Local, MappedLocalTime, NaiveTime, Weekday};
-2
View File
@@ -113,9 +113,7 @@ fn test_time_correction_with_overflow(#[case] input: &str, #[case] expected: &st
#[case("23:59:59 pm.")]
#[case("23:59:59+24:01")]
#[case("23:59:59-24:01")]
/* TODO: https://github.com/uutils/parse_datetime/issues/166
#[case("10:59am+01")]
*/
#[case("10:59+01pm")]
#[case("23:59:59+00:00:00")]
fn test_time_invalid(#[case] input: &str) {