Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Per #2500525: Time ago/hence date/time formatting breaks caching; needs appropriate max age date formatting $granularity renders units that aren't adjacent, such as 1 year 3 seconds.
On that issue I suggested setting max age based on the granularity that will be shown, but this will only result in a decent hit rate when units are minutes/hours/days/weeks/months rather than seconds.
Proposed resolution
When granularity is set, show adjacent granularities like "1 year, 1 month" but instead of "1 year, 47 seconds" show "1 year".
Remaining tasks
User interface changes
Date formatting will only show adjacent units.
API changes
None, but the output changes slightly.
Beta phase evaluation
Issue category | Task because we need to change how we handle granularity in formatted intervals. |
---|---|
Issue priority | Major because it blocks a non-js solution for the major issue #2500525: Time ago/hence date/time formatting breaks caching; needs appropriate max age |
Prioritized changes | The main goal of this issue is to make it possible to have a non-js solution for #2500525: Time ago/hence date/time formatting breaks caching; needs appropriate max age, which is a performance improvement. |
Disruption | None, but there is will be a minor change in the output of some formatted intervals. |
Comment | File | Size | Author |
---|---|---|---|
#20 | date_format_granularity-2502571-20.patch | 9.88 KB | Anonymous (not verified) |
#20 | interdiff-17-20.txt | 909 bytes | Anonymous (not verified) |
#17 | date_format_granularity-2502571-17.patch | 9.87 KB | Anonymous (not verified) |
#17 | interdiff-14-17.txt | 1.74 KB | Anonymous (not verified) |
#14 | date_format_granularity-2502571-14.patch | 10.15 KB | Anonymous (not verified) |
Comments
Comment #1
jhodgdonSo... This will mean that if the interval is for instance from January 3 2014 to February 2 2015, the output would be "1 year", and then the next day it would jump to "1 year 1 month". No days/weeks would be allowed after "1 year", only months.
Is that really what we want? I'm on board with not having "1 year 1 second", which although it has always been how the function has behaved, is definitely silly, but I'm not sure "1 year 3 weeks" is so silly. Thoughts? I guess it's not horrible to lose this.
Also we'll need to update #2456521: Add DateFormatter::formatDiff() as a non-buggy alternative to DateFormatter::formatInterval() when the start and end of the interval are known to do the same as formatInterval(), plus its tests. I would prefer to get that in first, then do the update of both formatDiff() and formatInterval() here, since that one is (again) RTBC and it's been going quite a while, but either way.
Comment #2
catchSo if we wanted to do that it'd mean allowing an adjacency of up to two.
So 1 hour 43 seconds.
1 day 23 minutes.
1 week 4 hours.
1 month 5 days.
1 year 3 weeks.
None of those look silly, but I don't think we'd miss them either. Since past 1 year and 3 weeks, it's always going to be 1 year 1 month, 1 year 2 months etc.
On formatDiff I'm not in a rush to do this, I think #2500525: Time ago/hence date/time formatting breaks caching; needs appropriate max age is definitely major and not critical, but hoping to have a plan to go forwards so we can do it before release if that's viable, or know what the impact will be post-release if not.
At the moment the patch isn't an API change (or addition), just a very small behaviour change to the function, so I think it's OK even in a patch release.
Comment #3
jhodgdonYeah, I think I agree that we can lose all of the "skip a granularity level" outputs.
So. Nitpicks on the patch:
Needs 1 more space of indentation here (this is in formatInterval()). I also think it could use a comment to explain why we want to break in this case, something like:
Break if there was previous output but not any output at this level, to avoid skipping levels and getting output like "1 year 1 second".
Otherwise, this looks good to me. I checked over the tests, and I think there is adequate test coverage with the patched test, both for adjacent intervals working and for not getting things like "1 year 1 sec".
Comment #4
mpdonadio#3 addressed.
Do we have a preferred commit order for all of these date/timestamp related patches?
Comment #5
jhodgdonI think this is fine now. It will conflict with #2456521: Add DateFormatter::formatDiff() as a non-buggy alternative to DateFormatter::formatInterval() when the start and end of the interval are known though, which is up to 156 comments and I'd love to see it get in before we do any of the other patches... [just my personal "This has been going on long enough" preference]
Comment #6
jhodgdonWe need to add this same fix to the new formatDiff() function from #2456521: Add DateFormatter::formatDiff() as a non-buggy alternative to DateFormatter::formatInterval() when the start and end of the interval are known (which just landed, woot!), and this may also need a reroll.
Comment #7
Anonymous (not verified) CreditAttribution: Anonymous at XIO commentedI'll take a look at this later this evening.
Comment #8
Anonymous (not verified) CreditAttribution: Anonymous at XIO commentedIt auto-merged:
The implementation in this patch uses a
break 2;
which I don't really like, but it was the most readable way to do this I think. I'm open for suggestions though.The test coverage seems sufficient.
I also added a beta eval, and fixed a typo.
Comment #9
Anonymous (not verified) CreditAttribution: Anonymous at XIO commentedComment #10
jhodgdonLooks pretty good! The test coverage is very thorough too.
I do have one suggestion, about the "break 2" code:
I also don't like the "break 2" very much... so I think we can combine these two if() statements and drop the "break 2" line. So the 2nd if would become:
I think that's right... We'd better make sure we definitely have a case to test that
1 month 1 day
cannot be created as output in formatDiff, since this is handled with special logic!
Let's see, yes:
So yes, we have the "if months and no weeks don't do days" cases covered. Excellent!
Comment #11
Anonymous (not verified) CreditAttribution: Anonymous at XIO commentedThat's a great suggestion! However, now I have 3 test failures locally. An example failure is the result "2 months 2 hours", which should be "2 months". I couldn't find the cause yet.
Comment #12
jhodgdonYou know, I don't really like this $parts integer variable anyway. Really it's being used as a binary: it's "had we already made some output before we got to this point in the loop", right?
I think if we switched both functions to that logic, it might work better and be easier to read than having this cryptic variable called $parts that measures how many times we have made output, when really we just need to know if there is some output (which we could test by seeing if the output text variable evaluates to FALSE, like if($interval_output) or whatever).
Also in formatDiff() I was suggesting:
that if can now be
if($weeks)
Anyway, let's see where the failures are.
Comment #14
Anonymous (not verified) CreditAttribution: Anonymous at XIO commentedRerolled, and what about just using $output as a check? I still have local failures so I only adjusted the formatDiff() one.
Comment #16
jhodgdonRE using $output as as check, sure. The new patch looks reasonable; still 3 fails...
Comment #17
Anonymous (not verified) CreditAttribution: Anonymous at XIO commentedThis ought to do it. Also fixed the other function. So I think this might be good to go?
Comment #18
jhodgdonThanks! Looks good, and the tests pass!
OK so I found one in-code comment that I didn't like... this is a rather long explanation of why... but I think it's a bit misleading...
Um...
The code comment in the else doesn't make sense to me.
The if part of this is basically "If we should be outputting days", so the else means "We are not outputting days".
The reason we are not outputting days is either that
(a) there were months but no weeks and we didn't want "1 month 1 day" output
or
(b) there was an even multiple of 7 days to render, so we output "1 month 1 week" and there were no days left over to output as "3 days".
And the reason we want to set the granularity to 0 in this else() is thus because we don't want to have hours, as the comment says, but it's not true that "we have months but no weeks".
So, that was kind of a long commentary...
I think this comment should say:
If we did not output days, set the granularity to 0 so that we will not output hours and get things like "1 week 1 hour".
Comment #19
Wim LeersComment #20
Anonymous (not verified) CreditAttribution: Anonymous at XIO commentedYes, that's indeed more comprehensible.
Comment #21
jhodgdonThanks, looks great!
Comment #22
catchCommitted/pushed to 8.0.x, thanks!
Comment #24
Wim LeersNice :)