涉及日期FNS的时区问题format() [英] Time zone issue involving date fns format()

查看:126
本文介绍了涉及日期FNS的时区问题format()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

const dt = new Date('2017-12-12');
console.log(format(dt, 'YYYY-MM-DD'));

上面的代码在美国记录为2017-12-11,而在印度记录为2017-12-12.

The above code logs 2017-12-11 in the US, but 2017-12-12 in India.

我遵循了这个github线程此处,并尝试了一些方法,但是没有得到预期的结果.

I followed this github thread here and tried out things but am not getting the desired results.

我希望无论时区如何都打印相同的日期

My expectation is to print the same date irrespective of time zone

为什么我需要这个:考虑一个涉及生日的场景.如果我要输入日期,则必须在所有区域中将其显示为相同的日期,而不管其时区如何.

Why I need this : Consider a scenario involving birthdates. If i am giving some input date, it has to be displayed as same date in all regions irrespective of their timezones.

推荐答案

您需要先从 Date 实例中减去本地时区的时区偏移,然后再将其传递给 date-fns 的> format .例如:

You will need to subtract the time zone offset of your local time zone from the Date instance, before you pass it to format from date-fns. For example:

const dt = new Date('2017-12-12');
const dtDateOnly = new Date(dt.valueOf() + dt.getTimezoneOffset() * 60 * 1000);
console.log(format(dtDateOnly, 'YYYY-MM-DD')); // Always "2017-12-12"

问题

您只想处理 Date 实例的日期部分,因为时间部分对生日没有意义.但是, Date 对象不提供任何仅日期"对象.模式.您可以在当地时区或UTC中访问其日期和时间部分.问题是,来自 date-fns format 总是在本地时区打印输出.

Problem

You want to handle only the date part of the Date instance, because the time part does not make sense for birthdates. However, the Date object does not offer any "date-only" mode. You can access both its date and time parts in the local time zone or UTC. The problem is, that format from date-fns prints the output always in the local time zone.

仅在日期部分执行构造函数时:

When you executed the constructor only with the date part:

const dt = new Date('2017-12-12');

JavaScript引擎实际上假定了不完整的ISO 8601格式的字符串,并且对此进行了填充:

The JavaScript engine actually assumed a string in the incomplete ISO 8601 format and perfomed this:

const dt = new Date('2017-12-12T00:00:00.000Z');

它看起来仍然无害".对您来说,但 date 实例不仅在UTC中而且还在本地时区公开该值.如果在美国东海岸构造 Date 实例,您将看到以下输出:

It may still look "harmless" to you, but the date instance exposes the value not only in UTC, but also in the local time zone. If you construct the Date instance on the East Coast of the US, you will see the following output:

> const dt = new Date('2017-12-12');
> dt.toISOString()
'2017-12-12T00:00:00.000Z'
> dt.toString()
'Tue Dec 11 2017 19:00:00 GMT-0500 (EST)'
> d.toLocaleString()
'12/11/2017 7:00:00 PM'

解决方案

如果您知道 date-fns 中的 format 会从本地时区的 date 实例中读取日期和时间部分,则您将需要使您的约会看起来像"传递给 Date 构造函数的本地时区中的午夜,而不是UTC中的午夜.然后,您将看到保留的年,月和日期数字.这意味着,您需要减去指定日期的本地时区的时区偏移量. Date.prototype.getTimezoneOffset 返回偏移量,但带有倒置符号,以分钟为单位.

Solution

If you know, that format from date-fns reads date and time parts from the date instance in the local time zone, you will need to make your date "looking like" the midnight in your local time zone and not in UTC, which you passed to the Date constructor. Then you will see the year, month and date numbers preserved. It means, that you need to subtract the time zone offset of your local time zone for the specified day. Date.prototype.getTimezoneOffset returns the offset, but with an inverted sign and in minutes.

const dt = new Date('2017-12-12');
// Tue Dec 11 2017 19:00:00 GMT-0500 (EST)
const dtDateOnly = new Date(dt.valueOf() + dt.getTimezoneOffset() * 60 * 1000);
// Tue Dec 12 2017 00:00:00 GMT-0500 (EST)
console.log(format(dtDateOnly, 'YYYY-MM-DD'));
// Prints always "2017-12-12", regardless the time zone it executed in

但是,这样的 Date 实例只能用于格式化仅日期值.例如,您不能将其用于计算日期差,这可能需要原始且正确的UTC值.

However, such Date instance can be used only to format the date-only value. You cannot use it for computing date differences, for example, which would need the original and correct UTC value.

如果您始终需要相同的仅日期格式,而不需要特定于当前语言环境的格式,则不需要 date-fns .您可以通过填充数字的串联来设置字符串的格式:

If you need always the same date-only format and not the format specific to the current locale, you do not need date-fns. You can format the string by the concatenation of padded numbers:

const dt = new Date('2017-12-12');

const year = dt.getUTCFullYear()
const month = dt.getUTCMonth() + 1 // Date provides month index; not month number
const day = dt.getUTCDate()

// Print always "2017-12-12", regardless the time zone it executed in
console.log(year + '-' + padToTwo(month) + '-', padToTwo(day));
// Or use a template literal
console.log(`${year}-${padToTwo(month)}-${padToTwo(day)}`);

function padToTwo (number) {
  return number > 9 ? number : '0' + number
}

这篇关于涉及日期FNS的时区问题format()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆