diff --git a/src/uucore/src/lib/features/fsext.rs b/src/uucore/src/lib/features/fsext.rs index 0d64661ee..3f5b2b77c 100644 --- a/src/uucore/src/lib/features/fsext.rs +++ b/src/uucore/src/lib/features/fsext.rs @@ -13,6 +13,7 @@ extern crate time; use time::macros::format_description; +use time::UtcOffset; pub use crate::*; // import macros from `../../macros.rs` @@ -733,16 +734,36 @@ where } // match strftime "%Y-%m-%d %H:%M:%S.%f %z" -const PRETTY_DATETIME_FORMAT: &[time::format_description::FormatItem] = format_description!("[year]-[month]-[day padding:zero] [hour]:[minute]:[second].[subsecond] [offset_hour sign:mandatory][offset_minute]"); +const PRETTY_DATETIME_FORMAT: &[time::format_description::FormatItem] = format_description!("[year]-[month]-[day padding:zero] [hour]:[minute]:[second].[subsecond digits:9] [offset_hour sign:mandatory][offset_minute]"); pub fn pretty_time(sec: i64, nsec: i64) -> String { // sec == seconds since UNIX_EPOCH // nsec == nanoseconds since (UNIX_EPOCH + sec) let ts_nanos: i128 = (sec * 1_000_000_000 + nsec).into(); - // TODO: return errors to caller - let tm = time::OffsetDateTime::from_unix_timestamp_nanos(ts_nanos).unwrap(); - let res = tm.format(&PRETTY_DATETIME_FORMAT).unwrap(); + // Return the date in UTC + let tm = match time::OffsetDateTime::from_unix_timestamp_nanos(ts_nanos) { + Ok(tm) => tm, + Err(e) => { + panic!("error: {}", e); + } + }; + + // Get the offset to convert to local time + // Because of DST (daylight saving), we get the local time back when + // the date was set + let local_offset = match UtcOffset::local_offset_at(tm) { + Ok(lo) => lo, + Err(e) => { + panic!("error: {}", e); + } + }; + + // Include the conversion to local time + let res = tm + .to_offset(local_offset) + .format(&PRETTY_DATETIME_FORMAT) + .unwrap(); if res.ends_with(" -0000") { res.replace(" -0000", " +0000") } else { diff --git a/tests/by-util/test_stat.rs b/tests/by-util/test_stat.rs index 6140f5017..0871a48fe 100644 --- a/tests/by-util/test_stat.rs +++ b/tests/by-util/test_stat.rs @@ -292,7 +292,22 @@ fn test_date() { #[cfg(any(target_os = "linux", target_os = "android"))] "%z", #[cfg(target_os = "linux")] - "/dev/pts/ptmx", + "/bin/sh", + #[cfg(any(target_vendor = "apple"))] + "%z", + #[cfg(any(target_os = "android", target_vendor = "apple"))] + "/bin/sh", + ]; + let ts = TestScenario::new(util_name!()); + let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str(); + ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout); + // Just test the date for the time 0.3 change + let args = [ + "-c", + #[cfg(any(target_os = "linux", target_os = "android"))] + "%z", + #[cfg(target_os = "linux")] + "/dev/ptmx", #[cfg(any(target_vendor = "apple"))] "%z", #[cfg(any(target_os = "android", target_vendor = "apple"))]