Skip to content

date: improve timezone handling and UTC mode support #7597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jadijadi
Copy link
Contributor

  • Add proper UTC mode handling with -u flag
  • Improve TZ environment variable support
  • Add more TZ tests

FIXES #7497
FIXES #7498

Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/stdbuf (passes in this run but fails in the 'main' branch)

@cakebaker
Copy link
Contributor

Can you please run cargo clippy? The corresponding checks fail in the CI :|

@jadijadi
Copy link
Contributor Author

Can you please run cargo clippy? The corresponding checks fail in the CI :|

Done and Thanks.

Copy link

GNU testsuite comparison:

Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

@@ -492,3 +492,101 @@ fn test_date_empty_tz() {
.succeeds()
.stdout_only("UTC\n");
}

#[test]
fn test_date_tz_utc() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you do a blank TZ too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the comments. there was one test empty TZ and I add another one with .arg("@0") as an additional test.

.arg("+%Z")
.succeeds()
.stdout_only("UTC\n");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, it'd be nice to have tests that actually test that the output time is shifted properly (since that's the issue in #7498). You should pass a fixed datetime as a parameter to date and check that the output is exactly what you expect.

Note that adding a full test for #7498 might be tricky, as it sort of relies on the localtime not being UTC (not sure how our CI runners are configured...)

Copy link
Contributor Author

@jadijadi jadijadi Apr 1, 2025

Choose a reason for hiding this comment

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

Dear @drinkcat , I've added a test for this but it was not working correctly on CI/CD. Its kind of complicated. Will try again tomorrow.
Side note: I also did minor changes to other tests to respect the Day Light Saving changes.

@jadijadi jadijadi force-pushed the timezone_fixes branch 3 times, most recently from 330bb67 to 7184adc Compare April 1, 2025 01:47
@jadijadi
Copy link
Contributor Author

jadijadi commented Apr 1, 2025

Side note: it seems our cargo fmt disagree on some minor stuff. I'm on +stable.

Copy link

github-actions bot commented Apr 1, 2025

GNU testsuite comparison:

Skip an intermittent issue tests/misc/stdbuf (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/inotify-dir-recreate (fails in this run but passes in the 'main' branch)

- Add proper UTC mode handling with -u flag
- Improve TZ environment variable support
- Add more TZ tests

FIXES uutils#7497
FIXES uutils#7498
Copy link

github-actions bot commented Apr 1, 2025

GNU testsuite comparison:

Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

Copy link
Contributor

@drinkcat drinkcat left a comment

Choose a reason for hiding this comment

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

Sorry for the delay, started looking at other timezone stuff and realized this was pending.

Still not 100% sure to understand everything, trying to simplify things where possible.

@@ -273,7 +294,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
for date in dates {
match date {
Ok(date) => {
let format_string = custom_time_format(format_string);
let format_string = if should_use_utc(settings.utc) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be better to move that logic to custom_time_format?

/// Check if we should use UTC time based on the utc flag and TZ environment variable
fn should_use_utc(utc: bool) -> bool {
// Either the -u flag is set or the TZ environment variable is empty
utc || matches!(std::env::var("TZ"), Ok(tz) if tz.is_empty())
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this is slightly nicer: std::env::var("TZ").is_ok_and(|tz| tz.is_empty())

@@ -167,7 +185,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
};

let date_source = if let Some(date) = matches.get_one::<String>(OPT_DATE) {
let ref_time = Local::now();
let ref_time = get_current_time(matches.get_flag(OPT_UNIVERSAL));
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd have a mild preference if you did this:

let utc = matches.get_flag(OPT_UNIVERSAL);

And used utc here and below when initializing settings.

now.with_timezone(&now.offset().fix())
let now = get_current_time(settings.utc);
// Convert to FixedOffset for consistent timezone handling
let now_fixed = if should_use_utc(settings.utc) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why aren't you moving the now_fixed logic into get_current_time? Seems like you output something with the wrong timezone in get_current_time that you now need to adjust again?

@drinkcat
Copy link
Contributor

drinkcat commented Apr 5, 2025

@jadijadi looking at this a bit more... I feel like this would be better fixed in chrono, not here (I was looking at #7504 and couldn't really fully grasp why uucore handling code needs to be so complicated...).

See chronotope/chrono#1690 . If you're interested to submit a patch for chrono I'm happy to leave it to you, just let me know.

If we have problems getting this fix into chrono (or if getting a new release takes time), we could think of some wrapper in uucore that fixes this for all the apps that handle dates (not just date, but also ls and du).

@drinkcat
Copy link
Contributor

drinkcat commented Apr 5, 2025

Argh, maybe I'm wrong, I think we still need some custom logic to handle timezone passed in TZ (i.e. to be able to read the abbreviation from the timezone database).

But... I think we can make things easier by having a wrapper function that returns something like this:

date.with_timezone(&tz)

(where tz comes from the code we already have in timezone_abbreviation)

@sylvestre
Copy link
Contributor

@jadijadi are you still working on it ? thanks :)

@drinkcat
Copy link
Contributor

(btw the empty TZ case is fixed in chrono, but we need to wait for a new release: chronotope/chrono#1691)

@jadijadi
Copy link
Contributor Author

@jadijadi are you still working on it ? thanks :)

yes. had a busy week. will work on it during this long weekend

Copy link
Contributor

@sylvestre sylvestre left a comment

Choose a reason for hiding this comment

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

waiting for update

@jadijadi
Copy link
Contributor Author

waiting for update

I'm a bit lost on this. As @drinkcat mentioned, its better to have most of these fixes in chrono. And they are already fixed there. So maybe its better to close this PR and wait for chrono changes to be merged and work on this again based on what they have.

I'm still having busy work days and wont have time to go deeper and see what is changed in upcomming days. If anyone else wants to finish this, I will be happy.

@drinkcat
Copy link
Contributor

I... also lost all context... and if it's not clear from my comments, I was also a bit confused a few weeks ago when I tried to look at this ,-)

drinkcat added a commit to drinkcat/coreutils that referenced this pull request Apr 25, 2025
iana_time_zone::get_timezone doesn't cover all cases, so we need
to handle some of the timezone parsing manually.

Also add a bunch of TODO, this function is by no means complete.

(change similar to uutils#7597 for this file)
drinkcat added a commit to drinkcat/coreutils that referenced this pull request Apr 25, 2025
iana_time_zone::get_timezone doesn't cover all cases, so we need
to handle some of the timezone parsing manually.

Also add a bunch of TODO, this function is by no means complete.

(change similar to uutils#7597 for this file)
drinkcat added a commit to drinkcat/coreutils that referenced this pull request Apr 25, 2025
iana_time_zone::get_timezone doesn't cover all cases, so we need
to handle some of the timezone parsing manually.

Also add a bunch of TODO, this function is by no means complete.

(change similar to uutils#7597 for this file)
drinkcat added a commit to drinkcat/coreutils that referenced this pull request Apr 27, 2025
iana_time_zone::get_timezone doesn't cover all cases, so we need
to handle some of the timezone parsing manually.

Also add a bunch of TODO, this function is by no means complete.

(change similar to uutils#7597 for this file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants