关于时区:如何在JavaScript中获取UTC时间戳?

How do I get a UTC Timestamp in JavaScript?

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

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

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

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

1
2
3
4
5
6
7
8
9
10
Date.prototype.getUTCTime = function(){
  return new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(),
    this.getUTCSeconds()
  ).getTime();
}

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


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

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

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

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

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

    澄清:

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    > 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()返回星期几。


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

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

    console.log("UTCseconds", UTCseconds)


    是的,你不需要做那么多;假设我理解正确,你只需要toUTCString方法。

    1
    2
    3
    var UTCstring = (new Date()).toUTCString();

    console.log('UTCstring', UTCstring);

    但是,请记住,您获得的日期值取决于客户端计算机的时钟,而不是您的服务器。如果您需要这些日期的精确值(例如,当相对于另一个用户的操作执行此操作或该操作时正确排序),您无论如何都不能依赖客户端日期库,并且您需要计算根据客户与您联系的时间来确定服务器端的日期。

    基本上也要记住,客户端基本上可以修改所有客户端代码并返回恶意值,只能保证服务器端的代码 - 将客户端视为可能的攻击者。


    您通常不需要在客户端执行大量"时区操作"。作为一项规则,我尝试以ticks或"自1970年1月1日午夜以来的毫秒数"的形式存储和使用UTC日期。这真的简化了存储,排序,偏移的计算,最重要的是,让您不必担心"夏令时"调整。这是我使用的一些JavaScript代码。

    要获取当前的UTC时间:

    1
    2
    3
    4
    5
    6
    7
    8
    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;
    }

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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();
    }

    所以下面的例子:

    1
    2
    3
    4
    5
    6
    7
    8
    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


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

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

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

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

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

    1
    someDate.toISOString();

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

    1
    someDate.getTime();

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

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

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


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

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


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

    1
    2
    3
    4
    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

    我使用以下内容:

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

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

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


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

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

    这将考虑系统的时区。它基本上是自纪元以来在Seconds中流逝的时间。

    这个怎么运作:

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


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

    1
    2
    3
    4
    5
    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)

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

    换句话说,不要打扰所有UTC javascript函数。相反,只需使用Date.getTime()。

    有关解释的更多信息,请访问:
    如果javascript"(new Date())。getTime()"是从2个不同的时区运行的。


    我对这个问题变得多么复杂感到惊讶。

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

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

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


    编辑:下面的代码不起作用。我总是假设新的Date()。getTime()返回自1970年1月1日以来在当前时区的秒数。情况并非如此:getTime()以UTC为单位返回秒数。因此,下面的代码会严重过度调整。谢谢大家!]

    首先,感谢您的精彩见解。
    我想我的问题有错误的标题......应该是"获取现有日期的UTC Unix时间戳"。

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

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

    我正在使用一个能告诉我"UTC Unix时间戳"的函数。

    这个功能似乎是真正的诀窍:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Date.prototype.getUTCUnixTime =  function (){
      return Math.floor( new Date(
        this.getUTCFullYear(),
        this.getUTCMonth(),
        this.getUTCDate(),
        this.getUTCHours(),
        this.getUTCMinutes(),
        this.getUTCSeconds()
      ).getTime() / 1000);
    }

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

    1
    2
    3
    4
    5
    var n = new Date(2008,10,10)
    ...
    ...

    n.getUTCUnixTime();

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

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

    芝加哥商业交易所。


    这将返回UTC的时间戳:

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


    我想这就是你所期待的......

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

    现在,

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