Skip to content

Instantly share code, notes, and snippets.

@thomasboyt
Last active November 28, 2018 00:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomasboyt/bee725d9c7ee74f14cd56c8d57e2f335 to your computer and use it in GitHub Desktop.
Save thomasboyt/bee725d9c7ee74f14cd56c8d57e2f335 to your computer and use it in GitHub Desktop.
import moment from 'moment';
/**
* XXX: Okay, so, no date library, other than moment, appears to currently
* support _formatting a date with a specified time offset_. That is, given the
* date string `2018-11-21T15:00:00+0100` (UTC+1:00), I want to format it as
* `3:00 PM`, regardless of the system's current local time.
*
* This seems like it should be easy, right? We don't need time zone data,
* because we're not specifying a time zone, just a UTC offset. All we need to
* do is basically parse out the string and format it back with the same offset
* it came in as.
*
* However, browsers are bad. JS Date objects more or less always get converted
* into UTC during parsing, and get converted into system-local time during
* formatting. Libraries like dayjs and date-fns further extend this behavior.
*
* You might think this would be a good use case for the fancy new Intl API,
* which supports time zones on newer browser. However, this API _requires a
* time zone name_, like 'Europe/Paris', to be passed when formatting, and
* doesn't support just passing a UTC offset.
*
* This left us with a few options:
*
* a) Add/subtract time from a system-local time to format in the offset time.
* This would require us to manually parse the UTC offset of the timestamp (the
* +XX:YY bit), and use time math to add both the system-local UTC offset, and
* the UTC offset of the timestamp, to a local time, then format it. This means
* that, on a system in the America/New_York zone, "3 PM Paris time" would
* become "9 AM New York time", then we'd add 5 hours for the UTC offset of New
* York, then 1 hour for the UTC offset of Paris, and the date would be "3 PM
* New York time", which would just get formatted as "3 PM". I don't like the
* idea of writing and maintaining this.
*
* b) Write custom logic just to parse and format the time part of an
* ISO8601-formatted time. I did this and hated how it looked, but it worked.
* This is the "low-cost" option, with only ~20 lines of new code, but also a
* bunch of tests and maintanence and a bunch of changes if you decide you want
* to format times in a more complicated way than just "3:00 PM".
*
* c) Pull in moment, which has moment.parseZone(). parseZone() is kind of a
* misnomer, because it doesn't actually handle _time zones_, just UTC offsets.
* Using `moment.parseZone(timeStamp).format()` will format your time with the
* same offset as specified in the timestamp.
*
* I'm going with (c), because it we're already using it elsewhere in our
* codebase (albiet not yet in this particular application, and while it's 12kb
* of additional JS, it's worth it to not have extra overhead).
*/
export default function formatTimeWithZone(timeString, fmtString = 'h:mm A') {
return moment.parseZone(timeString).format(fmtString);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment