在 JavaScript 中使用 DST 的日期范围

Date ranges with DST in javascript

本文关键字:日期 范围 DST JavaScript      更新时间:2023-09-26

我正在寻找有关日期的最佳实践 - 重要的是日期本身,而不是当天的特定时间。

一个很好的开始是这个问题:夏令时和时区最佳做法

想要一些指导,将其应用于我的情况。我的药物从特定日期开始,到另一个日期结束。然后,我需要查询在给定日期范围内处于活动状态的药物。

我尝试将开始和结束日期设置为当地时间午夜,然后以 UTC 格式存储在数据库中。我也可以添加时区条目。

我在客户端和服务器上都使用时刻.js,如果需要,可以使用时刻时区。

我想知道如何处理 DST 对我的时间的影响 - 这使得我在 DST 和非 DST 期间的本地午夜 UTC 时间相差一小时。

例如,我遇到的问题是,当某些药物的结束日期设置为DST期间,而有些药物的结束日期设置为非DST期间。然后,它们的 UTC 时间相差一个小时。当对从本地午夜开始的特定日期范围进行查询时,它并不准确,因为午夜有两种不同的表示形式。查询本身可能会将午夜视为两个不同时间之一,具体取决于在一年中进行查询的时间。

最终结果是,药物可能看起来比应有的晚一天结束,或者提前一天开始。

一个简单但不稳定的解决方法是始终将开始日期设置为标准(非 DST)时间的凌晨 1 点,将结束日期设置为标准(非 DST)时间的晚上 11:59,并在午夜进行查询。

或者,我应该检查每个查询的开始和结束日期,并计算出每个日期的 UTC 偏移量是多少?

但我更想知道在这种情况下的最佳实践是什么。谢谢。

JavaScript

Date 对象和 moment 对象在瞬间.js都用于表示特定的时刻。 换句话说,日期和时间。 它们通过计算自 Unix 时代(1970 年 1 月 1 日 UTC 午夜)以来经过的毫秒数在内部跟踪时间 - 忽略闰秒。

这意味着,从根本上说,它们不是处理整个日历日期的最佳方式。 当您只有一个日期,并且使用日期+时间值来跟踪它时,您将任意分配一天中的时间来表示一整天。 通常,这是午夜 - 但正如您指出的那样,这会导致夏令时出现问题。

考虑到在世界的某些地区(例如巴西),过渡发生在午夜 - 也就是说,在春季,时钟从 11:59:59 跳到 01:00:00。 如果您指定该日期的午夜,浏览器将向前或向后跳(取决于您使用的浏览器)!

如果将午夜的本地日期转换为其他时区(例如 UTC),则可以更改日期本身! 如果必须使用 date+time 来存储仅日期值,请使用中午而不是午夜。 这将缓解大多数(但不是全部)调整问题。

更好的主意是将整个日期视为整个日期。 不要为它们分配时间,也不要尝试将它们调整为 UTC。 不要使用Datemoment。 相反,将它们存储为 ISO-8601 格式的字符串,如 "2014-11-25" ,或者如果您需要对它们进行数学运算,请考虑将它们存储为自某个起始值以来的整数整天。 例如,使用相同的 1970 年 1 月 1 日纪元日期,我们可以使用以下 JavaScript 将 2014 年 11 月 11 日表示为16399

function dateToValue(year, month, day) {
    return Date.UTC(year, month-1, day) / 86400000;
}
function valueToDate(value) {
    var d = new Date(86400000 * value);
    return { year : d.getUTCFullYear(), 
             month : d.getUTCMonth() + 1,
             day : d.getUTCDate()
           };
}

使用整个日期时,还需要记住其他一些事项:

  • 在处理整个日期的范围时,人类倾向于使用完全包含的间隔。 例如,1 月 1 日到 1 月 2 日将是两天。 这与日期+时间(和仅时间)范围不同,在日期+时间(和仅时间)范围内,人类倾向于使用半开放间隔。 例如,1:00 到 2:00 为一小时

  • 由于时区的原因,每个人对"今天"的概念在全球范围内都是不同的。 我们通常用我们自己的本地时区来定义"今天"。 所以通常:

    var d = new Date();
    var today = { year : d.getFullYear(), 
                  month : d.getMonth() + 1,
                  day : d.getDate()
                };
    
    • 通常不希望将其更改为 UTC 或其他时区,除非您的企业在该时区下在全球范围内运营。 这种情况很少见,但确实会发生。 (例如,StackOverflow使用UTC天数来计算徽章和其他成就。

我希望这能让你开始。 你问了一个相当广泛的问题,所以我试图以解决主要问题的方式回答。 如果您有更具体的内容,请更新您的问题,我会尽力回复。

如果您想了解有关此主题的更多信息,我鼓励您观看我的Pluralsight课程,日期和时间基础。