问题描述
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()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!