mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
touch: fix parse_datetime 0.13 API usage for deterministic relative dates
The previous implementation incorrectly used parse_datetime() instead of parse_datetime_at_date(), causing relative date strings like 'yesterday' or '2 days ago' to be calculated from the current system time instead of the caller-specified reference time. This fix: - Uses parse_datetime_at_date() with proper chrono->jiff->chrono conversions - Restores deterministic behavior for relative date parsing - Adds jiff 0.2.15 as direct dependency (not workspace) to avoid feature conflicts - Ensures tests/touch/relative passes in CI Note on jiff dependency: parse_datetime 0.13 depends on jiff ^0.2.15 with specific features. Adding jiff via workspace dependency causes feature unification conflicts across platforms. Using a direct dependency with version 0.2.15 resolves this while maintaining compatibility with parse_datetime's requirements.
This commit is contained in:
parent
f4b66479f0
commit
f764be8ddf
3 changed files with 34 additions and 10 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
|
@ -508,7 +508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1074,7 +1074,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1667,7 +1667,7 @@ dependencies = [
|
|||
"portable-atomic",
|
||||
"portable-atomic-util",
|
||||
"serde",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4127,6 +4127,7 @@ dependencies = [
|
|||
"clap",
|
||||
"filetime",
|
||||
"fluent",
|
||||
"jiff",
|
||||
"parse_datetime",
|
||||
"thiserror 2.0.17",
|
||||
"uucore",
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ path = "src/touch.rs"
|
|||
filetime = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
jiff = "0.2.15"
|
||||
parse_datetime = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
uucore = { workspace = true, features = ["libc", "parser"] }
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use chrono::{
|
|||
use clap::builder::{PossibleValue, ValueParser};
|
||||
use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command};
|
||||
use filetime::{FileTime, set_file_times, set_symlink_file_times};
|
||||
use jiff::{Timestamp, Zoned};
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::{self, File};
|
||||
|
|
@ -588,7 +589,7 @@ fn stat(path: &Path, follow: bool) -> std::io::Result<(FileTime, FileTime)> {
|
|||
))
|
||||
}
|
||||
|
||||
fn parse_date(_ref_time: DateTime<Local>, s: &str) -> Result<FileTime, TouchError> {
|
||||
fn parse_date(ref_time: DateTime<Local>, s: &str) -> Result<FileTime, TouchError> {
|
||||
// This isn't actually compatible with GNU touch, but there doesn't seem to
|
||||
// be any simple specification for what format this parameter allows and I'm
|
||||
// not about to implement GNU parse_datetime.
|
||||
|
|
@ -638,14 +639,35 @@ fn parse_date(_ref_time: DateTime<Local>, s: &str) -> Result<FileTime, TouchErro
|
|||
}
|
||||
|
||||
// **parse_datetime 0.13 API change:**
|
||||
// Previously (0.11): parse_datetime_at_date(chrono) → chrono::DateTime
|
||||
// Now (0.13): parse_datetime() → jiff::Zoned
|
||||
// The parse_datetime crate was updated from 0.11 to 0.13 in commit 2a69918ca to fix
|
||||
// issue #8754 (large second values like "12345.123456789 seconds ago" failing).
|
||||
// This introduced a breaking API change in parse_datetime_at_date:
|
||||
//
|
||||
// Since touch still uses chrono types internally, we convert:
|
||||
// jiff::Zoned → Unix timestamp → chrono::DateTime
|
||||
// Previously (0.11): parse_datetime_at_date(chrono::DateTime) → chrono::DateTime
|
||||
// Now (0.13): parse_datetime_at_date(jiff::Zoned) → jiff::Zoned
|
||||
//
|
||||
// TODO: Consider migrating touch to jiff to eliminate this conversion
|
||||
if let Ok(zoned) = parse_datetime::parse_datetime(s) {
|
||||
// Commit 4340913c4 initially adapted to this by switching from parse_datetime_at_date
|
||||
// to parse_datetime, which broke deterministic relative date parsing (the ref_time
|
||||
// parameter was no longer used, causing tests/touch/relative to fail in CI).
|
||||
//
|
||||
// This implementation restores parse_datetime_at_date usage with proper conversions:
|
||||
// chrono::DateTime → jiff::Zoned → parse_datetime_at_date → jiff::Zoned → chrono::DateTime
|
||||
//
|
||||
// The use of parse_datetime_at_date (not parse_datetime) is critical for deterministic
|
||||
// behavior with relative dates like "yesterday" or "2 days ago", which must be
|
||||
// calculated relative to ref_time, not the current system time.
|
||||
|
||||
// Convert chrono DateTime to jiff Zoned for parse_datetime_at_date
|
||||
let ref_zoned = {
|
||||
let ts = Timestamp::new(
|
||||
ref_time.timestamp(),
|
||||
ref_time.timestamp_subsec_nanos() as i32,
|
||||
)
|
||||
.map_err(|_| TouchError::InvalidDateFormat(s.to_owned()))?;
|
||||
Zoned::new(ts, jiff::tz::TimeZone::system())
|
||||
};
|
||||
|
||||
if let Ok(zoned) = parse_datetime::parse_datetime_at_date(ref_zoned, s) {
|
||||
let timestamp = zoned.timestamp();
|
||||
let dt =
|
||||
DateTime::from_timestamp(timestamp.as_second(), timestamp.subsec_nanosecond() as u32)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue