date-fns|如何格式化为UTC



问题

当我使用format()函数时,它会自动将原始UTC时间转换为我的时区(UTC+8(。我已经在他们的文档中搜索了几个小时,似乎找不到默认为UTC时间的方法。

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!!

我试着使用data-fns-tz包,并使用类似的东西

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

仍然没有运气。

请帮忙!

预期输出

2019-10-25 08:10:00

实际输出

2019-10-25 16:10:00

你差不多到了。这对我有效:

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

幕后

日期fns[-tz]库坚持使用不携带tz信息的内置Date数据类型
有些函数将其视为一个时刻,但有些函数(如format(则将其更像是日历组件的结构——2019年。。。,第25天08小时。。。。

现在的问题是Date在内部只是一个瞬间。它的方法提供了到本地时区中日历组件的映射。

因此,为了表示不同的时区,date-fns-tz/utcToZonedTime临时生成Date实例,这些实例表示错误的时间时刻——只是为了使其在本地时间的日历组件成为我们想要的!

date-fns-tz/format函数的时区输入仅影响打印时区的模板字符(XX..Xxx..xzz..zOO..O(。

请参阅https://github.com/marnusw/date-fns-tz/issues/36为了对此进行一些讨论;移位";技术(以及激励他们的真实用例(
这有点低级&风险很大,但我在上面编写它们的具体方式——formatInTimeZone()——是我认为安全的配方。

我建议使用内置的Dateutil:

const date = new Date("2019-10-25T08:10:00Z");
const isoDate = date.toISOString();
console.log(`${isoDate.substring(0, 10)} ${isoDate.substring(11, 19)}`);

输出:

2019-10-25 08:10:00

不是任何格式的通用解决方案,但不需要外部库。

注意
以下解决方案不适用于所有时区,因此,如果时区准确性对您的应用程序至关重要,您可能需要尝试类似Beni的答案。查看此链接了解更多信息

我今天也有同样的问题,并做了一些研究,看看自从这个问题提出以来,是否有人想出了更好的办法。我发现了一个符合我的需求和风格偏好的解决方案:

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

解释

getTimezoneOffset返回将该日期转换为UTC所需的分钟数。在太平洋标准时间(0800小时(,它将返回480,而在CST(+0800小时(,则返回-480。

我也遇到了同样的问题。我所做的是从ISO字符串中删除时区,然后将该时间与日期fns:一起使用

let time = "2019-10-25T08:10:00Z".slice(0, -1)

上面是一个没有时区的时间,因为没有时区,所以fns假设为本地时区,所以当你这样做时:

format(parseISO(time), 'h:mm a')

您可以得到:8:10AM,或者您喜欢的任何格式。你只需要小心你正在切的绳子。如果它总是相同的格式,那么它应该可以工作。

我使用日期/fns和本机日期方法做了类似的事情

import format from 'date-fns/format';
import parseISO from 'date-fns/parseISO';
export const adjustForUTCOffset = date => {
return new Date(
date.getUTCFullYear(),
date.getUTCMonth(),
date.getUTCDate(),
date.getUTCHours(),
date.getUTCMinutes(),
date.getUTCSeconds(),
);
};
const formatDate = (dateString) = > {
const date = parseISO(dateString);
const dateWithOffset = adjustForUTCOffset(date)
return format(dateWithOffset, 'LLL dd, yyyy HH:mm')
}

以下是我的操作方法

const now = new Date()
const date = format(
new Date(now.toISOString().slice(0, -1)),
'yyyy-MM-dd HH:mm:ss'
)

我刚从ISO字符串中删除了Z。我不确定它是否通过解决了这个问题

时间戳解决方案

format(utcToZonedTime(timestamp, 'UTC'), 'MM/dd/yyyy hh:mm a', { timeZone: 'UTC' })

我猜

在解析之前将日期构造为UTC会很有帮助。

import { parseISO, format } from "date-fns";
const time = "2019-10-25T08:10:00Z";
const parsedTime = parseISO(new Date(Date.UTC(time)));
const formattedTime = format(parsedTime, "yyyy-MM-dd kk:mm:ss");

像这样。

尝试

const formatDate = new Date().toISOString().substr(0, 19).replace('T', ' ');

最新更新