mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37: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::fs::{self, File};
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::process;
|
||||||
|
|
||||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
static ABOUT: &str = "Update the access and modification times of each FILE to the current time.";
|
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) {
|
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),
|
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 {
|
fn str_to_filetime(format: &str, s: &str) -> FileTime {
|
||||||
let mut tm = time::strptime(s, format).unwrap();
|
let mut tm = time::strptime(s, format).unwrap();
|
||||||
tm.tm_utcoff = time::now().tm_utcoff;
|
tm.tm_utcoff = time::now().tm_utcoff;
|
||||||
|
tm.tm_isdst = -1; // Unknown flag DST
|
||||||
let ts = tm.to_timespec();
|
let ts = tm.to_timespec();
|
||||||
FileTime::from_unix_time(ts.sec as i64, ts.nsec as u32)
|
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!(atime, start_of_year);
|
||||||
assert_eq!(mtime, 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