当前位置: 首页 > 知识库问答 >
问题:

使用moment.js将一系列跨越秋季DST边界的非UTC时间戳转换为UTC时间戳的正确方法?

陈高寒
2023-03-14
moment('2017-03-12T06:59:59Z').tz('America/New_York').format('YYYY/MM/DD hh:mm:ss a z')

由于我的时间戳上有z,所以上面的输入被视为UTC,并且我正在用.tz('America/New_York')显式地设置目标时区,以便它不使用本地系统时间。

或者,使用moment-timezone,我可以显式地将输入时区设置为UTC,并将输出设置为America/New_York。

moment.tz('2017-03-12T06:59:59', 'UTC').tz('America/New_York').format('YYYY/MM/DD hh:mm:ss a z')

无论哪种方式,结果都是2017/03/12 01:59:59 am EST

moment('2017-03-12T07:00:00Z').tz('America/New_York').format('YYYY/MM/DD hh:mm:ss a z')

我的结果与预期的一样正确:2017/03/12 03:00:00 am EDT-由于夏令时,时间提前了一个小时。

然后,我可以使用moment-timezone返回另一种方式,通过传入America/New_York时间戳并将其转换为UTC。

moment.tz('2017-03-12T01:59:59', 'America/New_York').utc().format('YYYY/MM/DD hh:mm:ss a z')

这给出了2017/03/12 06:59:59 am UTC

    moment.tz('2017-03-12T03:00:00', 'America/New_York').utc().format('YYYY/MM/DD hh:mm:ss a z')

我的问题

太好了,所以我想做同样的事情,当夏令时在秋天结束,当然,这不是那么简单。我的假设是,由于夏令时有效地导致一个小时“重复”,所以moment没有办法知道正确的时间UTC。换句话说,在夏令时开始的时候有一个小时的间隙,现在我们有一个小时的重叠。

问题(第1部分):是否有一种方法将相对时间戳和时区传递到矩中,并返回正确的UTC时间?当我在下面的示例中尝试时,moment在UTC端跳过了一个小时。

moment.tz('2017-11-05T01:00:00', 'America/Denver').tz('UTC').format('YYYY/MM/DD hh:mm:ss a z') => "2017/11/05 07:00:00 am UTC"
moment.tz('2017-11-05T01:59:59', 'America/Denver').tz('UTC').format('YYYY/MM/DD hh:mm:ss a z') => "2017/11/05 07:59:59 am UTC"
moment.tz('2017-11-05T02:00:00', 'America/Denver').tz('UTC').format('YYYY/MM/DD hh:mm:ss a z') => "2017/11/05 09:00:00 am UTC"
moment.tz('2017-11-05T02:59:59', 'America/Denver').tz('UTC').format('YYYY/MM/DD hh:mm:ss a z') => "2017/11/05 09:59:59 am UTC"
*2017/11/05 01:00:00 am America/New_York => 2017/11/05 07:00:00 am UTC
*2017/11/05 01:59:59 am America/New_York => 2017/11/05 07:59:59 am UTC
*2017/11/05 01:00:00 am America/New_York => ???
*2017/11/05 01:59:59 am America/New_York => ???
2017/11/05 02:00:00 am America/New_York => 2017/11/05 09:00:00 am UTC
2017/11/05 02:59:59 am America/New_York => 2017/11/05 09:59:59 am UTC
  • moment.js将本地时间转换为UTC时间起作用
  • 用创建时区偏移量初始化时刻

共有1个答案

慎弘化
2023-03-14

看起来你把问题想透了,做了一些基础研究。谢谢!

您所描述的内容在这里的“时刻-时区”文档中有涉及。如果输入中的数据不能作为UTC偏移量使用,则无法区分第一次或第二次出现不明确的本地时间之间的区别。Moment选择第一个发生,因为时间是向前移动的,所以对于大多数场景来说,这通常是最明智的选择。

问题是模棱两可。即使作为一个人,如果我说“2017年11月5日凌晨1点在纽约”,你也不知道我在描述两个时间点中的哪一个。

这就是说,有时你有外部的知识可以帮助你。例如,如果您有一组有序的时间戳,其中包含向后跳过的时间,那么您就知道遇到了回落转换。假设我以当地时间15分钟为间隔记录数据:

00:45
01:00
01:15
01:30
01:45
01:00  <---  this one comes next sequentially, but appears backwards, so infer transition
01:15
01:30
01:45
02:00

您必须编写自己的检测逻辑来比较该场景中的一个值和下一个值。还请注意,如果您没有任何时间出现的顺序混乱,那么您就无法确定所描述的是哪一个事件。在某些情况下,“心跳”信号可以帮助实现这一点。

function adjustToLaterWhenAmbiguous(m) {
    if (hasAmbiguousWallTime(m)) {
        m.utcOffset(moment(m).add(1, 'hour').utcOffset(), true);
    }
}

现在可以这样做了:

// start with the first occurrence
var m = moment.tz("2017-11-05T01:00:00", "America/New_York");
m.format(); // "2017-11-05T01:00:00-04:00"

// now shift it to the second occurrence
if (... your logic, such as wall time going backwards in sequence, etc. ...) {
    adjustToLaterWhenAmbiguous(m);
    m.format(); // "2017-11-05T01:00:00-05:00"
}

这两个函数可能应该被硬化并添加到moment-timezone中,但它们应该足以满足您描述的场景。

还有几个要点:

    null
 类似资料:
  • 问题内容: 我有一个毫秒本地本地时间戳,我想将其转换为毫秒本地UTC时间戳。快速浏览一下文档,看起来像这样工作: 有一个更好的方法吗? 问题答案: 使用a 来获取本地纪元处的偏移量,然后将其添加到本地纪元时间戳中。

  • 问题内容: 我正在寻找将UTC时间字符串转换为Unix时间戳的选项。 我拥有的字符串变量是,需要将其转换为unix时间戳,例如 任何想法如何做到这一点? 问题答案: 首先,unix时间戳没有时间,但以UTC为单位。 在包有功能解析与预计解析时的布局。布局是从参考时间开始构造的。因此,在您的情况下,布局应为。使用Parse之后,您将获得一个可以调用Unix来接收Unix时间戳的结构。

  • 我尝试了convert_timezone('CET',current_timestamp)函数,但它在AWS Athena中不被识别 在更简单的工作中,我在Presto中寻找SQL Server函数GETUTCDATE()的替代品,只是希望获得CET时间戳。有什么建议吗?

  • 问题内容: 我正在使用MongoDB来存储我的数据。Mongo默认将时间戳存储在UTC中。我们在不同时区处理数据。我正在努力将UTC时间戳转换为PDT或IST时间戳。 试图构造一种方法来传递时区(将我的时间戳转换为时区)和timestamp(UTC)。返回指定时区的时间戳的方法。 问题答案: 您可以使用带有所需时区的dateformat并将其应用于日期

  • 我正在尝试使用Joda在一个简单的Java程序中获取UTC时间戳: 程序输出如下: 毫秒值是正确的UTC时间(即用时区确认)第二个值是时区。 我需要的是UTC值不变为(即独立于TZ),用于数据库写入。这可能吗? 我知道是本地日期(GMT-4),是UTC(GMT-0)。日期的输出值如下: 我尝试了所有组合,试图将的UTC值作为java.sql.TimeStamp: 用于测试的打印输出: 第一行是正确

  • 我想把UTC的时间戳转换成Postgres中的毫秒。我在Ruby控制台上使用这个查询(使用Postgres)。我的问题是: 以上查询结果, 2018年7月5日星期四05:05:39 UTC 00:00至1530767139732.35 输出看起来不错,但在“.”之后我不需要35岁。有没有办法得到13位毫秒的输出。 我会很感激你的帮助。