在 JavaScript 中使用 DST 的日期范围
Date ranges with DST in javascript
我正在寻找有关日期的最佳实践 - 重要的是日期本身,而不是当天的特定时间。
一个很好的开始是这个问题:夏令时和时区最佳做法
我想要一些指导,将其应用于我的情况。我的药物从特定日期开始,到另一个日期结束。然后,我需要查询在给定日期范围内处于活动状态的药物。
我尝试将开始和结束日期设置为当地时间午夜,然后以 UTC 格式存储在数据库中。我也可以添加时区条目。
我在客户端和服务器上都使用时刻.js,如果需要,可以使用时刻时区。
我想知道如何处理 DST 对我的时间的影响 - 这使得我在 DST 和非 DST 期间的本地午夜 UTC 时间相差一小时。
例如,我遇到的问题是,当某些药物的结束日期设置为DST期间,而有些药物的结束日期设置为非DST期间。然后,它们的 UTC 时间相差一个小时。当对从本地午夜开始的特定日期范围进行查询时,它并不准确,因为午夜有两种不同的表示形式。查询本身可能会将午夜视为两个不同时间之一,具体取决于在一年中进行查询的时间。
最终结果是,药物可能看起来比应有的晚一天结束,或者提前一天开始。
一个简单但不稳定的解决方法是始终将开始日期设置为标准(非 DST)时间的凌晨 1 点,将结束日期设置为标准(非 DST)时间的晚上 11:59,并在午夜进行查询。
或者,我应该检查每个查询的开始和结束日期,并计算出每个日期的 UTC 偏移量是多少?
但我更想知道在这种情况下的最佳实践是什么。谢谢。
Date
对象和 moment
对象在瞬间.js都用于表示特定的时刻。 换句话说,日期和时间。 它们通过计算自 Unix 时代(1970 年 1 月 1 日 UTC 午夜)以来经过的毫秒数在内部跟踪时间 - 忽略闰秒。
这意味着,从根本上说,它们不是处理整个日历日期的最佳方式。 当您只有一个日期,并且使用日期+时间值来跟踪它时,您将任意分配一天中的时间来表示一整天。 通常,这是午夜 - 但正如您指出的那样,这会导致夏令时出现问题。
考虑到在世界的某些地区(例如巴西),过渡发生在午夜 - 也就是说,在春季,时钟从 11:59:59 跳到 01:00:00。 如果您指定该日期的午夜,浏览器将向前或向后跳(取决于您使用的浏览器)!
如果将午夜的本地日期转换为其他时区(例如 UTC),则可以更改日期本身! 如果必须使用 date+time 来存储仅日期值,请使用中午而不是午夜。 这将缓解大多数(但不是全部)调整问题。
更好的主意是将整个日期视为整个日期。 不要为它们分配时间,也不要尝试将它们调整为 UTC。 不要使用Date
或moment
。 相反,将它们存储为 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课程,日期和时间基础。
- 正在更新起始日期角度日期范围选择器中的日期选择
- 如何从日期范围选择器中获取两个日期
- 基于日期范围的一组日期范围内的天数
- 过滤日期范围 angularjs 时出错
- 如何在引导日期选取器中限制可选择的日期范围
- 如何在 jQuery 日期选择器 UI 中阻止多个日期范围
- 根据主干集合中的日期范围进行选择
- 关于如何将日期输入值与最小/最大日期范围进行比较的建议
- 查找某个日期范围内的可用天数
- 正在将日期范围选择器转换为角度指令
- 在日期范围内查找丢失日期的最有效方法是什么
- XML查询日期范围查找
- 更改日期范围输入组件的格式
- 24小时格式的日期范围选取器
- jQuery:检索日期选择器日期,检查是否在日期范围内,显示/隐藏字段
- 如何在eonasdan Bootstrap 3 Datepicker上重置链接选取器的日期范围
- 从日期范围滑块访问最小值和最大值
- 什么是JavaScript日期范围
- 正在将日期范围选取器的开始日期设置为空
- RobinHubots jquery.inputmask日期范围