获取不同时区的日期时间戳
Get Timestamp of date In a different timezone
我需要获取不同时区日期的时间戳。
例如 - 现在时间戳 (new Date().valueOf()
) 是:
1643530435160
在我的时区是 (new Date(1643530435160)
):
Sun Jan 30 2022 10:13:55 GMT+0200 (Israel Standard Time)
我需要这个日期 (10:13:55) 但作为时间戳但在时间戳中 - 这意味着我正在寻找这个时间戳:
1643555635000
所以我的解决方案是:
export const getTimeStampOfDateInEnvTimeZone = (timeStamp:number, timezoneForTesting:string = null):number => {
const envTimeZoneOffset = moment.tz.names()
.filter((name: string) => name === (timezoneForTesting || EnvSelector.TIME_ZONE))
.map((zone:string) => moment.tz(zone).format('Z'))[0];
return new Date(`${new Date(timeStamp)} GMT${envTimeZoneOffset}`).valueOf();
};
它看起来像工作 - 但是:
- 我不太乐意使用
moment
和 moment-timezone
,因为它们应该很快就会被弃用。
- 看起来这段代码在本地完美运行——我从浏览器、邮递员和单元测试中尝试过——但在产品中——我们在这段代码上遇到了一些问题,我们每次都没有得到预期的结果。
所以我想我们可能因为 AWS 远程服务器上的不同时区或类似的原因而遇到此代码问题?
寻找更好的解决方案 - 谢谢!
我相信有一种更简单的方法可以做到这一点,
但我发现的唯一方法,
没有时刻和moment-timezone,是:
首先得到时区偏移量是单位():
const getTimeZoneOffset = (date, timeZone) => {
// Abuse the Intl API to get a local ISO 8601 string for a given time zone.
const options = {
timeZone, calendar: 'iso8601', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false,
};
// @ts-ignore
const dateTimeFormat = new Intl.DateTimeFormat(undefined, options);
const parts = dateTimeFormat.formatToParts(date);
const map = new Map(parts.map((x) => [x.type, x.value]));
const year = map.get('year');
const month = map.get('month');
const day = map.get('day');
const hour = map.get('hour');
const minute = map.get('minute');
const second = map.get('second');
const ms = date.getMilliseconds().toString().padStart(3, '0');
const iso = `${year}-${month}-${day}T${hour}:${minute}:${second}.${ms}`;
// Lie to the Date object constructor that it's a UTC time.
const lie = new Date(`${iso}Z`);
// Return the difference in timestamps, as minutes
// Positive values are West of GMT, opposite of ISO 8601
// this matches the output of `Date.getTimeZoneOffset`
// @ts-ignore
return -(lie - date) / 60 / 1000;
};
比:
export const getTimeStampOfDateInEnvTimeZone = (timeStamp:number, userTimezone: string, timezoneForTesting:string = null) => {
const envTimeZoneOffsetInMinutes = getTimeZoneOffset(new Date(timeStamp), timezoneForTesting || EnvSelector.TIME_ZONE);
const userTimeZoneOffsetInMInutes = getTimeZoneOffset(new Date(timeStamp), userTimezone);
const difference = userTimeZoneOffsetInMInutes - envTimeZoneOffsetInMinutes;
const diffInMilliseconds = difference * 60000;
return timeStamp - diffInMilliseconds;
};
这些是验证此代码的单元测试:
describe('test getTimeStampOfDateInEnvTimeZone method', () => {
it('should verify that is we get the correct ts when user is in "Asia/Jerusalem" tz of and env is in "America/New_York" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643530435160, 'Asia/Jerusalem', 'America/New_York')).toBe(1643555635160);
});
it('should verify that is we get the correct ts when user is in "Asia/Jerusalem" tz of and env is in "America/Santa_Isabel" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643303881092, 'Asia/Jerusalem', 'America/Santa_Isabel')).toBe(1643339881092);
});
it('should verify that is we get the correct ts when user is in "America/New_York" tz of and env is in "Asia/Jerusalem" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643555635160, 'America/New_York', 'Asia/Jerusalem')).toBe(1643530435160);
});
it('should verify that is we get the correct ts when user is in "America/Santa_Isabel" tz of and env is in "Asia/Jerusalem" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643339881092, 'America/Santa_Isabel', 'Asia/Jerusalem')).toBe(1643303881092);
});
it('should verify that is we get the correct ts when user is in "America/Santa_Isabel" tz of and env is in "America/Santa_Isabel" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643339881092, 'America/Santa_Isabel', 'America/Santa_Isabel')).toBe(1643339881092);
});
it('should verify that is we get the correct ts when user is in "Africa/Douala" tz of and env is in "Pacific/Tahiti" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643808653000, 'Africa/Douala', 'Pacific/Tahiti')).toBe(1643848253000);
});
it('should verify that is we get the correct ts when user is in "Pacific/Tahiti" tz of and env is in "Africa/Douala" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643555635000, 'Pacific/Tahiti', 'Africa/Douala')).toBe(1643516035000);
});
});
我需要获取不同时区日期的时间戳。
例如 - 现在时间戳 (new Date().valueOf()
) 是:
1643530435160
在我的时区是 (new Date(1643530435160)
):
Sun Jan 30 2022 10:13:55 GMT+0200 (Israel Standard Time)
我需要这个日期 (10:13:55) 但作为时间戳但在时间戳中 - 这意味着我正在寻找这个时间戳:
1643555635000
所以我的解决方案是:
export const getTimeStampOfDateInEnvTimeZone = (timeStamp:number, timezoneForTesting:string = null):number => {
const envTimeZoneOffset = moment.tz.names()
.filter((name: string) => name === (timezoneForTesting || EnvSelector.TIME_ZONE))
.map((zone:string) => moment.tz(zone).format('Z'))[0];
return new Date(`${new Date(timeStamp)} GMT${envTimeZoneOffset}`).valueOf();
};
它看起来像工作 - 但是:
- 我不太乐意使用
moment
和moment-timezone
,因为它们应该很快就会被弃用。 - 看起来这段代码在本地完美运行——我从浏览器、邮递员和单元测试中尝试过——但在产品中——我们在这段代码上遇到了一些问题,我们每次都没有得到预期的结果。
所以我想我们可能因为 AWS 远程服务器上的不同时区或类似的原因而遇到此代码问题?
寻找更好的解决方案 - 谢谢!
我相信有一种更简单的方法可以做到这一点, 但我发现的唯一方法, 没有时刻和moment-timezone,是:
首先得到时区偏移量是单位(
const getTimeZoneOffset = (date, timeZone) => {
// Abuse the Intl API to get a local ISO 8601 string for a given time zone.
const options = {
timeZone, calendar: 'iso8601', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false,
};
// @ts-ignore
const dateTimeFormat = new Intl.DateTimeFormat(undefined, options);
const parts = dateTimeFormat.formatToParts(date);
const map = new Map(parts.map((x) => [x.type, x.value]));
const year = map.get('year');
const month = map.get('month');
const day = map.get('day');
const hour = map.get('hour');
const minute = map.get('minute');
const second = map.get('second');
const ms = date.getMilliseconds().toString().padStart(3, '0');
const iso = `${year}-${month}-${day}T${hour}:${minute}:${second}.${ms}`;
// Lie to the Date object constructor that it's a UTC time.
const lie = new Date(`${iso}Z`);
// Return the difference in timestamps, as minutes
// Positive values are West of GMT, opposite of ISO 8601
// this matches the output of `Date.getTimeZoneOffset`
// @ts-ignore
return -(lie - date) / 60 / 1000;
};
比:
export const getTimeStampOfDateInEnvTimeZone = (timeStamp:number, userTimezone: string, timezoneForTesting:string = null) => {
const envTimeZoneOffsetInMinutes = getTimeZoneOffset(new Date(timeStamp), timezoneForTesting || EnvSelector.TIME_ZONE);
const userTimeZoneOffsetInMInutes = getTimeZoneOffset(new Date(timeStamp), userTimezone);
const difference = userTimeZoneOffsetInMInutes - envTimeZoneOffsetInMinutes;
const diffInMilliseconds = difference * 60000;
return timeStamp - diffInMilliseconds;
};
这些是验证此代码的单元测试:
describe('test getTimeStampOfDateInEnvTimeZone method', () => {
it('should verify that is we get the correct ts when user is in "Asia/Jerusalem" tz of and env is in "America/New_York" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643530435160, 'Asia/Jerusalem', 'America/New_York')).toBe(1643555635160);
});
it('should verify that is we get the correct ts when user is in "Asia/Jerusalem" tz of and env is in "America/Santa_Isabel" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643303881092, 'Asia/Jerusalem', 'America/Santa_Isabel')).toBe(1643339881092);
});
it('should verify that is we get the correct ts when user is in "America/New_York" tz of and env is in "Asia/Jerusalem" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643555635160, 'America/New_York', 'Asia/Jerusalem')).toBe(1643530435160);
});
it('should verify that is we get the correct ts when user is in "America/Santa_Isabel" tz of and env is in "Asia/Jerusalem" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643339881092, 'America/Santa_Isabel', 'Asia/Jerusalem')).toBe(1643303881092);
});
it('should verify that is we get the correct ts when user is in "America/Santa_Isabel" tz of and env is in "America/Santa_Isabel" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643339881092, 'America/Santa_Isabel', 'America/Santa_Isabel')).toBe(1643339881092);
});
it('should verify that is we get the correct ts when user is in "Africa/Douala" tz of and env is in "Pacific/Tahiti" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643808653000, 'Africa/Douala', 'Pacific/Tahiti')).toBe(1643848253000);
});
it('should verify that is we get the correct ts when user is in "Pacific/Tahiti" tz of and env is in "Africa/Douala" time zone', () => {
expect.hasAssertions();
expect(getTimeStampOfDateInEnvTimeZone(1643555635000, 'Pacific/Tahiti', 'Africa/Douala')).toBe(1643516035000);
});
});