【问题标题】:Displaying timezone-formatted date as UTC time将时区格式的日期显示为 UTC 时间
【发布时间】:2016-04-14 17:57:30
【问题描述】:

在我的 UI 上,我尝试根据特定时区显示日期。在此示例中,我将使用 Americas/New_York 作为时区。我就是这样做的。

    $scope.getStartTime = function(){
        var date = new Date();
        return moment(date).tz("Americas/New_York").format('YYYY-MM-DD HH:mm:ss');
    };

之后,我想发送这些数据并将其发送到我的服务器。但是,在我的服务器中,我希望它始终序列化为 UTC 时间,而不是纽约时区 (EST)。

例如,如果时间是下午 12:00。在纽约,那么时间将被连载到下午 4:00。在发送到后端之前的 UTC 时间。这是我的尝试:

    var date = getStartTime();
    ....
    // Display the date in the UI
    ....
    $scope.revertStartTime(date);

    $scope.revertStartTime = function(startTime) {
        console.log("Start time: ", startTime);
        console.log("Moment: ", moment(startTime).format());
        console.log("Converted to utc time: ", moment().utc(startTime).format());
        return moment.utc(startTime).format("YYYY-MM-DD'T'HH:mm:ss.SSSZ");
    }

我尝试使用 moment().utc() 函数恢复开始时间,并希望日期会更改为基于 UTC 的日期,但不幸的是它一直将我的日期变成本地化日期而不是 UTC 日期,我不确定为什么。任何帮助,将不胜感激。谢谢!

编辑:

尝试遵循以下方法,这就是我所做的:

    $scope.getStartTime = function(){
        var date = new Date();
        var startTime = new moment(date).tz($rootScope.userinfo.timeZone).format('YYYY-MM-DD HH:mm:ss');
        $rootScope.offset = moment().utcOffset(startTime);    
        console.log("offset: ", $rootScope.offset);
        return startTime;
    };

    $scope.revertStartTime = function(startTime) {
        console.log("User Selected Time: ", moment().utcOffset(startTime).format('YYYY-MM-DD HH:mm:ss'));
        return moment().utcOffset(startTime).format('YYYY-MM-DD HH:mm:ss');
    }

但我得到的只是一个错误,说 revertStartTime 返回一个 Invalid Date

【问题讨论】:

    标签: javascript date datetime timezone momentjs


    【解决方案1】:

    一些事情:

    • 希望这是一个错字,但要指出的是,区域 ID 是 America/New_York,而不是 Americas/New_York

    • 您可以将值传递为moment.utc(foo)moment(foo).utc(),但不能传递moment().utc(foo)。不同之处在于,一个人将输入解释为 UTC 并保持 UTC 模式,而另一个人只是切换到 UTC 模式。您也可以将其视为“转换为 UTC”,但实际上底层时间戳值并没有改变。

    • 是的,您可以切换到 UTC 模式和呼叫格式,但您也可以直接呼叫 .toISOString(),无论您处于何种模式。这已经是您正在寻找的 ISO 格式。

    • 请注意,如果您从一个唯一的时间点开始,并以转换为 UTC 结束,那么中间的任何切换时区或偏移量都不会改变结果。换句话说,这些都是等价的:

      moment().toISOString()
      moment.utc().toISOString()
      moment(new Date()).toISOString()
      moment.utc(new Date()).toISOString()
      moment(new Date()).utc().toISOString()
      moment().tz('America/New_York').toISOString()
      moment.tz('America/New_York').toISOString()
      moment().utcOffset(1234).toISOString()
      moment.utc().format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]')
      moment().utc().format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]')
      

      甚至只有最后两个需要处于 UTC 模式,因为如果在本地模式或特定时区,format 函数会产生不同的输出。

    【讨论】:

    • 嗨,马特,我已经阅读了你的例子,我明白你在说什么。我尝试了以下方法:moment().utcOffset(startTime).toISOString() 其中 startTime 是这样分配的:startTime = new moment(date).tz("Americas/New_York").format('YYYY-MM-DD HH:mm:ss')。通过这种方式,我想更改startTime,无论它是什么(它可以更改,因为它是时间选择器中的日期)并将其转换为UTC时间。但是,该方法给了我一个Invalid Date。有什么理由会这样吗?
    • 你不能把它传递给utcOffset。偏移量可以是距 UTC 的分钟数,也可以是 "-04:00" 之类的字符串。我只是想说明,无论您传递什么偏移量,它都不会影响该特定操作的结果。
    • 您真正想要完成的是什么?如果date 只是从new Date() 派生的当前日期,那么您不需要提供它。目前还不清楚你在问什么。您是否只是说您有一个格式为纽约时间的字符串,并且您想要相同格式的等效 UTC 时间?
    【解决方案2】:

    为了实现这一点,您需要使用.utcOffset()。这是 Moment 2.9.0 的首选方法。此函数使用与 UTC 的实际偏移量,而不是反向偏移量(例如,DST 期间的纽约为 -240)。像“+0400”这样的偏移字符串的工作方式和以前一样:

    // always "2013-05-23 00:55"
    moment(1369266934311).utcOffset(60).format('YYYY-MM-DD HH:mm')
    moment(1369266934311).utcOffset('+0100').format('YYYY-MM-DD HH:mm')
    

    旧的 .zone() as a setter 在 Moment.js 2.9.0 中被弃用。它接受包含时区标识符的字符串(例如,“-0400”或“-04:00”表示 -4 小时)或表示 UTC 分钟的数字(例如,DST 期间纽约的 240 )。

    // always "2013-05-23 00:55"
    moment(1369266934311).zone(-60).format('YYYY-MM-DD HH:mm')
    moment(1369266934311).zone('+0100').format('YYYY-MM-DD HH:mm')
    

    要使用命名时区而不是数字偏移量,请包含 Moment Timezone 并改用 .tz()

    // determines the correct offset for America/Phoenix at the given moment
    // always "2013-05-22 16:55"
    moment(1369266934311).tz('America/Phoenix').format('YYYY-MM-DD HH:mm')
    

    【讨论】:

    • 啊,我明白了。代码的最后一行有效,但实际上给出了不正确的偏移量。正如我在上面发布的,我的时间是东部标准时间。但是,我的本地时区是太平洋标准时间。当我像这样执行上述操作时:moment(startTime).tz('UTC').format(),我的 startTime 偏移了 7 小时(太平洋标准时区应该是这样)而不是 4 小时(东部标准时区应该是这样)。你知道为什么会这样吗?
    • @user1871869 - 尝试查看以下内容,让我知道这是否有意义:jsfiddle.net/uq99udc9/4。如果没有,我会再深入一点 - 你就快到了!
    • 嗨,我看过你的例子,但我似乎无法弄清楚如何用我自己的用例来做到这一点。原因是我正在使用时间并将其显示在基于特定时区(在我的情况下为 EST)的时间选择器上。在这个时间选择器上,用户可以将时间更改为他或她想要的任何时间,然后当我单击提交时,我会将他们在时间选择器上设置的时间更改为 UTC 时间(总是提前 +4 小时)他们设置的时间是因为 EST -> UTC 时间相差 4 小时。根据上面的小提琴,我似乎无法弄清楚。
    • 嘿,很遗憾,我无法让它工作。我试图按照你的方法,但我根本无法让它工作。我在上面发布了我的尝试。你介意为我做一个小提琴吗?谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 2018-08-31
    • 2018-05-08
    相关资源
    最近更新 更多