Page MenuHomePhabricator

Expose DST-corrected user timezone offset to frontend
Closed, ResolvedPublic

Description

Currently on the frontend, mw.user.options.get('timecorrection') gives the time zone from the user's site preferences, but this timezone can't be reliably used as it doesn't take into account changes due to DST. See explanantion by @JJMC89 at T223002#5843155.

Exposing the correct timezone offset (maybe via an mw.config property) would make it possible for client-side JS to accurately format dates and times per user preferences. The absence of this feature is affecting a number of tools:

Possible solutions:
  • mw.config.get('timezone') could give the DST-corrected timezone. This is computed on the server side for every page with dates, so would likely cost nothing for it to be exported, except for a tiny bit of HTML load.
  • ApiQueryUserInfo could add timezone as a new uiprop option. Looks like getCurrentUserInfo() is where the changes needs to be made.

Event Timeline

You should be able to just pass it the timezone with

var d = new Date("2020-04-13T00:00:00Z");    // UTC time
d.toLocaleString('en-US', { timeZone: 'America/New_York' })

I think all browsers that are supported support toLocaleString as well these days...

I should note that, in Convenient-Discussions, the issue is inferring the UTC time from localized time. So, if I correctly understand the workings of mw.user.options.get('timecorrection') (explained in T223002#5843155) and how user timezone affects log pages such as user contributions and history, while both solutions (by @SD0001 and @TheDJ) will definitely move us closer to correct behavior, neither of them will work reliably. On one page, both dates in DST and standard time can be present. So,

  • With the current user timezone offset, only the most recent dates will be interpreted correctly.
  • With Date#toLocaleString (if it is reliable itself), we can only do the opposite of the operation we need: convert UTC time to local time. So we can pretend we have a UTC date, infer the timezone, and then use it to correct the date. But the result of such conversion will be wrong during the several hours near the transition time.

So, for the purposes of Convenient Discussions, the best solution would be to have a UTC timestamp for each revision somewhere in a data attribute, like it is done in the watchlist (but not on user contributions pages, history pages and in diff page headers). An alternative seems to be loading kilobytes of timezone data provided by modules such as Moment Timezone.

I could be wrong, since I haven't investigated the subject in-depth.

  • With Date#toLocaleString (if it is reliable itself), we can only do the opposite of the operation we need: convert UTC time to local time. So we can pretend we have a UTC date, infer the timezone, and then use it to correct the date. But the result of such conversion will be wrong during the several hours near the transition time.

Ah your problem is that you want to use the rendered html dates from MW as input for Convenient Discussions ?

Yup. The task is to generate correct links to comments on talk pages. We have UTC timestamps on the watchlist page, but on other pages we will have to make additional API request(s).

Yeah parsing any localised date format, which doesn't necessarily matches your current localised browser format is a pain without moment.js/luxon. But navigation popups should already be using the api, so should already have access to utc times.

So I don't think these two issues have much to do with each other. The problem for navpopups is that it is not using the timezone information. The problem for convenient discussions is that it is having to use localised date strings as input (because the rendered html doesn't provide it with access to the UTC timestamps most of the time).

The problem with Twinkle was coming up with strings like "Yesterday at 5:43 PM" but in user time. toLocaleString() AFAIK has no option to generate these. I didn't think about the case of referring to events that took place when DST is in effect when it is not in effect now (or vice versa). We have the time in UTC here, but toLocaleString() isn't flexible enough (not to mention its cross-browser inconsistencies). So this seems like a third problem altogether for which apparently there's no solution other than loading moment with timezones?

Interestingly, DiscussionTools appears to do exactly that.

Yesterday at

This can be done with the new https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat but it isn't as widely supported just yet as toLocaleString() is.

but yes, overall momentjs (or better luxon) is still the best way to do this. But it seems a bit overkill to me for a gadget.

Yeah likely overkill. As of now, what Twinkle does is to use a rather mediawiki-specific and lightweight replacement for moment but contends with using either UTC time or browser time.

Closing as doing what the task describes is unlikely to be useful per the above discussion.

SD0001 changed the task status from Invalid to Resolved.May 30 2021, 12:30 PM

This was nevertheless resolved by @TheDJ in https://gerrit.wikimedia.org/r/c/mediawiki/core/+/679959. mw.user.options.get('timecorrection') should now give the current UTC offset.