正如 @Alnitak 所说,这是一个严格的演示问题。所有 JavaScript 日期都以 UTC 格式在内部存储,并在浏览器 (OS) 的本地时区进行操作。目标时区发挥作用的唯一地方是当您将 Date 对象转换为字符串以便将其显示给用户时。所有日期都将根据每个用户的本地时区进行格式化。
但是,如果您想在某个特定时区格式化日期(例如,当您的用户在纽约并且您想在莫斯科显示日期时),您将不得不使用更高级的格式化实用程序,例如 Moment.js 和 @ 987654322@.
当您控制应用程序中的所有日期格式时 - 这很容易实现。但是,当您需要将此功能传递给一些不关心时区等的第三方组件(例如某些 DatePicker 组件)时,它可能会变得非常丑陋。
我发现解决此问题的唯一实用解决方案是创建一个标准的Date 对象,该对象假装在用户的本地时区。这是您可以使用的功能:
/**
* Returns standard Date from Moment.js date as if it was in local timezone.
* Use getMoment() method of the result to get proper Moment.js date back.
*
* @param {object} momentDate
*
* @returns {Date}
*/
function momentAsLocalDate(momentDate) {
var origOffset = momentDate.format('ZZ');
var localOffset = moment().format('ZZ');
// Creating a standard date as if date was in current browser TZ.
var stdDate = new Date(
// Creating date from ISO:8601 format.
momentDate.format('YYYY-MM-DDTHH:mm:ss') + localOffset
);
stdDate.getMoment = function() {
function pad(number) {
if (number < 10) {
return '0' + number;
}
return number;
}
// String in ISO:8601 format.
var dateString =
this.getFullYear() +
'-' + pad(this.getMonth() + 1) +
'-' + pad(this.getDate()) +
'T' + pad(this.getHours()) +
':' + pad(this.getMinutes()) +
':' + pad(this.getSeconds()) +
origOffset
;
// Creating a new moment from date string.
var momentDate = moment(dateString);
// Setting original timezone.
momentDate.zone(origOffset);
return momentDate;
};
return stdDate;
}
这个函数的用法可以通过下面的简单测试来演示:
/**
* A stupid third-party component that doesn't care about timezones.
*
* @param {Date} inputDate
*/
var thirdPartyComponent = function(inputDate) {
// Showing date to a user.
console.log('Here is the date: ' + inputDate);
// Changing the date.
inputDate.setHours(17, 30);
};
var momentDate = moment('2014-12-14T21:00:00+03:00').zone('+03:00');
console.log('Original Moment Date', momentDate.format());
var stdDate = momentAsLocalDate(momentDate);
console.log('Converted Local Date', stdDate);
thirdPartyComponent(stdDate);
console.log('Changed Local Date', stdDate);
console.log('Converted Moment Date', stdDate.getMoment().format());
您将在控制台中得到以下结果:
Original Moment Date 2014-12-14T21:00:00+03:00
Converted Local Date Sun Dec 14 2014 21:00:00 GMT-0500 (EST)
Here is the date: Sun Dec 14 2014 21:00:00 GMT-0500 (EST)
Changed Local Date Sun Dec 14 2014 17:30:00 GMT-0500 (EST)
Converted Moment Date 2014-12-14T17:30:00+03:00
如果可以的话,我强烈建议不要在实践中使用这种方法。更好的做法是重写组件以支持时区或切换到更好的组件。但是,如果没有其他选择,请谨慎使用,风险自负。
如果有更好的解决方案,或者这个例子可以改进 - 请告诉我。
干杯!