mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
touch: dealing with DST in touch -m -t (#2073)
This commit is contained in:
parent
f33320e581
commit
fe207640e2
2 changed files with 41 additions and 1 deletions
|
@ -18,6 +18,7 @@ use filetime::*;
|
|||
use std::fs::{self, File};
|
||||
use std::io::Error;
|
||||
use std::path::Path;
|
||||
use std::process;
|
||||
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
static ABOUT: &str = "Update the access and modification times of each FILE to the current time.";
|
||||
|
@ -261,7 +262,27 @@ fn parse_timestamp(s: &str) -> FileTime {
|
|||
};
|
||||
|
||||
match time::strptime(&ts, format) {
|
||||
Ok(tm) => local_tm_to_filetime(to_local(tm)),
|
||||
Ok(tm) => {
|
||||
let mut local = to_local(tm);
|
||||
local.tm_isdst = -1;
|
||||
let ft = local_tm_to_filetime(local);
|
||||
|
||||
// We have to check that ft is valid time. Due to daylight saving
|
||||
// time switch, local time can jump from 1:59 AM to 3:00 AM,
|
||||
// in which case any time between 2:00 AM and 2:59 AM is not valid.
|
||||
// Convert back to local time and see if we got the same value back.
|
||||
let ts = time::Timespec {
|
||||
sec: ft.unix_seconds(),
|
||||
nsec: 0,
|
||||
};
|
||||
let tm2 = time::at(ts);
|
||||
if tm.tm_hour != tm2.tm_hour {
|
||||
show_error!("invalid date format {}", s);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
ft
|
||||
}
|
||||
Err(e) => panic!("Unable to parse timestamp\n{}", e),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ fn set_file_times(at: &AtPath, path: &str, atime: FileTime, mtime: FileTime) {
|
|||
fn str_to_filetime(format: &str, s: &str) -> FileTime {
|
||||
let mut tm = time::strptime(s, format).unwrap();
|
||||
tm.tm_utcoff = time::now().tm_utcoff;
|
||||
tm.tm_isdst = -1; // Unknown flag DST
|
||||
let ts = tm.to_timespec();
|
||||
FileTime::from_unix_time(ts.sec as i64, ts.nsec as u32)
|
||||
}
|
||||
|
@ -352,3 +353,21 @@ fn test_touch_set_date() {
|
|||
assert_eq!(atime, start_of_year);
|
||||
assert_eq!(mtime, start_of_year);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_touch_mtime_dst_succeeds() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file = "test_touch_set_mtime_dst_succeeds";
|
||||
|
||||
ucmd.args(&["-m", "-t", "202103140300", file])
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file));
|
||||
|
||||
let target_time = str_to_filetime("%Y%m%d%H%M", "202103140300");
|
||||
let (_, mtime) = get_file_times(&at, file);
|
||||
eprintln!("target_time: {:?}", target_time);
|
||||
eprintln!("mtime: {:?}", mtime);
|
||||
assert!(target_time == mtime);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue