将UTC时间戳转换为本地日期

402

我已经在这方面奋斗了一会儿。我试图将时间戳转换为日期对象。时间戳以UTC格式发送给我。当您将new Date()传递一个时间戳时,它假定它是本地时间戳。我尝试创建一个UTC对象,然后使用setTime()将其调整为正确的时间戳,但唯一看起来有用的方法是toUTCString(),而字符串对我没有帮助。如果我将该字符串传递给一个新的日期对象,它应该注意到它是UTC格式,但事实并非如此。

new Date( new Date().toUTCString() ).toLocaleString()

我的下一步尝试是获取本地当前时代和UTC当前时代之间的差异,但我也无法做到这一点。

new Date( new Date().toUTCString() ).getTime() - new Date().getTime()

它只给我非常小的差异,小于1000,也就是毫秒级别。

有什么建议吗?


17
时代时间指的是自1970年*在协调世界时(UTC)*以来经过的毫秒数。没有所谓的本地时代!不确定我是否理解了您的问题。 - Chetan S
可能是计算机的时区不正确,导致UTC值不同? - kijin
2
如果您想在使用toLocaleString()时“查看”UTC时间,您必须将时钟设置为UTC时间。午夜UTC是EST的晚上7点。如果您使用new Date().toString()而不是toLocaleString,您会得到类似于“Fri Jan 07 2011 07:00:00 GMT-0500”的内容,其中包括偏移量。 - kennebec
Epoch单位是秒,而不是毫秒。 - Teson
18个回答

656

我认为我有一个更简单的解决方案——将初始日期设置为纪元并添加UTC单位。假设你有一个以秒为单位存储的UTC纪元变量,比如 1234567890。要将其转换为本地时区中的正确日期:

var utcSeconds = 1234567890;
var d = new Date(0); // The 0 there is the key, which sets the date to the epoch
d.setUTCSeconds(utcSeconds);

d已经是一个日期(以我的时区为准),设置为Fri Feb 13 2009 18:31:30 GMT-0500 (EST)


273
FWIW,Date对象可以使用毫秒进行初始化。因此,var d = new Date(utcSeconds * 1000)应该得到相同的结果。 - kurttheviking
83
var d = new Date(1234567890000) 返回相同的结果。 - Matjaz Lipus
14
也许其他人可以从两点中得到一些明确的信息:日期对象不会被设置为带有时区的时间戳。可以将它看作只是一个数字。这个数字是从1970年1月1日UTC开始到现在的毫秒数(现在也是在UTC时区)。因此,每当你创建一个日期对象时,它实际上是在幕后以UTC格式存在的。要显示该日期,可以将其显示为语言环境设置(使用toLocaleString()),或者以UTC格式显示(使用toUTCString())。你不需要自己进行任何转换。使用UTC毫秒构造即可,非常好用。如果使用字符串构造,则必须是本地时区的字符串。 - da Bich
4
1234567890000被视为与1234567890相同,也就是所谓的“Y39K问题”... - muttonUp
2
@muttonUp,用1000次乘法它可以工作。但是,“Y39K问题”谷歌没有给出任何有效的结果。任何URL都将是有帮助的。 - Satish Patro
显示剩余3条评论

358

这很简单,new Date()只需要毫秒数即可,例如:

new Date(1394104654000)
> Thu Mar 06 2014 06:17:34 GMT-0500 (EST)

9
好的!这个答案应该真正被认为是被接受的答案。 - Nizar B.
1
这个对我没用,只有在有时间戳的情况下才有效,但是使用UTC纪元时必须手动设置UTC秒数,被接受的答案是正确的答案。 - sameerali
33
这是一个恰当的答案。新日期可能只需要毫秒级别的时间,因此只需将其乘以1000:const d = new Date(epoch * 1000) - vinyll
2
@sameerali 或许你的系统出了一些问题,或者你感到困惑了。这个答案是正确的。Unix纪元的定义是:自UTC午夜1月1日以来经过的秒数。只需乘以1000即可得到经过的毫秒数。 - nalply
这个有文档记录吗? - pooya13

35

Unix时间戳以秒为单位从1970年1月1日开始计时。date.getTime()方法返回的是从1970年1月1日开始计时的毫秒数,因此,如果你有Unix时间戳,需要将其乘以1000以获取JavaScript时间戳。

   function epochToJsDate(ts){
        // ts = epoch timestamp
        // returns date obj
        return new Date(ts*1000);
   }

   function jsDateToEpoch(d){
        // d = javascript date obj
        // returns epoch timestamp
        return (d.getTime()-d.getMilliseconds())/1000;
   }

我在想到底出了什么问题。很高兴知道在日期解析方面,epochTime !== javascriptTime。谢谢! - GrayedFox

35

只是为了记录,我是使用Moment.js库来完成这个操作的。我之前已经在使用它来进行格式化了。

moment.utc(1234567890000).local()
>Fri Feb 13 2009 19:01:30 GMT-0430 (VET)

5
使用一个1.3MB的库来仅仅将一个纪元转换为日期是不��智的,即使Moment很好用。难怪有那么多臃肿的Node应用程序存在。 - not2qubit
8
我的意思是,他确实指定了他正在使用它进行格式化。在这里这样说是不公平的。 - Xevion

17
 function ToLocalDate (inDate) {
    var date = new Date();
    date.setTime(inDate.valueOf() - 60000 * inDate.getTimezoneOffset());
    return date;
}

1
你让我开心了。谢谢。我刚刚把工作中的减号替换成加号。 - Ludovic Kuty

13

时间戳(即Unix时间戳)几乎总是指自1970年1月1日00:00:00(UTC时间)以来已经过去的秒数,而不是一些答案中所暗示的毫秒数

https://zh.wikipedia.org/wiki/Unix%E6%97%B6%E9%97%B4

因此,如果您已经获得了一个Unix时间戳值,它很可能是以秒为单位的,并且看起来像1547035195。如果您想在JavaScript中使其可读,请将该值转换为毫秒,并将该值传递给Date(value)构造函数,例如:

const unixEpochTimeMS = 1547035195 * 1000;
const d = new Date(unixEpochTimeMS);
// Careful, the string output here can vary by implementation...
const strDate = d.toLocaleString();

接受的答案中不需要执行d.setUTCMilliseconds(0)步骤,因为JavaScript Date(value)构造函数需要以毫秒为单位的UTC值(而不是本地时间)。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Syntax

此外,请注意避免使用接受日期时间字符串表示的Date(...)构造函数,这不被推荐(请参见上面的链接)。


9

6

最简单的方法

如果你有以毫秒为单位表示的 Unix 时间戳,例如我的情况是1601209912824

  1. 将其转换为 Date 对象,如下所示
const dateObject = new Date(milliseconds)
const humanDateFormat = dateObject.toString() 

输出 -

Sun Sep 27 2020 18:01:52 GMT+0530 (India Standard Time)

如果您需要UTC时间-
const dateObject = new Date(milliseconds)
const humanDateFormat = dateObject.toUTCString() 
  1. 现在您可以按自己的喜好进行格式化。

5

将当前的以毫秒为单位的纪元时间转换为24小时制时间。您可能需要指定选项来禁用12小时格式,详情请参考此处

$ node.exe -e "var date = new Date(Date.now()); console.log(date.toLocaleString('en-GB', { hour12:false } ));"

2/7/2018, 19:35:24

或者作为JS:

var date = new Date(Date.now()); 
console.log(date.toLocaleString('en-GB', { hour12:false } ));
// 2/7/2018, 19:35:24

console.log(date.toLocaleString('en-GB', { hour:'numeric', minute:'numeric', second:'numeric', hour12:false } ));
// 19:35:24

注意:此处使用 en-GB,只是为了随机选择一个使用 24 小时制的地区,它并不代表你的时区!


1
这是从日期方法获取任何类型转换的最佳方式。谢谢! - SeaWarrior404
我唯一不喜欢上面的是,它以 d/m/yyyym/d/yyyy 这种模糊的格式返回日期。正确(最合理)的显示方式应该是:yyyy-mm-dd。有人愿意接手吗? - not2qubit

5
除了@djechlin的上述回答外,还有以下补充:
d = '1394104654000';
new Date(parseInt(d));

将 EPOCH 时间转换为可读日期。只是不要忘记,EPOCH 时间的类型必须是整数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接