From e52fe3a7e16cb92f1eda9c11b8343845e32aeb7e Mon Sep 17 00:00:00 2001 From: Asifur Rahaman Meeru Date: Sun, 11 Oct 2026 12:17:26 +0600 Subject: [PATCH 1/2] fix(offset): correct ADT, AST, BST, GST and SST to GNU's values The table is meant to cover the same abbreviations GNU date supports, but five of them resolved to a different offset than GNU date gives, so "2026-06-15 12:00 BST" parsed as +06:00 (Bangladesh) rather than +01:00 (British Summer Time). Offsets were measured with `date --debug` on GNU coreutils 9.10: ADT is -3, AST -4, BST +1, GST +10 and SST -12. --- src/items/offset.rs | 16 +++++++++++----- tests/date.rs | 13 +++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/items/offset.rs b/src/items/offset.rs index 4268919..e8afed5 100644 --- a/src/items/offset.rs +++ b/src/items/offset.rs @@ -298,7 +298,7 @@ fn timezone_name_to_offset(input: &str) -> ModalResult { "ut" => (false, 0, 0), "u" => (true, 8, 0), "t" => (true, 7, 0), - "sst" => (true, 11, 0), + "sst" => (true, 12, 0), "sgt" => (false, 8, 0), "sast" => (false, 2, 0), "s" => (true, 6, 0), @@ -329,7 +329,7 @@ fn timezone_name_to_offset(input: &str) -> ModalResult { "i" => (false, 9, 0), "hst" => (true, 10, 0), "h" => (false, 8, 0), - "gst" => (false, 4, 0), + "gst" => (false, 10, 0), "gmt" => (false, 0, 0), "g" => (false, 7, 0), "f" => (false, 6, 0), @@ -348,15 +348,15 @@ fn timezone_name_to_offset(input: &str) -> ModalResult { "cdt" => (true, 5, 0), "cat" => (false, 2, 0), "c" => (false, 3, 0), - "bst" => (false, 6, 0), + "bst" => (false, 1, 0), "brt" => (true, 3, 0), "brst" => (true, 2, 0), "b" => (false, 2, 0), - "ast" => (true, 3, 0), + "ast" => (true, 4, 0), "art" => (true, 3, 0), "akst" => (true, 9, 0), "akdt" => (true, 8, 0), - "adt" => (false, 4, 0), + "adt" => (true, 3, 0), "a" => (false, 1, 0), _ => return Err(ErrMode::Backtrack(ContextError::new())), }; @@ -459,6 +459,12 @@ mod tests { ("mesz", off(false, 2, 0)), ("mest", off(false, 2, 0)), ("kst", off(false, 9, 0)), + // Corrected to the offsets GNU date assigns these abbreviations. + ("adt", off(true, 3, 0)), // Atlantic Daylight, was +4 + ("ast", off(true, 4, 0)), // Atlantic Standard, was -3 + ("bst", off(false, 1, 0)), // British Summer, was +6 + ("gst", off(false, 10, 0)), // Guam Standard, was +4 + ("sst", off(true, 12, 0)), // was -11 ("z123", off(false, 0, 0)), // space separator can be ignored if immediately followed by digits (GNU date behavior) ] { let mut s = input; diff --git a/tests/date.rs b/tests/date.rs index 5c745e5..6d81d4c 100644 --- a/tests/date.rs +++ b/tests/date.rs @@ -298,6 +298,19 @@ fn test_embedded_timezone(#[case] input: &str, #[case] expected: &str) { check_absolute(input, expected); } +// Zone abbreviations must resolve to the offsets GNU date assigns them, +// not to other real meanings of the same letters, e.g. BST as Bangladesh +// Standard Time rather than British Summer Time. +#[rstest] +#[case::bst("2026-06-15 12:00 BST", "2026-06-15 12:00:00+01:00")] +#[case::gst("2026-06-15 12:00 GST", "2026-06-15 12:00:00+10:00")] +#[case::ast("2026-06-15 12:00 AST", "2026-06-15 12:00:00-04:00")] +#[case::adt("2026-06-15 12:00 ADT", "2026-06-15 12:00:00-03:00")] +#[case::sst("2026-06-15 12:00 SST", "2026-06-15 12:00:00-12:00")] +fn test_zone_abbreviation_offsets(#[case] input: &str, #[case] expected: &str) { + check_absolute(input, expected); +} + // Regression test for uutils/coreutils#12555. // A fixed offset (e.g. the "UTC" keyword) must anchor the instant *before* // relative adjustments are applied. Otherwise, when the base zone observes DST, From 000c30dd8ad45a51125016d41018f8c6e7ec3097 Mon Sep 17 00:00:00 2001 From: CodSpeed Bot Date: Sun, 11 Oct 2026 07:25:59 +0000 Subject: [PATCH 2/2] bench: pin parse_weekday to a fixed reference date The weekday benchmark parsed "wednesday" relative to the current date, so its cost depended on which day of the week CI ran (no date shift on a Wednesday, a multi-day shift otherwise), producing spurious regressions. --- benches/parse_datetime.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/benches/parse_datetime.rs b/benches/parse_datetime.rs index d5dd900..6aff803 100644 --- a/benches/parse_datetime.rs +++ b/benches/parse_datetime.rs @@ -55,7 +55,16 @@ fn bench_relative_keywords(c: &mut Criterion) { } fn bench_weekday(c: &mut Criterion) { - c.bench_function("parse_weekday", |b| b.iter(|| parse_datetime("wednesday"))); + // Use a fixed reference date: the cost of resolving a weekday depends on + // how many days separate it from "today", so relying on the current date + // makes the measurement vary with the day the benchmark runs. + // 2000-01-03 is a Monday, so "wednesday" resolves two days ahead. + let base = jiff::civil::DateTime::from(jiff::civil::date(2000, 1, 3)) + .to_zoned(jiff::tz::TimeZone::UTC) + .unwrap(); + c.bench_function("parse_weekday", |b| { + b.iter(|| parse_datetime_at_date(base.clone(), "wednesday")) + }); } fn bench_timezone_offset(c: &mut Criterion) {