-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Make dateI18n returns be affected by gmt
parameter
#18982
Conversation
I admit to not being too terribly familiar with this specific function or why it was passing the second argument previously. Maybe @iandunn could advise on whether the proposed changes here seem reasonable? Here's relevant documentation from Moment on this parameter:
I also observe that between the original patches at Trac#39222 (last patch by @ocean90) and its introduction to Gutenberg in #841 by @youknowriad , only the latter included this argument, and it's not clear if there was a reason for this disparity. I realize this has been many years, but perhaps one or the other of the two might have some recollection to whether it is necessary. |
I was asking because I think we might need to change this line too, as I did in my commit, but I'm not sure. |
@aduth, I've been investigating this issue and here's what I've found (spoiler alert: it's a mess). If I'm not mistaken, we want our JavaScript functions to "mimic" what we see in PHP (even though I'm not sure it's the best approach), so I thought I'd run a few tests on PHP and see the results I get in the hopes of better understanding how things currently work. Just to make sure we're on the same page, my setup is as follows:
I'll be using the same values used in issue #16218 reported by @iandunn:
PHP's
|
@aduth, I've spent some time digging into this issue and I think I have a clearer understanding now. Essentially, when working with the
Timezone/UTC offset in an argumentUsually, the timezone we use in our arguments is explicit. That is, if we use a
but sometimes it's not and, therefore, the date is ambiguous:
SOLUTION: When the given date is ambiguous, we should assume it uses WordPress' timezone. Timezone used in a formatted resultAccording to the documentation, this is how the functions are supposed to work:
Next StepsSo, if we all agree on this, I can prepare a test suite that validates this behavior in my PR so that the current implementation fails (as originally reported in #16218). Then, I'll work on a fix. |
It might be good idea to connect with @Rarst since he did/is doing some great work to fix date handling on the PHP side, see https://make.wordpress.org/core/2019/09/23/date-time-improvements-wp-5-3/ for example. |
I am not entirely sure about JS context of the issue, but on PHP side WordPress 5.3+ replacement and now "main" date formatting function is |
gmt
parameter
As discussed in our last JS meeting, @aduth, I've applied the minimum number of changes required and implemented a bunch of tests that verify the expected behavior. In particular, tests:
validate that the original issue (#16218) is fixed. Therefore, this PR is ready to be merged. Now, there's only one issue left, which is what should we do if the given date has an ambiguous timezone (i.e. has no timezone), as in |
Do note that this isn't consistent with how Not sure what the design for JS counterpart is supposed to be, but if it diverges from PHP original while keeping a very close name it would need to be thoroughly documented that behavior is not identical between the two. |
You mean the third param ( With that said, I'd personally implement these functions a little bit differently. If we want to keep |
As above, just giving some context on PHP side of things. :) Not plugged into the process of how the JS versions are designed and what expectations are. But from my point of view Ending up with two crazy functions that aren't consistent with each other would be... suboptimal outcome. :) |
My understanding of the historical context is that these functions are intended to essentially be direct ports of the equivalent PHP functionality (or at least the solutions which existed at the time). Whether we'd want to reevaluate these options, especially as new solutions are emerging in PHP, I think it would be fair to consider that, though separately to the effort here. For the sake of backward-compatibility, I think the focus here should be to strive to align the two as much as possible, even if the aligned behavior is suboptimal.
Can you elaborate on what you're considering to be the differences? Is it something you think we can't change without being considered backwards-incompatible? Would it be enough to say that the current behavior is buggy (especially if we're promoting it as intending to align to the corresponding PHP behavior)? |
Let's put this side by side for clarity.
So, yes, JS and PHP is already out of sync, since On one hand aligning JS version with it is replicating crazy behavior. On other hand it's not aligned already. Bonus question — what happens when someone provides timestamp to JS version? Is it supposed to treat it like Unix timestamp or like WP timestamp?
|
@Rarst did a pretty good job at summarizing the differences. Essentially, in PHP the second argument (date) is not exactly a date, but the result of a weird function, and the third one (gmt) should only be used if the second one is set to false. In JS the date is, well, a date (compatible with momentjs) and the third argument can be used even if the date arg is set (but, if it isn't, it behaves like PHP). Personally, I like the approach followed by But there's a thing missing there, @Rarst and @aduth. If my understanding is correct, My solution/My preferred scenarioIf I were to implement these functions in JavaScript right now, I'd create a function named |
As discussed during JavaScript Chat - January 21, 2020, I've modified this PR so that Notice: The PR also include several new tests that verify the expected behavior. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the continued work here. I left a few remarks, most of which aren't so much concerned with the implementation itself, but rather small recommendations about documentation.
packages/date/src/index.js
Outdated
* @param {(string|number|null)} timezone Timezone to output result in or | ||
* a UTC offset. | ||
* Defaults to timezone from site. | ||
* See momentjs.com. | ||
* | ||
* @return {string} Formatted date. | ||
*/ | ||
export function dateI18n( dateFormat, dateValue = new Date(), timezone ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timezone
argument isn't consistent with the documented type, in two ways:
- It's optional, but the type doesn't indicate this (related documentation)
- The first line of code in the function tests if
timezone === true
, buttrue
is not a valid documented value fortimezone
. We should includeboolean
if it's expected.
Small formatting nit-picks, but relevant if there's a concern of running out of available space for the description texts:
- The enclosing parentheses on union types are unnecessary (the
timezone
types as currently implemented could be expressed{string|number|null}
) - You have a few unnecessary extra spaces after your longest type tag
@param {(Date|string|Moment|null)} dateValue
. There only need be a single space here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now a few lines earlier from this that it's mentioned in the documentation about the special treatment for the boolean variable for the sake of backwards-compatibility. One thing I might be worried about is that as we transition to stricter type-checking (#18838), the type-checker may struggle to reconcile or otherwise reject the fact that we document the function as not accepting a boolean, only to then proceed to test a boolean.
I think it may just be worth including boolean
in the documented type, both for this reason and because it's still technically accepted. Between the documentation of the function (and perhaps an additional note in the argument description), it should be clear enough that boolean
is effectively deprecated, even if still supported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in c3d5fe4.
timezone
indateI18n
now includesboolean
and explicitly states that "is effectively deprecated, but still supported for backward compatibility reasons."- Also fixed union types and spacing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's still some issue here; these functions have optional arguments, but null
is not a correct way to denote an optional argument (via reference documentation mentioned in #18982 (comment)).
Looking at the current build failure and knowing this to be related to issues yesterday with Travis + Composer, the branch may need a rebase. I tried restarting the build, but it clearly wasn't enough. It may also be an opportunity to correct a mistake I made in squashing commits, where I accidentally made myself the author of the commit. |
…’re transforming the same common Moment instance in distinct ways.
Thanks for the patience in working through the conversation and iterations here 👍 Glad to see it finally land. |
🎉 , great job @davilera :) |
Description
The PR adds a couple of tests to reproduce the issue #16218 reported by @iandunn and proposes a simple fix.
Types of changes
Bug fix.
Checklist: