在 JavaScript 中获取任何时区日期字符串的星期几的最佳方法是什么?

What's the best way in JavaScript to get the day of the week of a date string in any time zone?

我正在尝试在 JavaScript 中找到最好的方法来获取任何时区特定日期的星期几,只给定一个日期字符串。

具体来说,如果我有一个日期字符串,例如:

2022-01-29

然后我用那个字符串在JS中创建一个新的Date对象,然后在Date对象上调用getDay方法,因为我在“America/New_York”时区,我实际上获取该日期前一天的星期几,而不是日期本身的星期几。

这可以通过 运行:

轻松地向处于减去 UTC 时间的时区(例如美国、加拿大等)的任何人演示
new Date('2022-01-29').getDay()

星期六应该 return 6,但由于时区转换,我星期五得到 5

我找到了“ getTimezoneOffset 方法,例如:

var date = new Date('2016-08-25T00:00:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);

这似乎可行,但有几点:

  1. SO post 建议最后使用 - userTimezoneOffset,但它只适用于 + userTimezoneOffset。为什么?
  2. 关于 post 的评论说它不适用于夏令时或所有时区,我不确定如何轻松确认。在我最初的测试中,它似乎适用于夏令时,但也许我遗漏了一些东西,而且无论哪种方式,我都不确定如何在其他时区测试它。

当我只有一个日期字符串时,在 JavaScript 中获取星期几的最佳方法是什么?

let weekday = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][new Date().getDay()]

使用

new Date('2022-01-29').getUTCDay()

new Date('2022-01-29') 将使用 UTC(格林威治标准时间)日期“2022-01-29”和时间“00:00h”创建日期对象。当获得 .getDay() 的工作日时,您的浏览器会根据您的 local 时区计算它。通过使用 .getUTCDay(),您可以获得 UTC 时区的工作日。

@RayHatfield 提出的有趣观点

console.log("UTC-time:", new Date("2022-01-29").getUTCHours()) // 0
console.log("UTC-time:", new Date("2022-01-29Z00:00:00").getUTCHours()) // 0 ("Z" is for "ZULU" -> UTC)
console.log("UTC-time:", new Date("2022-01-29T00:00:00Z").getUTCHours()) // 0 (ISO 8601 date string -> UTC)
console.log("UTC-time:", new Date("2022-01-29T00:00:00").getUTCHours()) // UTC time (h) for your local midnight

有关日期字符串的详细信息,请参阅 https://en.m.wikipedia.org/wiki/ISO_8601

如果你想获得任何时区任何日期的工作日名称,你可以使用 toLocaleString 和合适的选项。

因为内置解析器将'2022-01-29'解析为UTC,所以时区需要设置为UTC。如果需要其他时区的日期名称,只需插入适当的 IANA 代表位置。

// Saturday
console.log(new Date('2022-01-29').toLocaleString('en',{
  weekday: 'long',
  timeZone: 'UTC'
}));

这样您就不会尝试手动调整日期。

OP 中的 getTimezoneOffset 方法也可以工作,即使偏移量已更改,例如夏令时或历史更改,但可以更简单一些:

let d = new Date('2022-01-29');
d.setMinutes(d.getMinutes() - d.getTimezoneOffset());

console.log(d.getDay()); // 6
console.log(d.toLocaleString('en',{weekday:'long'})); // Saturday