如何在 JavaScript 中获取 UTC 时间戳?

Posted

技术标签:

【中文标题】如何在 JavaScript 中获取 UTC 时间戳?【英文标题】:How do I get a UTC Timestamp in JavaScript? 【发布时间】:2012-04-03 02:37:00 【问题描述】:

在编写 Web 应用程序时,将(服务器端)所有日期时间作为 UTC 时间戳存储在数据库中是有意义的。

当我注意到在 javascript 中的时区操作方面,您本身无法做很多事情时,我感到很惊讶。

我稍微扩展了 Date 对象。这个功能有意义吗?基本上,每次我向服务器发送任何东西时,它都会是一个用这个函数格式化的时间戳......

你能看出这里有什么大问题吗?还是换个角度的解决方案?

Date.prototype.getUTCTime = function() 
  return new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime(); 

这对我来说似乎有点令人费解。我也不太确定性能。

【问题讨论】:

我知道这是一个老问题,但尽量不要扩展像 Date 对象这样的原生对象。赞成,因为我喜欢这个问题本身。 Date.parse(new Date().toUTCString()) 这是我今天的提要中出现的一个老问题,其中充满了错误信息。 时间戳始终采用 UTC。 new Date().toString() 将显示当前时区时间表示,new Date().toUTCString() 将显示 UTC 时间 repr,但 new Date().getTime() 始终为 UTC,因为这就是 Unix 时间的定义:“Unix 时间(也称为 POSIX 时间或纪元时间)是用于描述时间瞬间的系统,定义为自协调世界时 00:00:00 以来经过的秒数(UTC),1970 年 1 月 1 日星期四,不包括闰秒。” 【参考方案1】:

    以这种方式构造的日期使用本地时区,导致构造的日期不正确。设置某个日期对象的时区是从包含时区的日期字符串构造它。 (我无法让它在旧版 android 浏览器中运行。)

    请注意,getTime() 返回毫秒,而不是普通秒。

对于 UTC/Unix 时间戳,以下内容就足够了:

Math.floor((new Date()).getTime() / 1000)

它会将当前时区偏移量计入结果中。对于字符串表示,David Ellis' 答案有效。

澄清一下:

new Date(Y, M, D, h, m, s)

该输入被视为当地时间。如果传入UTC时间,结果会有所不同。观察(我现在在 GMT +02:00,现在是 07:50):

> var d1 = new Date();
> d1.toUTCString();
"Sun, 18 Mar 2012 05:50:34 GMT" // two hours less than my local time
> Math.floor(d1.getTime()/ 1000)
1332049834 

> var d2 = new Date( d1.getUTCFullYear(), d1.getUTCMonth(), d1.getUTCDate(), d1.getUTCHours(), d1.getUTCMinutes(), d1.getUTCSeconds() );
> d2.toUTCString();
"Sun, 18 Mar 2012 03:50:34 GMT" // four hours less than my local time, and two hours less than the original time - because my GMT+2 input was interpreted as GMT+0!
> Math.floor(d2.getTime()/ 1000)
1332042634

另请注意,getUTCDate() 不能替代 getUTCDay()。这是因为getUTCDate() 返回the day of the month;而getUTCDay() 返回the day of the week

【讨论】:

1) 我没有构造日期...我添加了一个适用于 this 的原型函数。 2) 好点,我应该做 Math.floor / 1000 - 但我仍然需要该函数才能获得 existing 日期对象的 UTC 时间戳...对吗? @Merc: 1) 您正在调用new Date(),它会根据您的 UTC 输入创建一个新日期,但会将其视为本地日期/时间。 2) 是的,在这种情况下你应该使用Math.floor(this.getTime() / 1000) 在此处回答,因为我需要更新代码...这是为了在 现有 日期中使用 UTC 中的 Unix 时间戳:function () return Math.floor(新日期(this.getUTCFullYear(),this.getUTCMonth(),this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()).getTime()/ 1000);这意味着我可以这样做: var n = new Date(2008,10,10) ... ... n.getUTCTime(); (这将与 n.getUTCTime() 不同) 感谢兄弟它的工作文件 Math.floor((new Date()).getTime() / 1000)【参考方案2】:

以传统格式获取 UTC 时间的最简单方法如下:

> new Date().toISOString()
"2016-06-03T23:15:33.008Z"

如果您需要 EPOC 时间戳,请将您的日期传递给 Date.parse 方法

> Date.parse(new Date)
1641241000000
> Date.parse('2022-01-03T20:18:05.833Z')
1641241085833

或者您可以使用 + 将类型转换为 Date 到 Int

> +new Date 
1641921156671

EPOC 时间戳,以秒为单位。

> parseInt(Date.parse('2022-01-03T20:18:05.833Z') / 1000)
1641241085

【讨论】:

这是正确答案。许多其他答案给出了“通用时间字符串”,但没有给出当前的“通用协调时间”。我不明白为什么这里的一切都这么复杂。 谢谢@gburton。感谢您看到通往真理的简单方法。 :) 我将它与 ".split('T')[0]" 一起用于基于 YYYY-MM-DD 日期的轻松比较。 这提供了一个 UTC 时间字符串,但 OP 要求提供一个 UTC timestamp (epoch) 这是误导,它不提供 UTC 时间戳【参考方案3】:

您也可以使用 getTimezoneOffset 和 getTime,

x = new Date()
var UTCseconds = (x.getTime() + x.getTimezoneOffset()*60*1000)/1000;

console.log("UTCseconds", UTCseconds)

【讨论】:

谢谢,这在互联网上找不到! 我测试了以下代码:var tt = new Date('Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time)'); (tt.getTime() - tt.getTimezoneOffset()*60*1000)/1000。看来tt.getTime() - tt.getTimezoneOffset()GMT+0800 是正确的。 这样更好var UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60) 看起来这不像写的那样工作..看起来你必须将时间字符串传递给包含时区的new Date()..这有点违背了尝试这样做的目的在js中.. 这完全是错误的,分配给 UTCseconds 不是 UTC 秒的值.. Date 的时间值 is UTC,用任何方法改变它意味着它代表一个不同的时刻。【参考方案4】:

我实际上认为 js 中的 Date 值比 C# DateTime 对象要好得多。 C# DateTime 对象具有 Kind 属性,但没有严格的底层时区,如果您在两个非 UTC 和非本地时间之间进行转换,则很难跟踪时区转换。在 js 中,所有 Date 值都有一个基础 UTC 值,无论您进行何种偏移或时区转换,该值都会被传递并知道。我对 Date 对象最大的抱怨是浏览器实现者选择包含的未定义行为的数量,这可能会使那些在 js 中攻击日期的人感到困惑,而不是阅读规范。使用 iso8601.js 之类的东西通过定义 Date 对象的单个实现来解决这种不同的行为。

默认情况下,规范说您可以使用扩展的 ISO 8601 日期格式创建日期,例如

var someDate = new Date('2010-12-12T12:00Z');

因此,您可以通过这种方式推断准确的 UTC 时间。

当您想将 Date 值传递回您将调用的服务器时

someDate.toISOString();

或者如果您更愿意使用毫秒时间戳(UTC 时间 1970 年 1 月 1 日起的毫秒数)

someDate.getTime();

ISO 8601 是一个标准。如果包含日期偏移量,您不会对日期字符串的含义感到困惑。作为开发人员,这意味着您不必自己处理本地时间转换。本地时间值的存在纯粹是为了用户的利益,日期值默认显示为本地时间。所有本地时间操作都允许您显示对用户有意义的内容并转换来自用户输入的字符串。尽快转换为 UTC 是一种很好的做法,而 js Date 对象使这变得相当简单。

不利的一面是,为客户端(我知道)强制时区或区域设置的空间不大,这对于特定于网站的设置来说可能很烦人,但我想这背后的原因是这是一个不应触及的用户配置。

因此,简而言之,没有很多本地支持时区操作的原因是您根本不想这样做。

【讨论】:

【参考方案5】:

您通常不需要在客户端做太多的“时区操作”。作为一项规则,我尝试以ticks 或“自 1970 年 1 月 1 日午夜以来的毫秒数的形式存储和使用 UTC 日期。这确实简化了存储、排序、偏移量的计算,最重要的是,让您摆脱了“夏令时”调整的烦恼。这是我使用的一小段 JavaScript 代码。

获取当前 UTC 时间:

function getCurrentTimeUTC()

    //RETURN:
    //      = number of milliseconds between current UTC time and midnight of January 1, 1970
    var tmLoc = new Date();
    //The offset is in minutes -- convert it to ms
    return tmLoc.getTime() + tmLoc.getTimezoneOffset() * 60000;

那么您通常需要为最终用户的本地时区和格式设置日期/时间格式。以下处理了客户端计算机上日期和时间格式的所有复杂性:

function formatDateTimeFromTicks(nTicks)

    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date/time
    return new Date(nTicks).toLocaleString();


function formatDateFromTicks(nTicks)

    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date
    return new Date(nTicks).toLocaleDateString();


function formatTimeFromTicks(nTicks)

    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted time
    return new Date(nTicks).toLocaleTimeString();

所以下面的例子:

var ticks = getCurrentTimeUTC();  //Or get it from the server

var __s = "ticks=" + ticks + 
    ", DateTime=" + formatDateTimeFromTicks(ticks) +
    ", Date=" + formatDateFromTicks(ticks) +
    ", Time=" + formatTimeFromTicks(ticks);

document.write("<span>" + __s + "</span>");

返回以下内容(对于我的美国英语语言环境):

ticks=1409103400661,DateTime=8/26/2014 6:36:40 PM,Date=8/26/2014, 时间=下午 6:36:40

【讨论】:

通过在getCurrentTimeUTC 函数中添加getTimezoneOffset 值,您实际上是在返回一个不同的时间点。 getTime 的结果已经采用 UTC。 @MattJohnson:这是不正确的。 tmLoc.getTime() 的结果是相对于本地时间的偏移量。这很容易检查您是否可以访问任何运行 JavaScript 的东西。 抱歉,这不是真的。见the MDN reference。您还可以在 ECMAScript 规范中看到这一点。 §15.9.3.3 describes getTime,它将您指向§15.9.5 中定义的“时间值”,即PrimitiveValue,在§15.9.3.3 中明确设置为UTC。 好吧,既然你是通过new Date()获得tmLoc,那也是一样的。时区会影响tmLoc.toString() 和类似项目的字符串输出,但不会影响tmLoc.getTime() 从UTC 1970-01-01 午夜开始的毫秒数。 @StefansArya: //The offset is in minutes -- convert it to ms【参考方案6】:

如果你想要一个单行UTC Unix Timestamp可以在JavaScript中创建为:

var currentUnixTimestap = ~~(+new Date() / 1000);

这将考虑系统的时区。它基本上是自纪元以来经过的秒数。

工作原理:

创建日期对象:new Date()。 通过在对象创建之前添加unary + 将其转换为timestamp integer 来转换为时间戳。 :+new Date(). 将毫秒转换为秒:+new Date() / 1000 使用 双波浪线 将值四舍五入为整数。 :~~(+new Date())

【讨论】:

它是tilde,而不是tilda(原文如此)。遗憾的是它不会让我删除一个错字,我必须进行至少 6 个字符的编辑。平滑,Stackexchange,平滑 不要使用这个。使用当前的 ecma 规范,按位运算(如波浪号 - 按位不)处理 32 位的有符号整数值。这意味着在 2038 年 1 月 19 日之后,当时间戳值将超过 32 位有符号整数的最大值时,此波浪号魔法将不起作用。 jsfiddle.net/phb20ymb @Sharky 我用这个是因为现在还不是 2038 年!【参考方案7】:

我认为这是一个更好的解决方案

// UTC milliseconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0

【讨论】:

另一个错误答案,getTime 返回一个 UTC 偏移量,添加本地时区偏移量完全搞砸了。 ECMAScript 偏移量是 +ve 表示西,-ve 表示东,因此应该从 UTC 中减去它们以获得本地。但由于时间值是​​ UTC 开始的,添加它实质上会将其从 UTC 偏移到与本地偏移相反的方向。【参考方案8】:

由于new Date().toUTCString()返回一个类似"Wed, 11 Oct 2017 09:24:41 GMT"的字符串,您可以对最后3个字符进行切片并将切片后的字符串传递给new Date()

new Date()
// Wed Oct 11 2017 11:34:33 GMT+0200 (CEST)

new Date(new Date().toUTCString().slice(0, -3))
// Wed Oct 11 2017 09:34:33 GMT+0200 (CEST)

【讨论】:

【参考方案9】:

我使用以下:

Date.prototype.getUTCTime = function() 
  return this.getTime()-(this.getTimezoneOffset()*60000); 
;

一旦定义了这个方法,你就可以这样做:

var utcTime = new Date().getUTCTime();

【讨论】:

最干净的解决方案。谢了! 但这不是发送日期的干净解决方案,因为时间戳始终是 UTC。发送日期时对我来说最好的解决方案是使用像“dd/MM/yyyy HH:mm:ss”这样的字符串表示,然后在服务器端使用服务器的默认时区解析它以获得UTC时间戳或其他任何东西。看到这个answer 解析一个字符串——你说那是干净的吗?嗯 当然,有一些方法可以根据 ISO 规范生成字符串格式的日期。方法是 toISOString()。您可以使用类似的方式在 Java 中干净地解析它:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00"); 另一个错误答案,this.getTime() 返回一个 UTC 偏移量,减去本地时区偏移量使其成为本地时区,而不是 UTC 所以 getUTCTime 返回一个本地偏移量,而不是 UTC。跨度> 【参考方案10】:

我想澄清一下, new Date().getTime() 实际上确实返回了一个 UTC 值,因此它是一种非常有用的方法,可以以与本地时间无关的方式存储和管理日期。

换句话说,不要为所有的 UTC javascript 函数而烦恼。相反,只需使用 Date.getTime()。

关于解释的更多信息在这里: If javascript "(new Date()).getTime()" is run from 2 different Timezones.

【讨论】:

【参考方案11】:

我对这个问题变得如此复杂感到惊讶。

这些都是相同的,它们的整数值都是=== EPOCH时间:D

console.log((new Date()).getTime() / 1000, new Date().valueOf() / 1000, (new Date() - new Date().getTimezoneOffset() * 60 * 1000) / 1000);

不信,结账: http://www.epochconverter.com/

【讨论】:

【参考方案12】:

我认为这是你所期望的......

var currTimestamp = Date.now(), //1482905176396
    utcDateString = (new Date(currTimestamp)).toUTCString(); //"Wed, 28 Dec 2016 06:06:50 GMT"

现在,

new Date(utcDateString).getTime(); //This will give you UTC Timestamp in JavaScript

【讨论】:

你有什么理由不做new Date().toUTCString()【参考方案13】:

编辑:下面的代码不起作用。我一直假设 new Date().getTime() 返回当前时区自 1970 年 1 月 1 日以来的秒数。情况并非如此:getTime() 以 UTC 格式返回秒数。因此,下面的代码确实进行了过度调整。谢谢大家!]

首先,感谢您的精彩见解。 我猜我的问题的标题有误……应该是“获取现有日期的 UTC Unix 时间戳”。

所以,如果我有一个日期对象:

var d = new Date(2009,01,31)

我正在寻找一个可以告诉我“UTC Unix 时间戳”的函数。

这个函数似乎是真正的把戏:

Date.prototype.getUTCUnixTime =  function ()
  return Math.floor( new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime() / 1000); 

请注意,它适用于“this”这意味着我可以这样做:

var n = new Date(2008,10,10)
...
...

n.getUTCUnixTime();

并获取自 1970 年 1 月 1 日以来 Unix 时间的秒数。 对吧?

对我来说,Javascript 以 UTC 时间存储所有内容有点疯狂,但为了获得该数字,我必须创建一个新的 Date 对象,传递各个 UTC getter,然后最后为此调用 getTime()。 ..

佣兵。

【讨论】:

你看到@DCoder 对他的回答的更新了吗?您的方法 getUTCUnixTime 得到了错误的时间,而 JavaScript 确实 提供了一种直接的方法来从 Date 对象获取 unix 时间戳 - 使用 getTime 方法。查看所有其他答案。 呃,你是对的,刚刚看到他们。 (头撞墙)【参考方案14】:

一旦你这样做了

new Date(dateString).getTime() / 1000

已经是UTC时间戳了

   const getUnixTimeUtc = (dateString = new Date()) => Math.round(new Date(dateString).getTime() / 1000)

我在https://www.unixtimestamp.com/index.php上测试过

【讨论】:

【参考方案15】:

使用day.js

在浏览器中:

dayjs.extend(dayjs_plugin_utc)
console.log(dayjs.utc().unix())
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/plugin/utc.js"></script>

在 node.js 中:

import dayjs from 'dayjs'
dayjs.extend(require('dayjs/plugin/utc'))
console.log(dayjs.utc().unix())

你会得到一个没有毫秒的 UTC unix 时间戳。

【讨论】:

【参考方案16】:

这将返回 UTC 时间戳:

var utc = new Date(new Date().toUTCString()).getTime();

【讨论】:

这不会返回 UTC 时间:new Date(new Date().toUTCString()) 给出 Wed Oct 04 2017 07:20:14 GMT+0200 (GMT+02:00)

以上是关于如何在 JavaScript 中获取 UTC 时间戳?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中获取 UTC 时间?

如何在 C# 中拒绝来自客户端的非 UTC/GMT 日期?

如何在javascript中比较UTC时间

如何从日历中获取 UTC 时间戳?

如何在javascript中获取指定时区的一天的开始时间和结束时间?

如何获取 UTC 中特定时间和当前时间之间的差异