20

I have a requirement, where I need to show a user's time in their local time zone. This needs to be done using date-fns.

The following code checks the current time and then given a timezone converts it into local time as per the time zone.

const { formatToTimeZone } = require('date-fns-timezone')

let date = new Date()
const format = 'D.M.YYYY HH:mm:ss [GMT]Z (z)'
const output = formatToTimeZone(date, format, { timeZone: 'Asia/Calcutta' })

However, how do I guess the user's timezone on the fly?

In moment.js, you can get it with moment.tz.guess(). But how can I do it without moment.js and by using date-fns?

https://runkit.com/embed/835tsn9a87so

UPDATE: I will be using this inside a VueJS application. So, if there are any other related solutions, those are welcomed as well. Thanks.

asanas
  • 3,782
  • 11
  • 43
  • 72
  • You don't have to guess anything. The timezone is automatically supplied by the browser whenever you create a new date object. – Borisu Feb 06 '19 at 15:03
  • Ok. And is it possible to explicitly read it in my app? Say for example, if I want to display a message like You are in 'x/y' time zone. – asanas Feb 06 '19 at 15:06
  • @asanas I would recommend you change your question's title and remove the " in a VueJS app?" as your question is valid in any js app. also it is better to remove the vue tags as well. – Iman Mahmoudinasab Sep 01 '20 at 20:58
  • @ImanMahmoudinasab done. thanks! – asanas Sep 07 '20 at 03:12

2 Answers2

43

To get the user's IANA time zone identifier, most modern browsers now support the following:

Intl.DateTimeFormat().resolvedOptions().timeZone

That said, the usual reason you would need to use formatToTimeZone from date-fns-timezone is when you need to use a different time zone other than the user's local zone. Otherwise, you can usually just use the format function from date-fns.

However, in your case, you are also trying to use the z format specifier to display the user's time zone abbreviation. This isn't provided by date-fns directly, so if that is critical then you will indeed need to get the user's time zone with the Intl api shown above and use formatToTimeZone.

Do keep in mind though that these abbreviations are whatever the IANA data has recorded, which are in English only, and it doesn't have abbreviations for every time zone. For those that don't, you will see a numeric value instead, such as -02.

Also, many abbreviations can be ambiguous (such as the I in IST possibly meaning India, Israel, or Ireland, and many others...). Thus, in most cases, if you don't need the abbreviation, you're often better off without it.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
7

Just solved a similar problem myself. The trick is to use the format function from date-fns-tz instead of the one from date-fns.

import { format } from "date-fns";
console.log(format(new Date(), "yyyy-MM-dd HH:mm z"));
// 2021-11-29 13:55 GMT-8

import { format } from "date-fns-tz";
console.log(format(new Date(), "yyyy-MM-dd HH:mm z"));
// 2021-11-29 13:55 PST

See documentation here: https://date-fns.org/v2.27.0/docs/Time-Zones

Ben Harris
  • 71
  • 1
  • 2
  • In the first format shouldn't it be a capital `Z`? – AlexDev May 11 '22 at 15:56
  • @AlexDev Yeah, the point of my original comment is that if you use the `format` function from `date-fns` is formats lowercase `z` incorrectly as if it were uppercase `Z`. If you use the function from `date-fns-tz` it works as expected. – Ben Harris May 12 '22 at 19:43
  • For me I got an actual `z` instead of `GMT-8`. Maybe I'm on an older version though. – AlexDev May 13 '22 at 19:00