将日期转换为 UTC 时间戳
Posted
技术标签:
【中文标题】将日期转换为 UTC 时间戳【英文标题】:Convert Date to UTC timestamp 【发布时间】:2021-10-06 00:46:00 【问题描述】:我有一个有时间的约会,像这样
const date = year: 2020, month: 12, day: 31;
const time = hours: 16, minutes: 2;
如何根据时区获取该时间的 UTC 表示? (不使用任何库)
convetToUTC(date, time, "Europe/Moscow") // => <UTC timestamp>
convetToUTC(date, time, "America/New_York") // => <UTC timestamp>
例子
convetToUTC(
year: 2021, month: 7, day: 30,
hours: 16, minutes: 15,
"Europe/Moscow"
) // => 1627650900
convetToUTC(
year: 2021, month: 7, day: 30,
hours: 16, minutes: 15,
"America/New_York"
) // => 1627676100
【问题讨论】:
请查看https://***.com/questions/9756120/how-do-i-get-a-utc-timestamp-in-javascript
检查,看不到任何提示如何进行任意时区转换
“我如何根据时区获得该时间的 UTC 表示。”这是否意味着您要获取指定的日期和时间,将其视为指定时区的日期和时间,然后获取该时刻的 UTC 时间戳?
x = new Date() var UTCseconds = (x.getTime() + x.getTimezoneOffset()*60*1000)/1000; console.log("UTCseconds", UTCseconds)
@Forest1 这不适用于本地时区以外的任何地方。 OP 希望为任意时区做到这一点。
【参考方案1】:
const dateWithTimeZone = (timeZone, year, month, day, hour, minute, second) =>
let date = new Date(Date.UTC(year, month, day, hour, minute, second));
let utcDate = new Date(date.toLocaleString('en-US', timeZone: "UTC" ));
let tzDate = new Date(date.toLocaleString('en-US', timeZone: timeZone ));
let offset = utcDate.getTime() - tzDate.getTime();
date.setTime( date.getTime() + offset );
return date;
;
dateWithTimeZone("America/New_York", 2021, 7 - 1, 30, 16, 15, 0).getTime() / 1000)
// => 1627676100
dateWithTimeZone("Europe/Moscow", 2021, 7 - 1, 30, 16, 15, 0).getTime() / 1000)
// => 1627650900
7 - 1
用于说明该函数接受月份的索引,而不是月份的数字
【讨论】:
在 2021 年 11 月 7 日星期日凌晨 3:30 对纽约进行测试,然后获取结果并为纽约创建时间戳:new Date(value*1e3).toLocaleString('default',timeZone:'America/New_York')
。一个小时后就出来了。【参考方案2】:
借助 Achempion 的响应,我修复了时区偏移计算。应从 UTC 日期中减去时区日期。这种差异的结果应该以分钟为单位。
您需要将分钟偏移量转换回毫秒并从日期中减去。
/**
* Calculates the timezone offset of a particular time zone.
* @param String timeZone - a database time zone name
* @param Date date - a date for determining if DST is accounted for
* @return Number returns an offset in minutes
* @see https://***.com/a/68593283/1762224
*/
const getTimeZoneOffset = (timeZone = 'UTC', date = new Date()) =>
const utcDate = new Date(date.toLocaleString('en-US', timeZone: 'UTC' ));
const tzDate = new Date(date.toLocaleString('en-US', timeZone ));
return (tzDate.getTime() - utcDate.getTime()) / 6e4;
const defaultDateConfig = year: 0, month: 0, date: 0 ;
const defaultTimeConfig = hours: 0, minutes: 0, seconds: 0 ;
const convetToUTC = (dateConfig, timeConfig, timeZone) =>
const year, month, date = ...defaultDateConfig, ...dateConfig ;
const hours, minutes, seconds = ...defaultTimeConfig, ...timeConfig ;
const d = new Date(Date.UTC(year, month - 1, date, hours, minutes, seconds));
const offsetMs = getTimeZoneOffset(timeZone, d) * 6e4;
return (d.getTime() - offsetMs) / 1e3;
;
// Main
const date = year: 2021, month: 7, date: 30 ;
const time = hours: 16, minutes: 15 ;
console.log(convetToUTC(date, time, 'America/New_York')); // 1627676100
console.log(convetToUTC(date, time, 'Europe/Moscow')); // 1627650900
【讨论】:
我认为使用 10**3 甚至 1000 会使功能比使用 1e3 更简单 @achemion1e3
其实和1000
一样,只是科学记数法;而10**3
是功率计算。后者是Math.pow(10, 3)
的有效语法糖。
实际上没有必要在 getTimeZoneOffset 中对 6e4 进行除法然后将其相乘,因为您仍将秒数保留在偏移量中,因为 devision 会产生浮点数并且您不会对其进行舍入
@achemion getTimeZoneOffset
函数独立于 convetToUTC
中的逻辑。如果您查看MDN: Date.prototype.getTimezoneOffset()。它指出结果以分钟为单位。作为经验法则,我坚持这一点。我更新了我的代码以包含一些 JS 文档以获取更多信息。
我同意你在这里采用了正确的方法,我们应该在 getTimeZoneOffset 函数中返回分钟。问题是它返回像这样的值 1627661700.24,其中最后的“.24”部分意味着它仍然存在秒部分。通过“它声明结果以分钟为单位”。我认为您的意思是整分钟,但您的函数可以返回 1min 30m 秒作为示例。以上是关于将日期转换为 UTC 时间戳的主要内容,如果未能解决你的问题,请参考以下文章