Javascript 中的时区敏感日期比较
Timezone sensitive date comparisons in Javascript
我正在 Ember 应用程序中确定 Javascript 中两个日历日期之间的差异。我目前正在使用 date-fns 的 differenceInCalendarDays.
现在大部分都提供了所需的结果,唯一的问题是我需要处理计算对时区敏感的 2 个日期之间的差异(不是浏览器的本地时区)。
据我所知,JS 日期被跟踪为 UTC,日期对象本身没有存储时区。我在 JS 中完成的任何时区本地化都输出了一个字符串。
在考虑时区的同时,是否有好的库或方法来完成 differenceInCalendarDays?
const daysAgo = this.intl.formatRelative(-differenceInCalendarDays(new Date(), someOtherDay), {
unit: 'day',
numeric: 'auto',
timeZone: 'this.intl.timeZone
});
这是我正在做的事情的一个小样本,显然 differenceInCalendarDays 将解析为一个不考虑任何时区的数字。 differenceInDays 的文档对浏览器的本地时间时区敏感(这在这里没有帮助),但 differenceInCalendarDays 没有这样的提及。
任何帮助将不胜感激!
从逻辑上讲,2020-01-01
和 2020-01-02
两个日历日期之间的差异不区分时区,也根本不涉及时间。正好是一天。在这种情况下,一天不是 24 小时,而是一年的逻辑划分。把它想象成纸质日历上的一个正方形。
但是 - 在任何给定时刻,两个不同的时区可能在同一日历日期,或者它们可能在两个不同的日历日期。因此,在确定“现在”(或“今天”、“昨天”、“明天”等)日期时,时区很重要
为了说明这两点并希望能回答您的问题,可以使用以下代码获取给定时区自“今天”以来经过的天数:
function daysSince(year, month, day, timeZone) {
// Create a DateTimeFormat object for the given time zone.
// Force 'en' for English to prevent issues with languages that don't use Arabic numerals.
const formatter = new Intl.DateTimeFormat('en', { timeZone });
// Format "now" to a parts array, then pull out each part.
const todayParts = formatter.formatToParts(); // now is the default when no Date object is passed.
const todayYear = todayParts.find(x=> x.type === 'year').value;
const todayMonth = todayParts.find(x=> x.type === 'month').value;
const todayDay = todayParts.find(x=> x.type === 'day').value;
// Make a pseudo-timestamp from those parts, abusing Date.UTC.
// Note we are intentionally lying - this is not actually UTC or a Unix/Epoch timestamp.
const todayTimestamp = Date.UTC(+todayYear, todayMonth-1, +todayDay);
// Make another timestamp from the function input values using the same approach.
const otherTimestamp = Date.UTC(+year, month-1, +day);
// Since the context is the same, we can subtract and divide to get number of days.
return (todayTimestamp - otherTimestamp) / 864e5;
}
// example usage:
console.log("US Pacific: " + daysSince(2020, 1, 1, 'America/Los_Angeles'));
console.log("Japan: " + daysSince(2020, 1, 1, 'Asia/Tokyo'));
此方法仅适用于 UTC 没有转换(例如 DST 或标准时间偏移的更改)。
另请注意,我在这里不使用 Date
对象,因为我们必须非常注意这些对象的构造方式。如果您只有一个来自日期选择器 UI 的 Date
对象,则该对象很可能是在假设本地时间的情况下创建的 - 而不是特定时区的时间。因此,在继续之前,您需要从该对象中取出年、月和日。例如:
daysSince(dt.getFullYear(), dt.getMonth() + 1, dt.getDate(), 'America/New_York');
密切关注+1和-1。 Date
对象使用从 0 开始的月份,但我更喜欢从 1 开始的月份。
我正在 Ember 应用程序中确定 Javascript 中两个日历日期之间的差异。我目前正在使用 date-fns 的 differenceInCalendarDays.
现在大部分都提供了所需的结果,唯一的问题是我需要处理计算对时区敏感的 2 个日期之间的差异(不是浏览器的本地时区)。
据我所知,JS 日期被跟踪为 UTC,日期对象本身没有存储时区。我在 JS 中完成的任何时区本地化都输出了一个字符串。 在考虑时区的同时,是否有好的库或方法来完成 differenceInCalendarDays?
const daysAgo = this.intl.formatRelative(-differenceInCalendarDays(new Date(), someOtherDay), {
unit: 'day',
numeric: 'auto',
timeZone: 'this.intl.timeZone
});
这是我正在做的事情的一个小样本,显然 differenceInCalendarDays 将解析为一个不考虑任何时区的数字。 differenceInDays 的文档对浏览器的本地时间时区敏感(这在这里没有帮助),但 differenceInCalendarDays 没有这样的提及。 任何帮助将不胜感激!
从逻辑上讲,2020-01-01
和 2020-01-02
两个日历日期之间的差异不区分时区,也根本不涉及时间。正好是一天。在这种情况下,一天不是 24 小时,而是一年的逻辑划分。把它想象成纸质日历上的一个正方形。
但是 - 在任何给定时刻,两个不同的时区可能在同一日历日期,或者它们可能在两个不同的日历日期。因此,在确定“现在”(或“今天”、“昨天”、“明天”等)日期时,时区很重要
为了说明这两点并希望能回答您的问题,可以使用以下代码获取给定时区自“今天”以来经过的天数:
function daysSince(year, month, day, timeZone) {
// Create a DateTimeFormat object for the given time zone.
// Force 'en' for English to prevent issues with languages that don't use Arabic numerals.
const formatter = new Intl.DateTimeFormat('en', { timeZone });
// Format "now" to a parts array, then pull out each part.
const todayParts = formatter.formatToParts(); // now is the default when no Date object is passed.
const todayYear = todayParts.find(x=> x.type === 'year').value;
const todayMonth = todayParts.find(x=> x.type === 'month').value;
const todayDay = todayParts.find(x=> x.type === 'day').value;
// Make a pseudo-timestamp from those parts, abusing Date.UTC.
// Note we are intentionally lying - this is not actually UTC or a Unix/Epoch timestamp.
const todayTimestamp = Date.UTC(+todayYear, todayMonth-1, +todayDay);
// Make another timestamp from the function input values using the same approach.
const otherTimestamp = Date.UTC(+year, month-1, +day);
// Since the context is the same, we can subtract and divide to get number of days.
return (todayTimestamp - otherTimestamp) / 864e5;
}
// example usage:
console.log("US Pacific: " + daysSince(2020, 1, 1, 'America/Los_Angeles'));
console.log("Japan: " + daysSince(2020, 1, 1, 'Asia/Tokyo'));
此方法仅适用于 UTC 没有转换(例如 DST 或标准时间偏移的更改)。
另请注意,我在这里不使用 Date
对象,因为我们必须非常注意这些对象的构造方式。如果您只有一个来自日期选择器 UI 的 Date
对象,则该对象很可能是在假设本地时间的情况下创建的 - 而不是特定时区的时间。因此,在继续之前,您需要从该对象中取出年、月和日。例如:
daysSince(dt.getFullYear(), dt.getMonth() + 1, dt.getDate(), 'America/New_York');
密切关注+1和-1。 Date
对象使用从 0 开始的月份,但我更喜欢从 1 开始的月份。