javascript - 涉及日期 fns 格式的时区问题()

标签 javascript datetime location locale date-fns

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

以上代码在美国记录 2017-12-11,但在印度记录 2017-12-12。

我关注了这个 github 线程 here并尝试了一些东西,但没有得到想要的结果。

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

为什么我需要这个: 考虑一个涉及生日的场景。如果我提供一些输入日期,它必须在所有地区显示为相同的日期,而不管它们的时区如何。

最佳答案

在从 date-fns< 将其传递给 format 之前,您需要从 Date 实例中减去本地时区的时区偏移量。例如:

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 总是在本地时区打印输出。

当您仅使用日期部分执行构造函数时:

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

JavaScript 引擎实际上假设了一个不完整的 ISO 8601 格式的字符串并执行了这个:

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

它对您来说可能仍然看起来“无害”,但是 date 实例不仅公开了 UTC 的值,还公开了本地时区的值。如果您在美国东海岸构建 Date 实例,您将看到以下输出:

> 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 返回偏移量,但带有倒号并以分钟为单位。

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 值。

备选

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

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
}

关于javascript - 涉及日期 fns 格式的时区问题(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48172772/

相关文章:

javascript - 函数返回 [Object Object] 不是值

php - 检测 DateTime 对象中是否指定了时间

python - 使用Python解析日期时间范围之间的日志

java - Java获取用户当前的经纬度

iphone - 在室内可靠地定位 iPhone?

javascript - 获取 ES6 循环的上一项

javascript - 事件未从窗口中删除

javascript - 引用错误 : variable is not defined

java - Scala Slick 3.0 java8 OffsetDateTime 和 Timestamp 之间的隐式映射

android如何以7位或更多位精度获取当前位置