Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

date-fns | How do I format to UTC

Problem

It looks like when I use the format() function, it automatically convert the original UTC time into my timezone (UTC+8). I have been digging through their docs for hours and couldn't seem to find a way to default it to UTC time.

import { parseISO, format } from "date-fns";  const time = "2019-10-25T08:10:00Z";  const parsedTime = parseISO(time); console.log(parsedTime); // 2019-10-25T08:10:00.000Z  const formattedTime = format(parsedTime, "yyyy-MM-dd kk:mm:ss"); console.log(formattedTime); // 2019-10-25 16:10:00 <-- 8 HOURS OFF!! 

I have tried to use the package data-fns-tz and use something like

format(parsedTime, "yyyy-MM-dd kk:mm:ss", {timeZone: "UTC"}); 

still no luck.

Please help!

Expected Output

2019-10-25 08:10:00

Actual Output

2019-10-25 16:10:00

like image 257
Patrick Mao Avatar asked Oct 25 '19 15:10

Patrick Mao


People also ask

How do I change date format to UTC?

To convert a JavaScript date object to a UTC string, you can use the toUTCString() method of the Date object. The toUTCString() method converts a date to a string, using the universal time zone. Alternatively, you could also use the Date. UTC() method to create a new Date object directly in UTC time zone.

How do I create a UTC timestamp?

Use the getTime() method to get a UTC timestamp, e.g. new Date(). getTime() . The method returns the number of milliseconds since the Unix Epoch and always uses UTC for time representation.

How do I find my UTC date?

The GETUTCDATE() function returns the current database system UTC date and time, in a 'YYYY-MM-DD hh:mm:ss.

Does date FNS support timezone?

Date-fns supports time zone data to work with UTC or ISO date strings. This will help you display the date and time in the local time of your users. The difficulty comes when working with another time zone's local time, for example showing the local time of an event in LA at 8 pm PST on a Node.


2 Answers

You were almost there. This works for me:

import { parseISO } from "date-fns"; import { format, utcToZonedTime } from "date-fns-tz";  const time = "2019-10-25T08:10:00Z";  const parsedTime = parseISO(time); console.log(parsedTime); // 2019-10-25T08:10:00.000Z  const formatInTimeZone = (date, fmt, tz) =>   format(utcToZonedTime(date, tz),           fmt,           { timeZone: tz });  const formattedTime = formatInTimeZone(parsedTime, "yyyy-MM-dd kk:mm:ss xxx", "UTC"); console.log(formattedTime); // 2019-10-25 08:10:00 +00:00 

Behind the scenes

The date-fns[-tz] libraries stick to the built-in Date data type that carries no TZ info.
Some functions treat it as a moment-in-time, but some like format treat it more like a struct of calendaric components — year 2019, ..., day 25, hour 08, ....

Now the trouble is a Date is internally only a moment in time. Its methods provide a mapping to/from calendaric components in local time zone.

So to represent a different time zone, date-fns-tz/utcToZonedTime temporarily produces Date instances which represent the wrong moment in time — just to get its calendaric components in local time to be what we want!

And the date-fns-tz/format function's timeZone input affects only the template chars that print the time zone (XX..X, xx..x, zz..z, OO..O).

See https://github.com/marnusw/date-fns-tz/issues/36 for some discussion of this "shifting" technique (and of real use cases that motivated them)...
It's a bit low-level & risky, but the specific way I composed them above — formatInTimeZone() — is I believe a safe recipe.

like image 71
Beni Cherniavsky-Paskin Avatar answered Sep 16 '22 15:09

Beni Cherniavsky-Paskin


Note
The following solution will not work for all time zones, so if timezone accuracy is critical for your application you might want to try something like the answer from Beni. See this link for more info

I had the exact same question today and did some research to see if anyone has come up with anything better since this question was posed. I came across this solution which fit my needs and stylistic preference:

import { format, addMinutes } from 'date-fns';  function formatDate(date) {   return format(addMinutes(date, date.getTimezoneOffset()), 'yyyy-MM-dd HH:mm:ss'); } 

Explanation

getTimezoneOffset returns the number of minutes needed to convert that date to UTC. In PST (-0800 hours) it would return 480 whereas for somebody on CST (+0800 hours) it would return -480.

like image 26
Sherwin F Avatar answered Sep 19 '22 15:09

Sherwin F