假设您网站的用户输入了一个日期范围。
2009-1-1 to 2009-1-3
您需要将此日期发送到服务器进行某些处理,但服务器希望所有日期和时间都采用 UTC。
现在假设用户在阿拉斯加或夏威夷或斐济。由于它们所在的时区与 UTC 完全不同,因此需要将日期范围转换为以下内容:
2009-1-1T8:00:00 to 2009-1-4T7:59:59
使用 JavaScript Date 对象,您如何将第一个“本地化”日期范围转换为服务器可以理解的内容?
假设您网站的用户输入了一个日期范围。
2009-1-1 to 2009-1-3
您需要将此日期发送到服务器进行某些处理,但服务器希望所有日期和时间都采用 UTC。
现在假设用户在阿拉斯加或夏威夷或斐济。由于它们所在的时区与 UTC 完全不同,因此需要将日期范围转换为以下内容:
2009-1-1T8:00:00 to 2009-1-4T7:59:59
使用 JavaScript Date 对象,您如何将第一个“本地化”日期范围转换为服务器可以理解的内容?
简单而愚蠢
var date = new Date();
var now_utc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
return new Date(now_utc);
该
toISOString()
方法以简化的扩展 ISO 格式 ( ISO 8601 ) 返回一个字符串,该字符串的长度始终为 24 或 27 个字符(分别为YYYY-MM-DDTHH:mm:ss.sssZ
或±YYYYYY-MM-DDTHH:mm:ss.sssZ
)。时区始终为 0 UTC 偏移量,由后缀“Z
”表示。
来源: MDN 网络文档
您需要的格式是使用该.toISOString()
方法创建的。对于本机不支持此方法的旧浏览器(ie8 及以下),可以在此处找到 shim :
这将使您能够做您需要的事情:
var isoDateString = new Date().toISOString();
console.log(isoDateString);
对于时区工作,moment.js 和 moment.js 时区确实是非常宝贵的工具……尤其是在客户端和服务器 javascript 之间导航时区。
这是我的方法:
var now = new Date();
var utc = new Date(now.getTime() + now.getTimezoneOffset() * 60000);
生成的utc
对象并不是真正的 UTC 日期,而是转移以匹配 UTC 时间的本地日期(请参阅注释)。但是,在实践中,它可以完成工作。
在不更改日期/时间的情况下转换为 ISO
var now = new Date(); // Fri Feb 20 2015 19:29:31 GMT+0530 (India Standard Time)
var isoDate = new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString();
//OUTPUT : 2015-02-20T19:29:31.238Z
转换为 ISO 并更改日期/时间(日期/时间将更改)
isoDate = new Date(now).toISOString();
//OUTPUT : 2015-02-20T13:59:31.238Z
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(':');
}
浏览器可能会有所不同,您还应该记住不要相信客户端生成的任何信息,也就是说,以下语句对我有用(Mac OS X 10.8.2 上的 Google Chrome v24)
var utcDate = new Date(new Date().getTime());
编辑:“这和刚才有什么不同new Date()
?” 见这里:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
如先前的答案所述,添加 60000 * Date.getTimezoneOffset() 是不正确的。首先,出于显示目的,您必须将所有日期/时间都视为带有时区修饰符的 UTC。
同样,浏览器可能会有所不同,但是 Date.getTime() 返回自 1970-01-01 UTC/GMT 以来的毫秒数。如果您像上面一样使用此数字创建一个新日期,它将是 UTC/GMT。但是,如果您通过调用 .toString() 来显示它,它将显示在您的本地时区,因为 .toString() 使用您的本地时区,而不是调用它的 Date 对象的时区。
我还发现,如果您在某个日期调用 .getTimezoneOffset() ,它将返回您的本地时区,而不是您调用它的日期对象的时区(但是我无法验证这是标准的)。
在我的浏览器中,添加 60000 * Date.getTimezoneOffset() 会创建一个不是 UTC的 DateTime 。但是,当在我的浏览器中显示(例如: .toString() )时,它会在我的本地时区显示一个 DateTime,如果忽略时区信息,它将是正确的 UTC 时间。
转换为 UTC 并将其保留为日期对象的另一种解决方案:(它的工作原理是从格式化字符串的末尾删除“GMT”部分,然后将其放回 Date 构造函数)
var now = new Date();
var now_utc = new Date(now.toUTCString().slice(0, -4));
console.log(now_utc)
我需要这样做才能与日期时间选择器库交互。但总的来说,以这种方式处理日期是个坏主意。
用户通常希望在本地时间使用日期时间,因此您可以更新服务器端代码以正确解析具有偏移量的日期时间字符串,然后转换为 UTC(最佳选择),或者在发送到客户端之前转换为 UTC 字符串客户端服务器(就像Will Stern 的回答一样)
无论客户端设置什么时区,我的解决方案都会使日期保持不变。也许有人会发现它很有用。
我的用例:
我正在创建一个待办事项应用程序,您可以在其中设置任务日期。无论您在哪个时区,这个日期都应该保持不变。
例子。你想在 6 月 25 日早上 8 点给你的朋友打电话。
您在中国的 5 天前(6 月 20 日)创建了此任务。
然后,在同一天,您飞往纽约几天。
然后在 6 月 25 日,当你还在纽约时,你会在早上 7:30 起床(这意味着你应该会在 30 分钟内收到任务通知(即使在你创建任务)
所以任务是忽略时区。这意味着“我想在早上 8 点在任何时区做这件事”。
我所做的是让我们说'我假设你总是在伦敦时区 - UTC'。
这意味着 - 当用户在她/他的时区中选择某个日期时 - 我将此日期转换为 UTC 中的同一日期。IE。您选择中国的上午 8 点,但我将其转换为 UTC 的上午 8 点。
然后 - 下次您打开应用程序时 - 我会读取以 UTC 保存的日期并将其转换为您当前时区中的相同日期 - 例如。我将 UTC 的上午 8 点转换为纽约时区的上午 8 点。
此解决方案意味着日期可能意味着其他内容,具体取决于您设置它时的位置以及您正在阅读它的位置,但它以一种“感觉”就像您始终处于同一个时区的方式保持不变。
让我们写一些代码:
首先 - 我们有 2 个主要功能用于从/转换到 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
}
var myDate = new Date(); // Set this to your date in whichever timezone.
var utcDate = myDate.toUTCString();
您是否正在尝试将日期转换为这样的字符串?
我会创建一个函数来做到这一点,虽然它有点争议,但将它添加到 Date 原型中。如果你不习惯这样做,那么你可以把它作为一个独立的函数,将日期作为参数传递。
Date.prototype.getISOString = function() {
var zone = '', temp = -this.getTimezoneOffset() / 60 * 100;
if (temp >= 0) zone += "+";
zone += (Math.abs(temp) < 100 ? "00" : (Math.abs(temp) < 1000 ? "0" : "")) + temp;
// "2009-6-4T14:7:32+10:00"
return this.getFullYear() // 2009
+ "-"
+ (this.getMonth() + 1) // 6
+ "-"
+ this.getDate() // 4
+ "T"
+ this.getHours() // 14
+ ":"
+ this.getMinutes() // 7
+ ":"
+ this.getSeconds() // 32
+ zone.substr(0, 3) // +10
+ ":"
+ String(temp).substr(-2) // 00
;
};
如果您在 UTC 时间需要它,只需将所有 get* 函数替换为 getUTC*,例如:getUTCFullYear、getUTCMonth、getUTCHours... 然后只需在末尾添加“+00:00”而不是用户的时区偏移量。
date = '2012-07-28'; stringdate = new Date(date).toISOString();
应该可以在大多数较新的浏览器中使用。它2012-07-28T00:00:00.000Z
在 Firefox 6.0 上返回
我在处理日期时的建议是将日期解析为用户输入的各个字段。您可以将其用作完整的字符串,但您正在玩火。
JavaScript 可以区别对待不同格式的两个相同日期。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
永远不要做类似的事情:
new Date('date as text');
从用户输入中将日期解析为各个字段后,创建一个日期对象。创建日期对象后,通过添加时区偏移量将其转换为 UTC。由于 DST,我不能强调使用日期对象的偏移量是多么重要(这是另一个讨论,但要说明原因)。
var year = getFullYear('date as text');
var month = getMonth('date as text');
var dayOfMonth = getDate('date as text');
var date = new Date(year, month, dayOfMonth);
var offsetInMs = ((date.getTimezoneOffset() * 60) // Seconds
* 1000); // Milliseconds
var utcDate = new Date(date.getTime + offsetInMs);
现在您可以将日期以 UTC 时间传递给服务器。我再次强烈建议不要使用任何日期字符串。将其传递给服务器,细分为您需要的最低粒度,例如年、月、日、分钟或作为 unix 纪元的毫秒值等值。
如果您经常处理日期,那么值得使用 moment.js ( http://momentjs.com )。转换为 UTC 的方法是:
moment(yourTime).utc()
您可以使用格式将日期更改为您想要的任何格式:
moment(yourTime).utc().format("YYYY-MM-DD")
时刻也有偏移选项,但还有一个额外的补充库来处理时区(http://momentjs.com/timezone/)。时间转换就像这样简单:
moment.tz(yourUTCTime, "America/New_York")
我发现jQuery Globalization Plugin日期解析效果最好。其他方法存在跨浏览器问题,并且 date.js 之类的东西已经有一段时间没有更新了。
您也不需要页面上的 datePicker。您可以调用类似于文档中给出的示例的内容:
$.parseDate('yy-mm-dd', '2007-01-26');
我刚刚发现 Steven Levithan 的date.format.js的 1.2.3 版本正是我想要的。它允许您为 JavaScript 日期提供格式字符串,并将本地时间转换为 UTC。这是我现在使用的代码:
// JavaScript dates don't like hyphens!
var rectifiedDateText = dateText.replace(/-/g, "/");
var d = new Date(rectifiedDateText);
// Using a predefined mask from date.format.js.
var convertedDate = dateFormat(d, 'isoUtcDateTime');
这个功能对我来说很好用。
function ParseDateForSave(dateValue) {
// create a new date object
var newDate = new Date(parseInt(dateValue.substr(6)));
// return the UTC version of the date
return newDate.toISOString();
}
此方法将为您提供 :2017-08-04T11:15:00.000+04:30
并且您可以忽略区域变量来简单地获取2017-08-04T11:15:00.000
.
function getLocalIsoDateTime(dtString) {
if(dtString == "")
return "";
var offset = new Date().getTimezoneOffset();
var localISOTime = (new Date(new Date(dtString) - offset * 60000 /*offset in milliseconds*/)).toISOString().slice(0,-1);
//Next two lines can be removed if zone isn't needed.
var absO = Math.abs(offset);
var zone = (offset < 0 ? "+" : "-") + ("00" + Math.floor(absO / 60)).slice(-2) + ":" + ("00" + (absO % 60)).slice(-2);
return localISOTime + zone;
}
const moment = require('moment');
const utc = moment.utc(new Date(string));
如果您需要日期对象
仅传递日期字符串 Date 假定时间按时区偏移 00:00:
new Date('2019-03-11')
Sun Mar 10 2019 18:00:00 GMT-0600 (Central Standard Time)
如果您添加当前小时和分钟,您将获得正确的日期:
new Date('2019-03-11 ' + new Date().getHours() + ':' + new Date().getMinutes())
Mon Mar 11 2019 04:36:00 GMT-0600 (Central Standard Time)
getTimezoneOffset()方法返回从当前区域设置(主机系统设置)到 UTC的时区差异(以分钟为单位)。
来源:MDN 网络文档
这意味着如果本地时区晚于 UTC,则偏移量为正,如果早于 UTC,则偏移量为负。例如,对于时区UTC+02:00,将返回-120 。
let d = new Date();
console.log(d);
d.setTime(d.getTime() + (d.getTimezoneOffset() * 60000));
console.log(d);
注意:这会将日期对象时间转换为UTC±00:00并且不转换其时区,因此日期对象时区仍将相同,但该值将以UTC±00:00为单位。
这是我过去所做的:
var utcDateString = new Date(new Date().toUTCString()).toISOString();
对于其他人的目标是将其作为“日期对象”而不是字符串,并且您只想显示没有 TZ(可能是硬编码)的日期/时间,您可以做的是:
const now = new Date();
const year = now.getUTCFullYear();
const month = now.getUTCMonth();
const day = now.getUTCDate();
const hour = now.getUTCHours();
const tomorrowUTC= new Date();
tomorrowUTC.setDate(day + 1); // +1 because my logic is to get "tomorrow"
tomorrowUTC.setYear(year);
tomorrowUTC.setMonth(month);
tomorrowUTC.Hours(hour);
// then use the tomorrowUTC for to display/format it
// tomorrowUTC is a "Date" and not a string.
然后,您可以执行以下操作:
We will delete your account at ${format(tomorrowUTC, 'EEEE do MMMM hh:mmaaa')} UTC
(format
是一个date-fns函数,如果需要,可以使用其他库);
这有点“hacky”,因为它仍在使用您的本地时区,但如果您只想显示日期而不是时区,那么这可行。
如果您的日期上有时区,您可以使用date-fns-tz:
import { zonedTimeToUtc } from 'date-fns-tz';
const dateBrazil = new Date() // I'm in Brazil, you should have or get the user timezone.
const dateUtc = zonedTimeToUtc(dateBrazil, 'America/Sao_Paulo')
查看您的问题很明显,您只想将日期范围发送到后端以进行进一步的后期处理。
我假设您符合标准数据指南,该指南期望数据采用特定格式。例如,我使用 ODATA,它是一个 RESTfull API,它期望日期时间对象采用以下格式:-
YYYY-MM-DDT00:00:00。
这可以通过下面发布的代码段轻松实现(请根据您的要求更改格式)。
var mydate;//assuming this is my date object which I want to expose
var UTCDateStr = mydate.getUTCFullYear() + "-" + mydate.getUTCMonth() + "-" + mydate.getUTCDate() + "T00:00:00";
另一方面,如果您处于从后端收到日期的情况,并且浏览器将其转换为您的本地日期。另一方面,您对 UTC 日期感兴趣,那么您可以执行以下操作:-
var mydate;//assuming this is my date object which I want to expose
var UTCDate = new Date(mydate);/*create a copy of your date object. Only needed if you for some reason need the original local date*/
UTCDate.setTime(UTCDate.getTime() + UTCDate.getTimezoneOffset() * 60 * 1000);
上面的代码片段基本上是根据时区添加/减去浏览器添加/减去的时间。
例如,如果我在 EST(GMT-5) 并且我的服务返回一个日期时间对象 = Wed Aug 17 2016 00:00:00 GMT-0500,我的浏览器会自动减去时区偏移量 (5hrs) 以获得我的本地时间。因此,如果我尝试获取 2016 年 8 月 16 日星期三 19:00:00 GMT-0500 的时间。这会导致很多问题。有很多库肯定会让这更容易,但我想分享纯 JS 方法。
有关更多信息,请查看:http ://praveenlobo.com/blog/how-to-convert-javascript-local-date-to-utc-and-utc-to-local-date/我在哪里得到了我的灵感。
希望这可以帮助!
var userdate = new Date("2009-1-1T8:00:00Z");
var timezone = userdate.getTimezoneOffset();
var serverdate = new Date(userdate.setMinutes(userdate.getMinutes()+parseInt(timezone)));
这将为您提供正确的 UTC 日期和时间。
这是因为getTimezoneOffset()
它将以分钟为单位为您提供时区差异。我建议您不要使用toISOString()
,因为输出将在字符串中因此将来您将无法操纵日期
使用 moment 包,您可以轻松地将 UTC 日期字符串转换为新的 Date 对象:
const moment = require('moment');
let b = new Date(moment.utc('2014-02-20 00:00:00.000000'));
let utc = b.toUTCString();
b.getTime();
当您的服务器不支持时区并且您希望始终将 UTC 日期存储在服务器中并将其作为新的 Date 对象取回时,这特别有用。上面的代码适用于我对该线程所针对的类似问题的要求。在这里分享,以便可以帮助其他人。我在任何答案中都没有看到上述解决方案。谢谢。
我知道这个问题很老,但正在研究同样的问题,一种选择是将 date.valueOf() 发送到服务器。javascript Date 的 valueOf() 函数发送自 UTC 1970 年 1 月 1 日午夜以来的毫秒数。
您可以使用以下方法将任何 js 日期转换为 UTC:
let date = new Date(YOUR_DATE).toISOString()
// It would give the date in format "2020-06-16T12:30:00.000Z" where Part before T is date in YYYY-MM-DD format, part after T is time in format HH:MM:SS and Z stands for UTC - Zero hour offset
到目前为止,我发现获取 GMT 时间的最佳方法是首先获取您的本地日期时间。然后转换为 GMT 字符串。然后使用字符串通过删除时区来构建新时间。
let dtLocal = new Date()
let dt = new Date(dtLocal.toISOString().split('Z')[0])
注意: - 它将在 GMT 中创建新的日期时间。但这将是本地日期时间,因为时区将附加到它上面。
据我观察,
var timeUtc = new Date();
timeUtc将始终具有 UTC 时间,但如果您调试或控制台,浏览器将始终按照当前时区显示时间。
如果您将timeUtc作为参数发送到任何发布请求,则在 chrome 的网络选项卡中,您可以检查发布数据,您将看到timeUtc将具有 UTC 时间。
所以这就是我必须这样做的方式,因为我仍然想要一个 JavaScript 日期对象作为日期来操作,不幸的是,很多这些答案都需要你去一个字符串。
//First i had a string called stringDateVar that i needed to convert to Date
var newDate = new Date(stringDateVar)
//output: 2019-01-07T04:00:00.000Z
//I needed it 2019-01-07T00:00:00.000Z because i had other logic that was dependent on that
var correctDate = new Date(newDate.setUTCHours(0))
//This will output 2019-01-07T00:00:00.000Z on everything which allows scalability
const event = new Date();
console.log(event.toUTCString());
更简单
myvar.setTime(myvar.getTime() + myvar.getTimezoneOffset() * 60000);