Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions src/uu/date/src/date.rs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might make sense to move the functionality over to https://github.com/uutils/parse_datetime . There we already use a parser library which could be helpful for the functionality I mentioned in the other comments.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I was just looking for a such function there, anyways, should we add tests for dates like 01.01. 2008 03:00 p.m. and 01.01. 03:00 p.m.?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please :)

Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@

/// OHOS helper: pass through the system time zone ID returned by
/// TimeService (OH_TimeService_GetTimeZone, e.g. "Asia/Shanghai") and
/// resolve it against the embedded IANA tzdata (jiff-tzdb) so that

Check warning on line 38 in src/uu/date/src/date.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

WARNING: `cspell`: Unknown word 'tzdb' (file:'src/uu/date/src/date.rs', line:38)
/// historial DST rules and transitions are preserved. jiff's

Check warning on line 39 in src/uu/date/src/date.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

WARNING: `cspell`: Unknown word 'historial' (file:'src/uu/date/src/date.rs', line:39)
/// `try_system()` is useless on OHOS because both `/etc/localtime` and
/// the zoneinfo dirs are absent.

Check warning on line 41 in src/uu/date/src/date.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

WARNING: `cspell`: Unknown word 'zoneinfo' (file:'src/uu/date/src/date.rs', line:41)
#[cfg(target_env = "ohos")]
fn ohos_system_zone() -> jiff::tz::TimeZone {
use core::ffi::{CStr, c_char};
Expand All @@ -55,7 +55,7 @@
let id = unsafe { CStr::from_ptr(buf.as_ptr() as *const c_char) }
.to_string_lossy()
.into_owned();
if let Some((name, tzif)) = jiff_tzdb::get(&id) {

Check warning on line 58 in src/uu/date/src/date.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

WARNING: `cspell`: Unknown word 'tzif' (file:'src/uu/date/src/date.rs', line:58)
if let Ok(tz) = jiff::tz::TimeZone::tzif(name, tzif) {
return tz;
}
Expand Down Expand Up @@ -1176,6 +1176,32 @@
}))
}

/// Convert a date string to iso if it is seperated by dots.
fn convert_to_iso(date_str: &str) -> Option<String> {
// Seperate the date from anything else, in case we have something like "01.01.2008 03:00 p.m."
let mut parts = date_str.splitn(2, ' ');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is one exception where this approach will fail: GNU date allows spaces between month and year and so something like "01.01. 2008 03:00 p.m." is a valid date.

let date_part = parts.next()?;
let time_part = parts.next();

// Get the year, month and the day
let date_subparts: Vec<&str> = date_part.split('.').collect();
if date_subparts.len() != 3 {
return None;
}
Comment on lines +1187 to +1190

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With GNU date the year is optional. If it is missing, the current year is used. And so something like "01.01. 03:00 p.m." is a valid date.


// Format in iso style
let new_date = format!(
"{}-{}-{}",
date_subparts[2], date_subparts[1], date_subparts[0]
);

// Concat the date and the time back
match time_part {
Some(time) => Some(format!("{new_date} {time}")),
None => Some(new_date),
}
}

/// Parse a string into either an in-range [`Zoned`] value or an extended date.
fn parse_date<S: AsRef<str>>(
s: S,
Expand Down Expand Up @@ -1209,7 +1235,9 @@
return Ok(ParsedDateTime::InRange(zoned));
}

match parse_datetime::parse_datetime_at_date(now.clone(), input_str) {
let input_str = convert_to_iso(input_str).unwrap_or(input_str.to_string());

match parse_datetime::parse_datetime_at_date(now.clone(), &input_str) {
// Convert to system timezone for display
// (parse_datetime returns a value in the input's timezone)
Ok(ParsedDateTime::InRange(date)) => {
Expand Down Expand Up @@ -1248,11 +1276,10 @@
Ok(ParsedDateTime::InRange(result))
}
Ok(ParsedDateTime::Extended(date)) if allow_extended => Ok(ParsedDateTime::Extended(date)),
Ok(ParsedDateTime::Extended(_)) => Err((
input_str.into(),
parse_datetime::ParseDateTimeError::InvalidInput,
)),
Err(e) => Err((input_str.into(), e)),
Ok(ParsedDateTime::Extended(_)) => {
Err((input_str, parse_datetime::ParseDateTimeError::InvalidInput))
}
Err(e) => Err((input_str, e)),
}
}

Expand Down
5 changes: 5 additions & 0 deletions tests/by-util/test_date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3297,3 +3297,8 @@ fn test_write_error() {
.fails_with_code(1)
.stderr_is("date: write error: No space left on device\n");
}

#[test]
fn test_date_separated_by_dots() {
new_ucmd!().args(&["-d", "15.06.2004 3:00 a.m."]).succeeds();
}
Loading