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


157

在编写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对象)。因为我喜欢这个问题本身而被投票。
trysis

Date.parse(new Date()。toUTCString())
萨吉

25
这是我今天的提要中提出的一个老问题,并且充满了错误信息。时间戳始终采用UTC。 new Date().toString()将显示您当前时区时间表示,new Date().toUTCString()将向您展示UTC时间再版,却new Date().getTime()始终UTC,因为这是Unix的时间定义为:“Unix时间(也被称为POSIX时间或信号出现时间)是一种描述瞬间系统时间,即从1970年1月1日星期四00:00:00世界标准时间(UTC)起经过的秒数,不包括leap秒。”
阿玛丹

Answers:


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

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

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

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

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

澄清:

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

该输入被视为本地时间。如果传递了UTC时间,结果将有所不同。观察(我现在是格林尼治标准时间+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()返回月份中的某天;相反,getUTCDay()返回星期几


1
1)我没有构建一个日期...我补充说,在一个工作原型函数。2)好点,我应该执行Math.floor / 1000 -但是我仍然需要该函数才能拥有现有日期对象的UTC时间戳……对吗?
Merc

@Merc:1)您正在呼叫new Date(),它将根据您的UTC输入创建一个新日期,但是将其视为本地日期/时间。2)是的,Math.floor(this.getTime() / 1000)在这种情况下应该使用。
DCoder 2012年

在这里回答,因为我需要更新代码...这是将UTC中的Unix时间戳记为现有日期:function(){return Math.floor(new Date(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())
Merc的

1
谢谢兄弟它的工作文件Math.floor((new Date())。getTime()/ 1000)
Manoj Patel

51

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

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

console.log("UTCseconds", UTCseconds)


4
谢谢,在互联网上找不到这个地方!
Theofanis Pantelides

我测试了以下代码: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
zangw

1
这样会更好var UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)
StefansArya

看来这无法按书面要求进行。.看来您必须在new Date()包含时区的时间字符串中进行传递。.这有点
违反

这是完全错误的,分配给UTCseconds 的值不是 UTC秒。.Date的时间值 UTC,通过任何方法更改它都表示它表示一个不同的时刻。
RobG

34

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

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

3
这是正确的答案。许多其他答案给出“通用时间字符串”,但没有给出当前的“通用协调时间”。我不明白为什么这里的一切都那么复杂。
gburton

谢谢@gburton。赞赏您看到了实现真理的简单方法。:)
Tahsin Turkoz

1
我将其与“ .split('T')[0]”一起使用,以方便进行基于日期的YYYY-MM-DD比较。
肖恩O

很高兴有@SeanO
Tahsin Turkoz

这提供了UTC时间字符串,但是OP要求提供UTC 时间戳(时代)
Jordi Nebot

13

我实际上认为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时间。

当您要将日期值传递回服务器时,您将调用

someDate.toISOString();

或者,如果您希望使用毫秒级的时间戳记(自1970年1月1日世界标准时间以来的毫秒数)

someDate.getTime();

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

不利的一面是,我没有意识到强制客户端的时区或区域设置的范围很大,这对于特定于网站的设置可能很烦人,但是我想这背后的原因是它是用户不应该涉及的配置。

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


12

通常,您不需要在客户端执行太多的“时区操作”。通常,我尝试以UTC日期的形式存储或使用UTC日期,ticks或以“ 自1970年1月1日午夜以来的毫秒数 ” 的形式。这确实简化了偏移的存储,排序,计算,并且最重要的是,您摆脱了“夏令时”调整的麻烦。这是我使用的一些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,Time = 6:36:40 PM


1
通过getTimezoneOffsetgetCurrentTimeUTC函数中添加值,实际上您在返回一个不同的时间点。结果getTime已经在UTC。
马特·约翰逊

1
@MattJohnson:那是不正确的。的结果tmLoc.getTime()是与当地时间的偏差。这很容易检查您是否有权访问运行JavaScript的任何内容。
ahmd0

2
抱歉,那不是事实。请参阅MDN参考。您也可以在ECMAScript规范中看到这一点。§15.9.3.3描述getTime,这点你在“时间值”中定义§15.9.5,这是一个PrimitiveValue,作为集§15.9.3.3明确为UTC。
马特·约翰逊

2
好吧,既然您tmLoc通过获取了new Date(),那么它也是一样。时区将影响tmLoc.toString()和类似项目的字符串输出,但不会影响tmLoc.getTime() 。自UTC 1970-01-01午夜以来,这始终只是毫秒数。
马特·约翰逊·品脱

1
@StefansArya://The offset is in minutes -- convert it to ms
ahmd0

5

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

// 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沿相反的方向移到本地偏移。
RobG

4

如果您需要一个衬板,则可以使用JavaScript创建UTC Unix时间戳,如下所示:

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

这将考虑系统的时区。基本上是从纪元开始经过的时间(以秒为单位)。

这个怎么运作:

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

7
tilde,不是tilda(原文如此)。可悲的是,它不允许我删除错字,我必须至少编辑6个字符。平滑,Stackexchange,平滑
Fred

3
不要使用这个。使用当前的ecma规范,按位运算(如波浪号-不按位运算)可处理32位带符号整数值。这意味着在2038年1月19日之后时间戳值将超过32位有符号整数的最大值时,该波浪符号魔术将不起作用jsfiddle.net/phb20ymb
沙基


3

我使用以下内容:

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

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

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

最干净的解决方案。谢谢!
avalanche1 2016年

但这不是发送日期的干净解决方案,因为时间戳始终是UTC。对我来说,发送日期时最好的解决方案是使用字符串表示形式,例如“ dd / MM / yyyy HH:mm:ss”,然后在服务器端使用服务器的默认TimeZone对其进行解析,以获取UTC时间戳或其他任何时间戳。看到这个答案
jlbofh

2
解析一个字符串-您正在调用它吗?meh
avalanche1

确保有一些方法可以根据ISO规范以字符串格式生成日期。该方法是toISOString()。您可以使用以下代码在Java中进行清晰的解析:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");
jlbofh

另一个错误的答案是this.getTime()返回UTC偏移量,减去本地时区偏移量使其成为本地而不是UTC,因此getUTCTime返回本地偏移量,而不是UTC。
RobG

2

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

这些都是相同的,并且它们的整数值都是=== EPOCH time:D

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

不相信我,结帐:http : //www.epochconverter.com/


2

由于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)

1

编辑:下面的代码不起作用。我一直以为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时间有点疯狂,但是为了获得该数字,我必须创建一个传递各个UTC getter的新Date对象,然后最终为此调用getTime()。

Merc。


1
您是否看到@DCoder更新了他的答案?您的方法使用getUTCUnixTime了错误的时间,JavaScript 确实提供了一种直接的方法来从Date对象获取UNIX时间戳-使用该getTime方法。查看所有其他答案。
阿努拉格2012年

1
gh,您说对了,刚看到他们。(撞墙)
Merc

1

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

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


0

使用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时间戳。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.