如何在javascript中获取日期的开始 - 考虑时区

How to the get the beginning of day of a date in javascript -- factoring in timezone

本文关键字:开始 时区 取日期 javascript 获取      更新时间:2023-09-26

我正在努力找出JavaScript中时区因素的开始。 请考虑以下事项:

   var raw_time = new Date(this.created_at);
   var offset_time = new Date(raw_hour.getTime() + time_zone_offset_in_ms);
   // This resets timezone to server timezone
   var offset_day = new Date(offset_time.setHours(0,0,0,0))
   // always returns 2011-12-08 05:00:00 UTC, no matter what the offset was!
   // This has the same issue:
   var another_approach_offset_day = new Date(offset_time.getFullYear(),offset_time.getMonth(),offset_time.getHours())

我希望当我通过太平洋时区偏移量时,得到:2011-12-08 08:00:00 UTC等等。

实现这一目标的正确方法是什么?

我认为问题的一部分是 setHours 方法根据当地时间设置小时(从 0 到 23(。

另请注意,我使用的是嵌入在 mongo 中的 javascript,所以我无法使用任何其他库。

谢谢!


哎呀,这对我来说真的很难,但这是我想出以下解决方案的最终解决方案。 诀窍是我需要使用 setHours 或 SetUTCHours 来获取一天的开始 - 我唯一的选择是系统时间和 UTC。 所以我得到了 UTC 一天的开始,然后重新添加偏移量!

// Goal is given a time and a timezone, find the beginning of day
function(timestamp,selected_timezone_offset) {
  var raw_time = new Date(timestamp)
  var offset_time = new Date(raw_time.getTime() + selected_timezone_offset);
  offset_time.setUTCHours(0,0,0,0);
  var beginning_of_day = new Date(offset_time.getTime() - selected_timezone_offset);
  return beginning_of_day;
}

在 JavaScript 中,所有日期都存储为 UTC。 也就是说,date.valueOf()返回的序列号是自 1970-01-01 00:00:00 UTC 以来的毫秒数。 但是,当您通过.toString().getHours()等检查日期时,您将获得本地时间的值。 即运行脚本的系统的本地时间。 您可以使用 .toUTCString().getUTCHours() 等方法获取 UTC 中的值。

因此,您无法在任意时区中获取日期,它都是UTC(或本地时间(。 但是,当然,如果您知道 UTC 偏移量,则可以在您喜欢的任何时区中获得日期的字符串表示形式。 最简单的方法是从日期中减去 UTC 偏移量,然后调用.getUTCHours().toUTCString()或任何您需要的内容:

var d = new Date();
d.setMinutes(d.getMinutes() - 480); // get pacific standard time
d.toUTCString(); // returns "Fri, 9 Dec 2011 12:56:53 UTC"

当然,如果您使用 .toUTCString(),则需要忽略最后的"UTC"。 你可以去:

d.toUTCString().replace(/UTC$/, "PST");

编辑:不必担心时区何时与日期边界重叠。 如果您传递负数setHours(),它将从昨天午夜减去这些小时数。 例如:

var d = new Date(2011, 11, 10, 15); // d represents Dec 10, 2011 at 3pm local time
d.setHours(-1);                     // d represents Dec 9, 2011 at 11pm local time
d.setHours(-24);                    // d represents Dec 8, 2011 at 12am local time
d.setHours(52);                     // d represents Dec 10, 2011 at 4am local time

您使用的time_zone_offset_in_ms变量来自哪里? 也许它不可靠,你应该使用Date的getTimezoneOffset((方法。 以下 URL 中有一个示例:

http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp

如果您知道其他日期字符串中的日期,则可以执行以下操作:

var currentDate = new Date(this.$picker.data('date'));
var today = new Date();
today.setHours(0, -currentDate.getTimezoneOffset(), 0, 0);

(基于我做的一个项目的代码库(

var aDate = new Date();
var startOfTheDay = new Date(aDate.getTime() - aDate.getTime() % 86400000)
将创建一天的开始

,有问题的一天的开始

您可以使用 Intl.DateTimeFormat。这也是 luxon 处理时区的方式。

下面的代码可以将任何时区的任何日期转换为时间的开始/结束。

const beginingOfDay = (options = {}) => {
  const { date = new Date(), timeZone } = options;
  const parts = Intl.DateTimeFormat("en-US", {
    timeZone,
    hourCycle: "h23",
    hour: "numeric",
    minute: "numeric",
    second: "numeric",
  }).formatToParts(date);
  const hour = parseInt(parts.find((i) => i.type === "hour").value);
  const minute = parseInt(parts.find((i) => i.type === "minute").value);
  const second = parseInt(parts.find((i) => i.type === "second").value);
  return new Date(
    1000 *
      Math.floor(
        (date - hour * 3600000 - minute * 60000 - second * 1000) / 1000
      )
  );
};
const endOfDay = (...args) =>
  new Date(beginingOfDay(...args).getTime() + 86399999);
const beginingOfYear = () => {};
console.log(beginingOfDay({ timeZone: "GMT" }));
console.log(endOfDay({ timeZone: "GMT" }));
console.log(beginingOfDay({ timeZone: "Asia/Tokyo" }));
console.log(endOfDay({ timeZone: "Asia/Tokyo" }));