moment-timezone.js 转换错误
moment-timezone.js doing wrong conversion
我正在尝试从一个时区转换为另一个时区(手动)获取日期对象并通过此函数返回另一个:
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));
}
一个例子是:
- Date date = 2018 年 8 月 17 日星期五 14:36:25 GMT+0200 (hora de verano de Europa central)
- 时刻sourceMoment = "2018-08-17 14:36"时刻
- localMoment = "2018-08-17T13:36:00"
为什么墨西哥 -> 里斯本只提前一小时?据我所知,localmoment 应该是“2018-08-17T20:36:00”。
我做错了什么?这似乎适用于 Europe/Lisbon 到 Europe/Madrid,但我不知道为什么。
谢谢。
解决方案:
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');
一个Date
对象永远不会表示任意时区的时间。它在内部跟踪自 1970-01-01 00:00:00 UTC 以来的毫秒数。显示非 UTC 时间的函数总是在 UTC 和执行代码的机器的 local 时区之间转换。任何对 return 位于其他时区的 Date
对象的尝试最终都会失败,无论您是使用 moment 来操纵事物还是其他一些技术,因为您无法绕过的行为本地时区。
此外,在使用 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-0700
和 Pacific Daylight Time
。更重要的是,它仍将使用太平洋标准时间和太平洋夏令时之间的 DST 转换,无论这些转换是否适用于其他时区。
这说明了 Date
对象的时区限制。 moment
对象没有这样的限制。
最后,如果您正在编写仅针对现代浏览器或 Node.js 的新应用程序,Moment 团队建议改用 Luxon。它的时区支持是由环境而不是数据文件提供的,所以它要小得多。
我正在尝试从一个时区转换为另一个时区(手动)获取日期对象并通过此函数返回另一个:
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));
}
一个例子是:
- Date date = 2018 年 8 月 17 日星期五 14:36:25 GMT+0200 (hora de verano de Europa central)
- 时刻sourceMoment = "2018-08-17 14:36"时刻
- localMoment = "2018-08-17T13:36:00"
为什么墨西哥 -> 里斯本只提前一小时?据我所知,localmoment 应该是“2018-08-17T20:36:00”。
我做错了什么?这似乎适用于 Europe/Lisbon 到 Europe/Madrid,但我不知道为什么。
谢谢。
解决方案:
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');
一个Date
对象永远不会表示任意时区的时间。它在内部跟踪自 1970-01-01 00:00:00 UTC 以来的毫秒数。显示非 UTC 时间的函数总是在 UTC 和执行代码的机器的 local 时区之间转换。任何对 return 位于其他时区的 Date
对象的尝试最终都会失败,无论您是使用 moment 来操纵事物还是其他一些技术,因为您无法绕过的行为本地时区。
此外,在使用 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-0700
和 Pacific Daylight Time
。更重要的是,它仍将使用太平洋标准时间和太平洋夏令时之间的 DST 转换,无论这些转换是否适用于其他时区。
这说明了 Date
对象的时区限制。 moment
对象没有这样的限制。
最后,如果您正在编写仅针对现代浏览器或 Node.js 的新应用程序,Moment 团队建议改用 Luxon。它的时区支持是由环境而不是数据文件提供的,所以它要小得多。