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

Use the last, not first, two digits as the year

This commit is contained in:
Jeffrey Finkelstein 2025-02-06 22:02:47 -05:00
parent 6dfa1f8276
commit c23e1db9c5
2 changed files with 32 additions and 13 deletions

View file

@ -141,11 +141,14 @@ fn all_digits(s: &str) -> bool {
} }
/// Convert a two-digit year string to the corresponding number. /// Convert a two-digit year string to the corresponding number.
///
/// `s` must be of length two or more. The last two bytes of `s` are
/// assumed to be the two digits of the year.
fn get_year(s: &str) -> u8 { fn get_year(s: &str) -> u8 {
// Pre-condition: s.len() >= 2
let bytes = s.as_bytes(); let bytes = s.as_bytes();
let y1 = bytes[0] - b'0'; let n = bytes.len();
let y2 = bytes[1] - b'0'; let y1 = bytes[n - 2] - b'0';
let y2 = bytes[n - 1] - b'0';
10 * y1 + y2 10 * y1 + y2
} }
@ -153,7 +156,7 @@ fn get_year(s: &str) -> u8 {
fn is_first_filename_timestamp( fn is_first_filename_timestamp(
reference: Option<&OsString>, reference: Option<&OsString>,
date: Option<&str>, date: Option<&str>,
timestamp: Option<&String>, timestamp: &Option<String>,
files: &[&String], files: &[&String],
) -> bool { ) -> bool {
match std::env::var("_POSIX2_VERSION") { match std::env::var("_POSIX2_VERSION") {
@ -180,6 +183,18 @@ fn is_first_filename_timestamp(
} }
} }
/// Cycle the last two characters to the beginning of the string.
///
/// `s` must have length at least two.
fn shr2(s: &str) -> String {
let n = s.len();
let (a, b) = s.split_at(n - 2);
let mut result = String::with_capacity(n);
result.push_str(b);
result.push_str(a);
result
}
#[uucore::main] #[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> { pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().try_get_matches_from(args)?; let matches = uu_app().try_get_matches_from(args)?;
@ -204,19 +219,23 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
.get_one::<String>(options::sources::DATE) .get_one::<String>(options::sources::DATE)
.map(|date| date.to_owned()); .map(|date| date.to_owned());
let mut timestamp = matches.get_one::<String>(options::sources::TIMESTAMP); let mut timestamp = matches
.get_one::<String>(options::sources::TIMESTAMP)
.map(|t| t.to_owned());
if is_first_filename_timestamp(reference, date.as_deref(), timestamp, &filenames) { if is_first_filename_timestamp(reference, date.as_deref(), &timestamp, &filenames) {
let head = filenames[0]; timestamp = if filenames[0].len() == 10 {
let tail = &filenames[1..]; Some(shr2(filenames[0]))
timestamp = Some(head); } else {
filenames = tail.to_vec(); Some(filenames[0].to_string())
};
filenames = filenames[1..].to_vec();
} }
let source = if let Some(reference) = reference { let source = if let Some(reference) = reference {
Source::Reference(PathBuf::from(reference)) Source::Reference(PathBuf::from(reference))
} else if let Some(ts) = timestamp { } else if let Some(ts) = timestamp {
Source::Timestamp(parse_timestamp(ts)?) Source::Timestamp(parse_timestamp(&ts)?)
} else { } else {
Source::Now Source::Now
}; };

View file

@ -935,9 +935,9 @@ fn test_obsolete_posix_format_with_year() {
let (at, mut ucmd) = at_and_ucmd!(); let (at, mut ucmd) = at_and_ucmd!();
ucmd.env("_POSIX2_VERSION", "199209") ucmd.env("_POSIX2_VERSION", "199209")
.env("POSIXLY_CORRECT", "1") .env("POSIXLY_CORRECT", "1")
.args(&["9001010000", "11111111"]) .args(&["0101000090", "11111111"])
.succeeds() .succeeds()
.no_output(); .no_output();
assert!(at.file_exists("11111111")); assert!(at.file_exists("11111111"));
assert!(!at.file_exists("01010000")); assert!(!at.file_exists("0101000090"));
} }