假设您网站的用户输入了一个日期范围。
2009-1-1 to 2009-1-3
您需要将此日期发送到服务器进行某些处理,但服务器要求所有日期和时间均为UTC。
现在假设用户在阿拉斯加。由于它们所处的时区与UTC完全不同,因此需要将日期范围转换为如下所示:
2009-1-1T8:00:00 to 2009-1-4T7:59:59
使用JavaScriptDate对象,如何将第一个“本地化”日期范围转换为服务器能够理解的内容?
假设您网站的用户输入了一个日期范围。
2009-1-1 to 2009-1-3
您需要将此日期发送到服务器进行某些处理,但服务器要求所有日期和时间均为UTC。
现在假设用户在阿拉斯加。由于它们所处的时区与UTC完全不同,因此需要将日期范围转换为如下所示:
2009-1-1T8:00:00 to 2009-1-4T7:59:59
使用JavaScriptDate对象,如何将第一个“本地化”日期范围转换为服务器能够理解的内容?
当前回答
我的解决方案使日期保持不变,无论客户端上设置了什么时区。也许有人会发现它很有用。
我的用例:
我正在创建一个todo应用程序,您可以在其中设置任务日期。无论您在哪个时区,此日期都应保持不变。
实例你想在6月25日早上8点给你的朋友打电话。
您在中国时,在5天前(6月20日)创建此任务。
然后,在同一天,你飞往纽约几天。
然后在6月25日,当你还在纽约时,你在早上7:30醒来(这意味着你应该在30分钟内收到任务通知(即使在中国,你创建任务时已经是下午1:30)
因此,任务是忽略时区。这意味着“我想在早上8点在任何时区做这件事”。
我所做的是让我们说“我假设你总是在伦敦时区-UTC”。
这意味着-当用户在她/他的时区中选择某个日期时-我将此日期转换为UTC中的相同日期。也就是说,你在中国选择上午8点,但我将其转换为UTC的上午8点。
然后-下次你打开应用程序时-我读取以UTC保存的日期,并将其转换为当前时区中的相同日期-例如,我将UTC中的上午8点转换为纽约时区中的早上8点。
这个解决方案意味着,日期可能意味着其他东西,这取决于你在设置日期时的位置和阅读日期的位置,但它保持不变,“感觉”你总是在同一时区。
让我们编写一些代码:
首先,我们有两个主要函数用于从UTC转换为UTC,忽略时区:
export function convertLocalDateToUTCIgnoringTimezone(date: Date) {
const timestamp = Date.UTC(
date.getFullYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds(),
);
return new Date(timestamp);
}
export function convertUTCToLocalDateIgnoringTimezone(utcDate: Date) {
return new Date(
utcDate.getUTCFullYear(),
utcDate.getUTCMonth(),
utcDate.getUTCDate(),
utcDate.getUTCHours(),
utcDate.getUTCMinutes(),
utcDate.getUTCSeconds(),
utcDate.getUTCMilliseconds(),
);
}
然后,我保存/读取此日期,如:
function saveTaskDate(localDate: Date) {
// I convert your local calendar date so it looks like you've picked it being in UTC somewhere around London
const utcDate = convertLocalDateToUTCIgnoringTimezone(localDate);
api.saveTaskDate(utcDate);
}
function readTaskDate(taskUtcDate: Date) {
// I convert this UTC date to 'look in your local timezone' as if you were now in UTC somewhere around london
const localDateWithSameDayAsUTC = convertUTCToLocalDateIgnoringTimezone(taskUtcDate);
// this date will have the same calendar day as the one you've picked previously
// no matter where you were saving it and where you are now
}
其他回答
浏览器可能会有所不同,你也应该记住不要相信客户端生成的任何信息,也就是说,下面的声明适用于我(Mac OS X 10.8.2上的Google Chrome v24)
var utcDate=新日期(new Date().getTime());
edit:“这和new Date()有什么不同?”请参见此处:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
如果未提供任何参数,则构造函数将根据系统设置为当前日期和时间创建JavaScript Date对象。注意:当Date作为具有多个参数的构造函数调用时,指定的参数表示本地时间。如果需要UTC,请使用具有相同参数的新日期(Date.UTC(…))。(注意:Date.UTC()返回自1970-01-01 00:00:00 UTC以来的毫秒数)
如前面的答案所述,添加60000*Date.getTimezoneOffset()是不正确的。首先,您必须将所有日期/时间视为UTC,并使用时区修饰符进行显示。
同样,浏览器可能有所不同,然而,Date.getTime()返回自1970-01-01 UTC/GMT以来的毫秒数。如果您像我上面所做的那样使用这个数字创建一个新的日期,它将是UTC/GMT。但是,如果通过调用.toString()来显示它,它将显示在本地时区中,因为.toString()使用的是本地时区,而不是调用它的Date对象的时区。
我还发现,如果您在日期上调用.getTimezoneOffset(),它将返回您的本地时区,而不是您调用它的日期对象的时区(但我无法验证这是否是标准的)。
在我的浏览器中,添加60000*Date.getTimezoneOffset()将创建一个不是UTC的DateTime。然而,当在我的浏览器中显示(例如:.toString())时,它会在我的本地时区中显示一个DateTime,如果忽略时区信息,该DateTime将是正确的UTC时间。
Date.prototype.toUTCArray= function(){
var D= this;
return [D.getUTCFullYear(), D.getUTCMonth(), D.getUTCDate(), D.getUTCHours(),
D.getUTCMinutes(), D.getUTCSeconds()];
}
Date.prototype.toISO= function(){
var tem, A= this.toUTCArray(), i= 0;
A[1]+= 1;
while(i++<7){
tem= A[i];
if(tem<10) A[i]= '0'+tem;
}
return A.splice(0, 3).join('-')+'T'+A.join(':');
}
这是我的方法:
var now = new Date();
var utc = new Date(now.getTime() + now.getTimezoneOffset() * 60000);
生成的utc对象实际上不是utc日期,而是转换为与utc时间匹配的本地日期(请参见注释)。然而,在实践中,它确实起到了作用。
更新:当调用UTC.toString()、UTC.toLocaleString()等时,这个答案是获取UTC日期的一种快速而肮脏的方法。不过,有更好的解决方案,尤其是现在使用现代浏览器的情况下,我应该改进一下答案。基本上,.toISOString()(IE 9+)是您想要使用的。
我发现jQuery全球化插件的日期解析工作得最好。其他方法存在跨浏览器问题,像date.js这样的东西已经很长时间没有更新了。
页面上也不需要datePicker。您可以调用与文档中给出的示例类似的内容:
$.parseDate('yy-mm-dd', '2007-01-26');
简单又愚蠢
var date=新日期();var now_utc=日期utc(Date.getUTCFullYear(),Date.getUTCMonth(),date.getUTCDate(),date.getUTPours(),date.getUTCMinutes(),date.getUTCSeconds());console.log(新日期(now_utc));console.log(date.toISOString());