1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

touch: improve the -d option support of other dates

This commit is contained in:
Sylvestre Ledru 2022-05-05 22:48:37 +02:00
parent 65d0f5ba9f
commit 06ef89b3d8
2 changed files with 25 additions and 10 deletions

View file

@ -16,7 +16,7 @@ use clap::{crate_version, Arg, ArgGroup, Command};
use filetime::*;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use time::macros::{format_description, time};
use time::macros::{format_description, offset, time};
use time::Duration;
use uucore::display::Quotable;
use uucore::error::{FromIo, UError, UResult, USimpleError};
@ -42,6 +42,7 @@ pub mod options {
static ARG_FILES: &str = "files";
// Convert a date/time to a date with a TZ offset
fn to_local(tm: time::PrimitiveDateTime) -> time::OffsetDateTime {
let offset = match time::OffsetDateTime::now_local() {
Ok(lo) => lo.offset(),
@ -52,10 +53,18 @@ fn to_local(tm: time::PrimitiveDateTime) -> time::OffsetDateTime {
tm.assume_offset(offset)
}
// Convert a date/time with a TZ offset into a FileTime
fn local_dt_to_filetime(dt: time::OffsetDateTime) -> FileTime {
FileTime::from_unix_time(dt.unix_timestamp(), dt.nanosecond())
}
// Convert a date/time, considering that the input is in UTC time
// Used for touch -d 1970-01-01 18:43:33.023456789 for example
fn dt_to_filename(tm: time::PrimitiveDateTime) -> FileTime {
let dt = tm.assume_offset(offset!(UTC));
local_dt_to_filetime(dt)
}
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().get_matches_from(args);
@ -310,15 +319,15 @@ fn parse_date(s: &str) -> UResult<FileTime> {
// Tue Dec 3 ...
// ("%c", POSIX_LOCALE_FORMAT),
//
// But also support other format found in the GNU tests like
if let Ok(parsed) = time::PrimitiveDateTime::parse(s, &POSIX_LOCALE_FORMAT) {
return Ok(local_dt_to_filetime(to_local(parsed)));
}
// Also support other formats found in the GNU tests like
// in tests/misc/stat-nanoseconds.sh
for fmt in [
POSIX_LOCALE_FORMAT,
YYYYMMDDHHMMS_FORMAT,
YYYYMMDDHHMMSS_FORMAT,
] {
for fmt in [YYYYMMDDHHMMS_FORMAT, YYYYMMDDHHMMSS_FORMAT] {
if let Ok(parsed) = time::PrimitiveDateTime::parse(s, &fmt) {
return Ok(local_dt_to_filetime(to_local(parsed)));
return Ok(dt_to_filename(parsed));
}
}

View file

@ -438,7 +438,7 @@ fn test_touch_set_date4() {
assert!(at.file_exists(file));
let expected = FileTime::from_unix_time(60213, 0);
let expected = FileTime::from_unix_time(67413, 0);
let (atime, mtime) = get_file_times(&at, file);
assert_eq!(atime, mtime);
assert_eq!(atime, expected);
@ -456,7 +456,13 @@ fn test_touch_set_date5() {
assert!(at.file_exists(file));
let expected = FileTime::from_unix_time(60213, 023456789);
// Slightly different result on Windows for nano seconds
// TODO: investigate
#[cfg(windows)]
let expected = FileTime::from_unix_time(67413, 23456700);
#[cfg(not(windows))]
let expected = FileTime::from_unix_time(67413, 23456789);
let (atime, mtime) = get_file_times(&at, file);
assert_eq!(atime, mtime);
assert_eq!(atime, expected);