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

Mer*_*erc 146 javascript timezone utc

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

当我发现你无法在JavaScript中进行时区操作时,我感到非常惊讶.

我稍微扩展了Date对象.这个功能有意义吗?基本上,每次我向服务器发送任何内容时,它都将是使用此功能格式化的时间戳...

你能看到这里有什么重大问题吗?或者从不同角度解决问题?

Date.prototype.getUTCTime = function(){ 
  return new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime(); 
}
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎有点令人费解.而且我对表现也不太确定.

DCo*_*der 141

  1. 以这种方式构造的日期使用本地时区,使构造日期不正确.设置某个日期对象的时区是从包含时区的日期字符串构造它.(我在使用较旧的Android浏览器时遇到了问题.)

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

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

Math.floor((new Date()).getTime() / 1000)
Run Code Online (Sandbox Code Playgroud)

它会将当前时区偏移量计入结果.对于字符串表示,David Ellis的回答是有效的.

澄清:

new Date(Y, M, D, h, m, s)
Run Code Online (Sandbox Code Playgroud)

该输入被视为当地时间.如果传入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
Run Code Online (Sandbox Code Playgroud)

另请注意,getUTCDate()不能替代getUTCDay().这是因为getUTCDate()返回该月的某一天 ; 然而,getUTCDay()返回星期几.


Shi*_*dim 47

你也可以利用getTimezoneOffset和getTime来做到这一点,

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

console.log("UTCseconds", UTCseconds)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这在互联网上无处可寻! (4认同)
  • 这更好`var UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)` (2认同)
  • 这是完全错误的,分配给 *UTCseconds* 的值不是** UTC 秒。日期的时间值**是** UTC,通过任何方法更改它都意味着它代表不同的时间时刻。 (2认同)

Tah*_*koz 19

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

new Date().toISOString()
"2016-06-03T23:15:33.008Z"
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案。许多其他答案给出了“通用时间字符串”,但没有给出当前的“通用协调时间”。我不明白为什么这里的一切都如此复杂。 (10认同)
  • 这是误导性的,它不提供 UTC 时间戳 (4认同)
  • 这提供了 UTC 时间字符串,但 OP 要求 UTC **时间戳**(纪元) (3认同)

ahm*_*md0 13

您通常不需要在客户端执行大量"时区操作".作为一项规则,我尝试以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;
}
Run Code Online (Sandbox Code Playgroud)

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

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();
}
Run Code Online (Sandbox Code Playgroud)

所以下面的例子:

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>");
Run Code Online (Sandbox Code Playgroud)

返回以下内容(对于我的美国英语区域设置):

ticks = 1409103400661,DateTime = 8/26/2014 6:36:40 PM,Date = 8/26/2014,Time = 6:36:40 PM

  • 对不起,但事实并非如此。请参阅 [MDN 参考](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime)。您也可以在 ECMAScript 规范中看到这一点。[§15.9.3.3 描述了`getTime`](http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.3.3),它指向你在[§ 15.9.5](http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.5),这是一个 `PrimitiveValue`,如 [§15.9.3.3](http: //www.ecma-international.org/ecma-262/5.1/#sec-15.9.3.3) 明确为 UTC。 (2认同)
  • 好吧,既然你通过 `new Date()` 获得了 `tmLoc`,那么它也是一样的。时区会影响`tmLoc.toString()` 和类似项目的字符串输出,但不会影响`tmLoc.getTime()` 自UTC 时间1970-01-01 午夜以来的毫秒数。 (2认同)

Mat*_*sch 12

我实际上认为js中的Date值远比C#DateTime对象好.C#DateTime对象具有Kind属性,但没有严格的基础时区,如果要在两个非UTC和非本地时间之间进行转换,则难以跟踪时区转换.在js中,所有日期值都具有基础UTC值,无论您执行的是哪个或哪些时区转换,都会传递并传输该值.我对Date对象的最大抱怨是浏览器实现者选择包含的未定义行为的数量,这可能会使用js攻击日期的人与阅读规范相混淆.使用像iso8601.js这样的东西通过定义Date对象的单个实现来解决这种变化的行为.

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

var someDate = new Date('2010-12-12T12:00Z');
Run Code Online (Sandbox Code Playgroud)

因此,您可以通过这种方式推断出确切的UTC时间.

如果要将Date值传递回要调用的服务器

someDate.toISOString();
Run Code Online (Sandbox Code Playgroud)

或者你是否愿意使用毫秒时间戳(从1970年1月1日UTC开始的毫秒数)

someDate.getTime();
Run Code Online (Sandbox Code Playgroud)

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

在缺点方面,没有太多的空间强制客户端(我知道)的时区或区域设置,这可能会令网站特定的设置烦恼,但我猜这背后的原因是它是一个用户不应该触及的配置.

因此,简而言之,没有很多原生支持时区操作的原因是因为你根本就不想这样做.


Kus*_*khi 8

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

var currentUnixTimestap = ~~(+new Date() / 1000);
Run Code Online (Sandbox Code Playgroud)

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

这个怎么运作:

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

  • 它是`tilde`,而不是`tilda`(原文如此)。遗憾的是它不会让我删除错字,我必须至少编辑 6 个字符。平滑,堆栈交换,平滑 (9认同)
  • **不要使用这个**。使用当前的 ecma 规范,按位运算(如波浪号 - 按位非)处理 32 位的有符号整数值。这意味着在 2038 年 1 月 19 日之后,当时间戳值将超过 32 位有符号整数的最大值时,此波浪符魔术**将不起作用**。https://jsfiddle.net/phb20ymb/ (7认同)
  • @Sharky 我用这个是因为现在还不是 2038 年! (2认同)

koa*_*lex 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
Run Code Online (Sandbox Code Playgroud)

  • 另一个错误的答案是,*getTime* 返回 UTC 偏移量,添加本地时区偏移量完全搞乱了它。ECMAScript 偏移量为 +ve(西)和 -ve(东),因此应从 UTC 中减去它们以获得本地偏移量。但由于时间值一开始就是 UTC,因此添加它实际上会将其从 UTC 移向与本地偏移量相反的方向。 (2认同)

Mau*_*ipf 7

由于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)
Run Code Online (Sandbox Code Playgroud)


jlb*_*ofh 5

我使用以下内容:

Date.prototype.getUTCTime = function(){ 
  return this.getTime()-(this.getTimezoneOffset()*60000); 
};
Run Code Online (Sandbox Code Playgroud)

定义此方法后,您可以执行以下操作:

var utcTime = new Date().getUTCTime();
Run Code Online (Sandbox Code Playgroud)

  • 解析一个字符串——你称之为干净?嗯 (2认同)