Skip to content
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

Parse relative months and years #1702

Merged
merged 3 commits into from
Nov 25, 2024

Conversation

EliahKagan
Copy link
Member

@EliahKagan EliahKagan commented Nov 25, 2024

Update: This now also fixes #1696. See 856b385 and #1702 (review).

This extends gix_date::parse::relative::span to recognize times with "months" and "years", as in "3 months ago" and "2 years ago".

The actual change here is very simple, because it is directly facilitated by #1474.

The units "seconds", "minutes", "hours", "days", and "weeks" continue to be recognized (as before). Relative times like "1 year, 2 months ago" remain unrecognized.

For background, see 43b6c06 (#498), c5c6bf6, #1474 (comment), and #1696 (comment).

Note that this change does not fix issue #1696, which continues to apply to the interpretation of "days" and "weeks", and now also applies in the same way to the interpretation of "months" and "years". (It continues not to apply to the interpretation of "seconds", "minutes", and "hours".)

The tests are updated to cover "months" and "years", as well as to exercise a wider range of relative times, including showing which units (e.g. "days") are affected by #1696. A few sub-cases, of those adjusted or added here, test strings from a related test in Git, to allow comparison. But most are not related to cases there.

As before, the tests pass on CI, or when the time zone is otherwise UTC, or with local time zones that never have DST adjustments.

The sub-cases are reordered to be monotone increasing in the magnitude of the relative intervals tested (and thus monotone decreasing in the associated absolute timestamps), and the original input is kept zipped into the actual and expected arrays being compared. This way, if the assertion fails (such as due to #1696), it is clear and readable which sub-cases failed and exactly how, as well as what all the sub-cases are and what each sub-case tests.

Reordering the sub-cases and preserving the inputs they parse in this way avoids the disadvantages of #1697 while keeping, and expanding on, its benefits.

Failure, where it occurs, now looks like:

--- STDERR:              gix-date::date time::parse::relative::various ---
thread 'time::parse::relative::various' panicked at gix-date\tests\time\parse.rs:252:9:
assertion failed: `(left == right)`: relative times differ

Diff < left / right > :
 [
     (
         "5 seconds ago",
         2024-11-24T23:51:49Z,
     ),
     (
         "5 minutes ago",
         2024-11-24T23:46:54Z,
     ),
     (
         "5 hours ago",
         2024-11-24T18:51:54Z,
     ),
     (
         "5 days ago",
         2024-11-19T23:51:54Z,
     ),
     (
         "3 weeks ago",
         2024-11-03T23:51:54Z,
     ),
     (
         "21 days ago",
         2024-11-03T23:51:54Z,
     ),
     (
         "504 hours ago",
         2024-11-03T23:51:54Z,
     ),
     (
         "30240 minutes ago",
         2024-11-03T23:51:54Z,
     ),
     (
         "2 months ago",
<        2024-09-24T23:51:54Z,
>        2024-09-24T22:51:54Z,
     ),
     (
         "1460 hours ago",
         2024-09-25T03:51:54Z,
     ),
     (
         "87600 minutes ago",
         2024-09-25T03:51:54Z,
     ),
     (
         "14 weeks ago",
<        2024-08-18T23:51:54Z,
>        2024-08-18T22:51:54Z,
     ),
     (
         "98 days ago",
<        2024-08-18T23:51:54Z,
>        2024-08-18T22:51:54Z,
     ),
     (
         "2352 hours ago",
         2024-08-18T23:51:54Z,
     ),
     (
         "141120 minutes ago",
         2024-08-18T23:51:54Z,
     ),
     (
         "5 months ago",
<        2024-06-24T23:51:54Z,
>        2024-06-24T22:51:54Z,
     ),
     (
         "3650 hours ago",
         2024-06-25T21:51:54Z,
     ),
     (
         "219000 minutes ago",
         2024-06-25T21:51:54Z,
     ),
     (
         "26 weeks ago",
<        2024-05-26T23:51:54Z,
>        2024-05-26T22:51:54Z,
     ),
     (
         "182 days ago",
<        2024-05-26T23:51:54Z,
>        2024-05-26T22:51:54Z,
     ),
     (
         "4368 hours ago",
         2024-05-26T23:51:54Z,
     ),
     (
         "262080 minutes ago",
         2024-05-26T23:51:54Z,
     ),
     (
         "8 months ago",
<        2024-03-24T23:51:54Z,
>        2024-03-24T22:51:54Z,
     ),
     (
         "5840 hours ago",
         2024-03-26T15:51:54Z,
     ),
     (
         "350400 minutes ago",
         2024-03-26T15:51:54Z,
     ),
     (
         "38 weeks ago",
         2024-03-03T23:51:54Z,
     ),
     (
         "266 days ago",
         2024-03-03T23:51:54Z,
     ),
     (
         "6384 hours ago",
         2024-03-03T23:51:54Z,
     ),
     (
         "383040 minutes ago",
         2024-03-03T23:51:54Z,
     ),
     (
         "11 months ago",
         2023-12-24T23:51:54Z,
     ),
     (
         "8030 hours ago",
         2023-12-26T09:51:54Z,
     ),
     (
         "481800 minutes ago",
         2023-12-26T09:51:54Z,
     ),
     (
         "14 months ago",
<        2023-09-24T23:51:54Z,
>        2023-09-24T22:51:54Z,
     ),
     (
         "21 months ago",
         2023-02-24T23:51:54Z,
     ),
     (
         "2 years ago",
         2022-11-24T23:51:54Z,
     ),
     (
         "20 years ago",
         2004-11-24T23:51:54Z,
     ),
     (
         "630720000 seconds ago",
         2004-11-29T23:51:54Z,
     ),
 ]

I've posted #1696 (comment) about why I think the changes here may be okay to do even before the main in #1696 (comment) (that would actually fix issue #1696) is not yet done.

It may be that this is an excessive number of lines of test output to show in a commit message (3082d40). I've included it, as I have done in previous changes to that test, since it will not be seen on CI or even in all local time zones, and since it makes much clearer how and why the test's output format has changed.

Ordinarily, I would not be reluctant to make a commit message that long. But in this case, it's a conventional commit with feat:, so I expect it to make its way into the changelog. The test is probably of less interest to future readers of the changelog and in any case is not, really, technically even part of the feature. I could put the test in its own commit, as I often do with tests. But the description of what the output looks like would be inaccurate if that commit precedes the commit that adds support for months and years--it produces a parsing error until support is added, whereas the test output that is informative is the output showing that we still, and better, see what is going on with #1696.

Anyway, I don't know if that is really to be considered a problem, but I mention it so that it will be noticed if it is.

@EliahKagan
Copy link
Member Author

From the refactoring in d140ad4:

  • place expectations to the right, actuals on the left.

Good idea. I had kept the way it was before, but on reflection this was not likely (or not likely still) intended, since not all assertions in the function had been using the same convention.

  • fix test expectation and make clear that relative dates are all UTC.

Does this actually do the rest of #1696 (comment), i.e. fix issue #1696? (Normally I might read the code carefully and try it out, rather than asking immediately, but I wanted to ask this before the PR is merged, in case the commit is not just a refactoring and should be differently titled.)

@Byron Byron force-pushed the run-ci/duration-units branch from eb77ccf to a769fdd Compare November 25, 2024 07:09
Copy link
Member

@Byron Byron left a comment

Choose a reason for hiding this comment

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

Thanks a lot for your help with this!

When looking at the exhaustive tests, I can't shake the feeling that other parts of gix-date are completely under-tested. And from my memory I can tell that I never put a lot of emphasis on this crate, just wanted to have 'something' so dates are just usable enough.

In any case, I definitely count this is a step in the right direction, with the current implementation probably covering the most common cases at last.

Regarding the commit message, I think tools should enable developers, and I hope that the message comes out OK in the changelog without preventing publishing. But when it does, I will just have to fix it and that's OK.

Please note that I underhandedly fixed the 'UTC-issue', which truly was just an incorrect test expectation - the implementation is already faithful to Git, it was just the test who wasn't faithful to it.

Also, I put the actual value on the left of an assertion, and added a third argument to further explain what's going on when I thought it could make a difference.

@Byron Byron enabled auto-merge November 25, 2024 07:10
@Byron Byron disabled auto-merge November 25, 2024 07:12
@Byron
Copy link
Member

Byron commented Nov 25, 2024

Does this actually do the rest of #1696 (comment), i.e. fix issue #1696? (Normally I might read the code carefully and try it out, rather than asking immediately, but I wanted to ask this before the PR is merged, in case the commit is not just a refactoring and should be differently titled.)

Probably I shouldn't have 'fixed' this underhandedly, so I disabled the auto-merge and invite you to split the commit. To me it was just a minor thing in the end, as I did have local test failures which I think were well enough understood to fix them. All seems alright, as I think it was just an incorrect test expectation that caused trouble.

This extends `gix_date::parse::relative::span` to recognize times
with "months" and "years", as in "3 months ago" and "2 years ago".
Those units are supported by Git.

The actual change here to the parsing code is very simple, because
it is directly facilitated by GitoxideLabs#1474.

The units "seconds", "minutes", "hours", "days", and "weeks"
continue to be recognized (as before). Relative times like
"1 year, 2 months ago" remain unrecognized.

For background, see 43b6c06 (GitoxideLabs#498), c5c6bf6,
GitoxideLabs#1474 (comment),
and
GitoxideLabs#1696 (comment).

Note that this specific change does not itself fix issue GitoxideLabs#1696,
which applies to the intepretation of "days" and "weeks", and now
also applies in the same way to the interpretation of "months" and
"years". (It continues not to apply to the interpretation of
"seconds", "minutes", and "hours".)

The tests are updated to cover "months" and "years", as well as to
exercise a wider range of relative times, including showing which
units (e.g. "days") are affected by GitoxideLabs#1696. A few sub-cases, of
those adjusted or added here, test strings from a related test in
Git, to allow comparison. But most are not related to cases there.

As before, the tests pass on CI, or when the time zone is otherwise
UTC, or with local time zones that never have DST adjustments.

The sub-cases are reordered to be monotone increasing in the
magnitude of the relative intervals tested (and thus monotone
decreasing in the associated absolute timestamps), and the original
input is kept zipped into the `actual` and `expected` arrays being
compared. This way, if the assertion fails (such as due to GitoxideLabs#1696),
it is clear and readable which sub-cases failed and exactly how, as
well as what all the sub-cases are and what each sub-case tests.

Reordering the sub-cases and preserving the inputs they parse in
this way avoids the disadvantages of GitoxideLabs#1697 while keeping, and
expanding on, its benefits.

Failure, where it occurs, now looks like:

    --- STDERR:              gix-date::date time::parse::relative::various ---
    thread 'time::parse::relative::various' panicked at gix-date\tests\time\parse.rs:252:9:
    assertion failed: `(left == right)`: relative times differ

    Diff < left / right > :
     [
         (
             "5 seconds ago",
             2024-11-24T23:51:49Z,
         ),
         (
             "5 minutes ago",
             2024-11-24T23:46:54Z,
         ),
         (
             "5 hours ago",
             2024-11-24T18:51:54Z,
         ),
         (
             "5 days ago",
             2024-11-19T23:51:54Z,
         ),
         (
             "3 weeks ago",
             2024-11-03T23:51:54Z,
         ),
         (
             "21 days ago",
             2024-11-03T23:51:54Z,
         ),
         (
             "504 hours ago",
             2024-11-03T23:51:54Z,
         ),
         (
             "30240 minutes ago",
             2024-11-03T23:51:54Z,
         ),
         (
             "2 months ago",
    <        2024-09-24T23:51:54Z,
    >        2024-09-24T22:51:54Z,
         ),
         (
             "1460 hours ago",
             2024-09-25T03:51:54Z,
         ),
         (
             "87600 minutes ago",
             2024-09-25T03:51:54Z,
         ),
         (
             "14 weeks ago",
    <        2024-08-18T23:51:54Z,
    >        2024-08-18T22:51:54Z,
         ),
         (
             "98 days ago",
    <        2024-08-18T23:51:54Z,
    >        2024-08-18T22:51:54Z,
         ),
         (
             "2352 hours ago",
             2024-08-18T23:51:54Z,
         ),
         (
             "141120 minutes ago",
             2024-08-18T23:51:54Z,
         ),
         (
             "5 months ago",
    <        2024-06-24T23:51:54Z,
    >        2024-06-24T22:51:54Z,
         ),
         (
             "3650 hours ago",
             2024-06-25T21:51:54Z,
         ),
         (
             "219000 minutes ago",
             2024-06-25T21:51:54Z,
         ),
         (
             "26 weeks ago",
    <        2024-05-26T23:51:54Z,
    >        2024-05-26T22:51:54Z,
         ),
         (
             "182 days ago",
    <        2024-05-26T23:51:54Z,
    >        2024-05-26T22:51:54Z,
         ),
         (
             "4368 hours ago",
             2024-05-26T23:51:54Z,
         ),
         (
             "262080 minutes ago",
             2024-05-26T23:51:54Z,
         ),
         (
             "8 months ago",
    <        2024-03-24T23:51:54Z,
    >        2024-03-24T22:51:54Z,
         ),
         (
             "5840 hours ago",
             2024-03-26T15:51:54Z,
         ),
         (
             "350400 minutes ago",
             2024-03-26T15:51:54Z,
         ),
         (
             "38 weeks ago",
             2024-03-03T23:51:54Z,
         ),
         (
             "266 days ago",
             2024-03-03T23:51:54Z,
         ),
         (
             "6384 hours ago",
             2024-03-03T23:51:54Z,
         ),
         (
             "383040 minutes ago",
             2024-03-03T23:51:54Z,
         ),
         (
             "11 months ago",
             2023-12-24T23:51:54Z,
         ),
         (
             "8030 hours ago",
             2023-12-26T09:51:54Z,
         ),
         (
             "481800 minutes ago",
             2023-12-26T09:51:54Z,
         ),
         (
             "14 months ago",
    <        2023-09-24T23:51:54Z,
    >        2023-09-24T22:51:54Z,
         ),
         (
             "21 months ago",
             2023-02-24T23:51:54Z,
         ),
         (
             "2 years ago",
             2022-11-24T23:51:54Z,
         ),
         (
             "20 years ago",
             2004-11-24T23:51:54Z,
         ),
         (
             "630720000 seconds ago",
             2004-11-29T23:51:54Z,
         ),
     ]
EliahKagan pushed a commit to EliahKagan/gitoxide that referenced this pull request Nov 25, 2024
- Fix test expectation and make clear that relative dates are all
  UTC. This fixes GitoxideLabs#1702.

- Place all expectations to the right and actuals to the left, for
  clearer messages, plus a bit of other cleanup.
@EliahKagan EliahKagan force-pushed the run-ci/duration-units branch from a769fdd to d2a10b1 Compare November 25, 2024 07:52
- Fix test expectation and make clear that relative dates are all
  UTC. This fixes GitoxideLabs#1696.

- Place all expectations to the right and actuals to the left, for
  clearer messages, plus a bit of other cleanup.
@EliahKagan EliahKagan force-pushed the run-ci/duration-units branch from d2a10b1 to 26cf998 Compare November 25, 2024 07:57
@EliahKagan
Copy link
Member Author

EliahKagan commented Nov 25, 2024

I've gone ahead and split the commit. For 856b385, I mentioned in the commit message that it fixes #1696, but didn't make it a conventional commit since it only changes the test.

I've also tested this locally on Windows 10 (x64) and Arch Linux (x64), with local time such that the tests had previous failed, and with TZ=UTC (which had previously passed). All gix-date tests now pass in all four combinations.

The test-32bit CI job is failing now, but the failure seems to be erratic and unrelated to these changes. I'll look into that.

Similar to Git, any unit is allowed and will default to seconds, like `60 flurps ago`
will mean a minute in the past.
@EliahKagan EliahKagan force-pushed the run-ci/duration-units branch from 26cf998 to 34d2fce Compare November 25, 2024 08:04
@EliahKagan
Copy link
Member Author

I've caused the failing test-32-bit job to re-run, and it passed. Also, it had failed before any gitoxide code or tests had run, or even compiled. So it is quite unlikely to be related to any changes here. Assuming the messages in the split commits are okay, I think this is ready to go.

@Byron Byron merged commit b34d14e into GitoxideLabs:main Nov 25, 2024
20 checks passed
@Byron
Copy link
Member

Byron commented Nov 25, 2024

Awesome, thank you!

@EliahKagan EliahKagan deleted the run-ci/duration-units branch November 25, 2024 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Relative time ambiguity across DST adjustments
2 participants