【问题标题】:moment-timezone.js doing wrong conversionmoment-timezone.js 转换错误
【发布时间】:2019-01-24 12:22:24
【问题描述】:

我正在尝试从一个时区转换为另一个时区(手动)获取一个 Date 对象并通过此函数返回另一个:

 getDateInMomentFormatToSave: function (date) {
                function padNums(num) {
                    return num.toString().length == 1 ? "0" + num : num;
                }
                var month = padNums(date.getMonth() + 1);
                var day = padNums(date.getDate());
                var hour = padNums(date.getHours());
                var minutes = padNums(date.getMinutes());
                var result = moment(date.getFullYear() + "-" + month + "-" + day + " " + hour + ":" + minutes, "YYYY-MM-DD HH:mm");
                var sourceMoment = moment.tz(result, "America/Mexico_City"); //UTC neutro de la BD moment.tz.guess()
                var localMoment = sourceMoment.clone().tz("Europe/Lisbon").format('YYYY-MM-DD[T]HH:mm:ss');
                return new Date(localMoment.substring(0, 19));
            }

一个例子是:

  • 日期日期 = 2018 年 8 月 17 日星期五 14:36:25 GMT+0200 (hora de verano de Europa central)
  • Moment sourceMoment = "2018-08-17 14:36" Moment
  • localMoment = "2018-08-17T13:36:00"

为什么墨西哥 -> 里斯本只提前一小时?据我所知,localmoment 应该是“2018-08-17T20:36:00”。

我做错了什么?这似乎适用于欧洲/里斯本到欧洲/马德里,但我不知道为什么。

谢谢。

解决方案:

var result = moment.tz(date.getFullYear() + "-" + month + "-" + day + " " + hour + ":" + minutes, "America/Mexico_City");
var localMoment = result.clone().tz("Europe/Lisbon").format('YYYY-MM-DD[T]HH:mm:ss');

【问题讨论】:

  • 我不知道为什么,但在初始化时刻调用 .tz 可以解决问题: var result = moment.tz(date.getFullYear() + "-" + month + "-" + day + " " + 小时 + ":" + 分钟, "America/Mexico_City"); var localMoment = result.clone().tz("欧洲/里斯本").format('YYYY-MM-DD[T]HH:mm:ss');

标签: javascript date timezone momentjs moment-timezone


【解决方案1】:

Date 对象从不代表任意时区的时间。它在内部跟踪自 1970-01-01 00:00:00 UTC 以来的毫秒数。显示非 UTC 时间的函数总是在 UTC 和执行代码的机器的本地时区之间转换。任何返回位于其他时区的Date 对象的尝试最终都会失败,无论您是使用时刻来操作事物还是其他一些技术,因为您无法绕过本地时区的行为。

此外,在使用 Moment 时,您不应该对输入和输出进行太多手动操作,例如从日期部分手动创建然后再次解析的字符串。 Moment 可以为您处理这些事情。

您可以在构造moment 对象时使用Date 对象作为输入,但这将用于从Date 对象保存的UTC 时刻进行转换。您可以从本地时间或 UTC 时间构造 Date 对象,但不能从任意时区构造。因此,如果您的源是Date 对象,则不能将America/Mexico_City 断言为输入时区。相反,您可以传递字符串、数组、具有单个部分的整数,或文档中描述的任何其他创建 moment 对象的方法。

同样,如果您希望它反映任意时区,则永远不能输出 Date 对象。虽然 moment 确实具有 .toDate() 函数,但它将基于 moment 的 UTC 时间构造(由于 Date 对象的限制)。换句话说,像moment(someDateObject).tz(someTimeZone).toDate() 这样的代码只会产生与您开始时相同的someDateObject - 无论经过的时区如何。

使用字符串从一个时区转换为另一个时区的代码如下:

moment.tz("2018-08-17 14:36:25", "YYYY-MM-DD HH:mm:ss", "America/Mexico_City")
      .tz("Europe/Lisbon").format("YYYY-MM-DD HH:mm:ss")

//=> "2018-08-17 20:36:25"

同样的使用数组的代码是这样的:

moment.tz([2018, 7, 17, 14, 36, 25, 0], "America/Mexico_City")
      .tz("Europe/Lisbon").toArray()

//=> [2018, 7, 17, 20, 36, 25, 0]   (note months are 0-11)

但现在看看我们是否使用Date 对象,它是如何不起作用的:

moment.tz(new Date(2018, 7, 17, 14, 36, 25, 0), "America/Mexico_City")
      .tz("Europe/Lisbon").toDate()

//=> Fri Aug 17 2018 14:36:25 GMT-0700 (Pacific Daylight Time)

因为我的电脑是太平洋时间,输入日期被视为太平洋时间(不是墨西哥城),输出日期显示为太平洋时间(不是里斯本)。即使我尝试调整时间以匹配其他时区,它仍然会显示GMT-0700Pacific Daylight Time。更重要的是,它仍然会使用太平洋标准时间和太平洋夏令时间之间的 DST 转换,无论这些转换是否适用于其他时区。

这说明了Date 对象的时区限制。 moment 对象没有这样的限制。

最后,如果您正在编写仅针对现代浏览器或 Node.js 的新应用程序,Moment 团队建议您改用 Luxon。它的时区支持是由环境而不是数据文件提供的,所以它要小得多。

【讨论】:

  • 感谢您清除对象创建的瞬间。它大大简化了我的代码。关于使用 Luxon,我会尝试一下。谢谢,
猜你喜欢
  • 2021-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-26
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
相关资源
最近更新 更多