mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
date: re-zone trailing TZ abbreviation input to local timezone (#12327)
The dedicated abbreviation-aware path `try_parse_with_abbreviation` in
`src/uu/date/src/date.rs` returned a `Zoned` in the input abbreviation
timezone (e.g. `-05` for `EST`). The generic `parse_datetime` fallback
already re-zones to `now.time_zone()` for display, so identical inputs
took two divergent code paths and only one matched GNU `date`.
GNU treats a trailing TZ abbreviation as describing the *input*
timezone; the output is always re-zoned into the local zone (or UTC
under `-u`). For example, under `TZ=UTC`:
$ date -d "2024-01-01 EST" # GNU
Mon Jan 1 05:00:00 UTC 2024
uutils previously emitted `Mon Jan 1 00:00:00 -05 2024`.
Convert the parsed instant to `now.time_zone()` before returning,
matching the fallback path and GNU’s behavior. `-u` still works
because `now` is already zoned to UTC in that case (date.rs:362),
and the final output stage still applies `with_time_zone(TimeZone::UTC)`
when `settings.utc` is set.
Un-ignores the existing regression test for this issue.
Fixes uutils/parse_datetime#281.
This commit is contained in:
@@ -853,11 +853,17 @@ fn try_parse_with_abbreviation<S: AsRef<str>>(date_str: S, now: &Zoned) -> Optio
|
||||
|
||||
if let Some(tz) = tz {
|
||||
let date_part = s.trim_end_matches(last_word).trim();
|
||||
// Parse in the target timezone so "10:30 EDT" means 10:30 in EDT
|
||||
// Parse in the target timezone so "10:30 EDT" means 10:30 in EDT.
|
||||
if let Ok(parsed) = parse_datetime::parse_datetime_at_date(now.clone(), date_part) {
|
||||
let dt = parsed.datetime();
|
||||
if let Ok(zoned) = dt.to_zoned(tz) {
|
||||
return Some(zoned);
|
||||
// The trailing abbreviation only describes the *input*
|
||||
// timezone. For display, re-zone to the system timezone
|
||||
// (i.e. `now`'s zone, which is UTC under `-u`). This
|
||||
// matches GNU `date` and keeps this path consistent
|
||||
// with the generic `parse_datetime` fallback below,
|
||||
// which already re-zones via `to_zoned(now.time_zone())`.
|
||||
return Some(zoned.with_time_zone(now.time_zone().clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1873,10 +1873,12 @@ fn test_date_input_hhmm_ampm() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "https://github.com/uutils/parse_datetime/issues/281 — GNU date re-zones input with trailing TZ abbreviation (e.g. `2024-01-01 EST`) into the local TZ; uutils keeps the input TZ on output."]
|
||||
fn test_date_input_trailing_tz_abbrev_rezones() {
|
||||
// `TZ=UTC+1 date -d '2024-01-01 EST'` should display the instant in UTC+1
|
||||
// (GNU: 04:00:00 UTC), not leave it in EST (uutils: 00:00:00 -05).
|
||||
// (GNU: 04:00:00 -01:00), not leave it in EST (the pre-fix uutils
|
||||
// behavior was 00:00:00 -05). The trailing abbreviation only specifies
|
||||
// the input timezone; output should be re-zoned to local.
|
||||
// Regression test for https://github.com/uutils/parse_datetime/issues/281.
|
||||
new_ucmd!()
|
||||
.env("LC_ALL", "C")
|
||||
.env("TZ", "UTC+1")
|
||||
|
||||
Reference in New Issue
Block a user