我正在尝试从一个时区转换为另一个(手动)获取日期对象并通过此函数返回另一个:
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”。
我做错了什么?这似乎适用于欧洲/里斯本到欧洲/马德里,但我不知道为什么。
谢谢。
解决方法:
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');
最佳答案
A Date
对象永远不能代表任意时区的时间。它在内部跟踪自 1970-01-01 00:00:00 UTC 以来的毫秒数。显示非 UTC 时间的函数始终在 UTC 和执行代码的机器的本地时区之间进行转换。任何返回 Date
的尝试位于其他时区的对象最终会失败,无论您是使用 moment 来操纵事物还是使用其他技术,因为您无法绕过本地时区的行为。
此外,在使用 Moment 时,您不应该对输入和输出进行如此多的手动操作,例如您从日期部分手动创建然后再次解析的字符串。 Moment 可以为您处理这些事情。
您可以使用 Date
对象作为构建 moment
时的输入对象,但这将用于从 Date
保留的 UTC 即时转换目的。你可以构造一个 Date
来自本地时间或来自 UTC 时间的对象,但不是来自任意时区。因此你不能断言 America/Mexico_City
作为输入时区,如果您的来源是 Date
目的。相反,您可以传递一个字符串、一个数组、具有各个部分的整数,或任何其他创建 moment
的方法。文档中描述的对象。
同样,您永远无法输出 Date
如果您希望它反射(reflect)任意时区,请使用对象。虽然 moment 确实有一个 .toDate()
函数,它将基于时刻的 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反而。它的时区支持是由环境而不是数据文件提供的,所以它要小得多。
关于javascript - moment-timezone.js 转换错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51895713/