如何将JavaScript日期转换为UTC?

dth*_*her 540 javascript date utc

假设您网站的用户输入了日期范围.

2009-1-1 to 2009-1-3
Run Code Online (Sandbox Code Playgroud)

您需要将此日期发送到服务器进行某些处理,但服务器希望所有日期和时间都是UTC.

现在假设用户在阿拉斯加或夏威夷或斐济.由于它们处于与UTC完全不同的时区,因此需要将日期范围转换为如下所示:

2009-1-1T8:00:00 to 2009-1-4T7:59:59
Run Code Online (Sandbox Code Playgroud)

使用JavaScript Date对象,您如何将第一个"本地化"日期范围转换为服务器将理解的内容?

Dru*_*der 539

简单而愚蠢

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);
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢你的想法,并做了一个我多次使用的方法.`function convertDateToUTC(date){return new Date(date.getUTCFullYear(),date.getUTCMonth(),date.getUTCDate(),date.getUTCHours(),date.getUTCMinutes(),date.getUTCSeconds()); }` (83认同)
  • 我不会用这个 - 通过使用新的Date()你可以获得浏览器的时区.在Chrome 29和IE10中,日期+时间似乎是正确的,但时区设置为浏览器的时区,这可能会导致问题...... (21认同)
  • 我想出的获得UTC日期和时间的最短代码是砍掉时区:`new Date(new Date().toUTCString().substr(0,25))` (20认同)
  • 这是无稽之谈.新日期的价值将与您实际需要的价值不同.只需使用`now.toUTCSTring()`而不是(错误的)`now_utc.toString()`. (19认同)
  • 请注意,getUTCMonth()返回值0到11.因此,如果您需要按月号而不是字符串,则有助于+1值. (15认同)
  • 这将在当前时区创建一个新日期,其中包含UTC的日期和时间值.所以它不再代表同一时刻. (6认同)
  • 这是行不通的.新的`Date`对象仍然根据用户的时区设置偏移量. (5认同)
  • 对我来说,这创建了一个**显示为UTC**时间的日期,但**实际上不是UTC**时间.更多信息在我的答案如下:http://stackoverflow.com/questions/948532/how-do-you-convert-a-javascript-date-to-utc/14610512#14610512 (4认同)
  • `now_utc` 与 `date.getTime()` 具有相同的值(除了忽略 date.getUTCMilliseconds() 导致的毫秒差异)。这怎么算是正确答案呢? (3认同)
  • 这个答案演示了“纪元转换”的一种实现,这种实现单独来看是危险的,因为它可能会在 DST 转换等边缘情况附近失败。不建议。 (2认同)
  • 多年来,这个答案已被黑客攻击,毫无用处。它制作了同一日期的 3 个副本,本质上与:`var date = new Date(); var now_utc = 新日期(日期); 返回新的日期(日期)`。 (2认同)

Wil*_*ern 345

toISOString()方法以简化的扩展ISO格式(ISO 8601)返回一个字符串,该字符串总是24或27个字符长(YYYY-MM-DDTHH:mm:ss.sssZ±YYYYYY-MM-DDTHH:mm:ss.sssZ分别).时区始终为零UTC偏移,由后缀" Z"表示.

资料来源: MDN网络文档

您需要的格式是使用该.toISOString()方法创建的.对于本身不支持此方法的旧浏览器(ie8及以下),可在此处找到垫片:

这将使您能够做您需要的事情:

var isoDate = new Date('yourdatehere').toISOString();
Run Code Online (Sandbox Code Playgroud)

对于Timezone工作,moment.js和moment.js时区是非常宝贵的工具......尤其适用于在客户端和服务器javascript之间导航时区.

  • 实际上这将日期对象转换为字符串,将无法对其进行进一步的日期操作 (65认同)
  • @Will,你是完全正确的,但是 - 就像我在这里假设的大多数观众一样 - 我根据标题到达这里,搜索一般的JS日期转换为UTC,所以我认为在这里提一下它是有用的:) (26认同)
  • 使用这种方法时要小心!它不会创建UTC日期 - 它将现有日期数据按原样格式化为UTC格式并为其提供"Z"时区.99%的时间这是错误的!在使用此方法之前,您必须将日期转换为GMT时区! (3认同)
  • @ user1944491我认为这是不正确的。根据MDN文档,`toISOString`确实可以正确转换为UTC`[toISOString]返回简化的扩展ISO格式的字符串...时区始终为零UTC偏移量'在此示例中,它们还显示了toISOString时的偏移量叫做 (3认同)
  • MomentJS 并不是无价的,它是一大堆可怕的代码。易于使用,不是最完整的,而是一个臃肿的猪,如果没有 hack,它甚至无法与几个现代框架一起使用。但是它太臃肿了,使用它没有意义。 (3认同)
  • @TheRebel,给出的用例是他需要向服务器发送格式化的字符串。 (2认同)
  • @orszaczky——这个评论毫无意义。*Date* 实例不会“转换”为任何内容,*toISOString* 返回一个 UTC 时间戳,表示完全相同的时间**可以发送到服务器**,这是 OP 的要求。原始 *Date* 对象保持不变。 (2认同)

Gra*_*ble 188

这是我的方法:

var now = new Date();
var utc = new Date(now.getTime() + now.getTimezoneOffset() * 60000);
Run Code Online (Sandbox Code Playgroud)

生成的utc对象实际上不是UTC日期,而是移动了一个本地日期以匹配UTC时间(请参阅注释).但是,在实践中它完成了这项工作.

  • 添加60000*Date.getTimezoneOffset()是不正确的!首先,您必须将所有日期/时间视为UTC,并使用时区修改器进行显示.浏览器可能不同,但Date.getTime()返回自1970-01-01以来的毫秒数.如果使用此数字创建新日期,例如:new Date(Date.getTime()); 它*将是UTC*,但是当你显示它时(例如:通过chrome dev工具控制台),它将显示为你当地的时区. (14认同)
  • 在我的浏览器中,这会创建一个非UTC的DateTime.但是,当我在浏览器中显示时,如果忽略时区信息,则会在我的本地时区显示一个正确的UTC时间的DateTime. (14认同)
  • 这个答案展示了另一种常见的"时代转换"实现方式,这种方法在隔离方面很危险,因为它可能会在DST转换等边缘情况附近失败.不建议. (3认同)

ken*_*bec 24

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(':');    
}
Run Code Online (Sandbox Code Playgroud)


Rol*_*sta 23

转换为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
Run Code Online (Sandbox Code Playgroud)

转换为ISO,日期/时间更改(日期/时间将更改)

isoDate = new Date(now).toISOString();
//OUTPUT : 2015-02-20T13:59:31.238Z 
Run Code Online (Sandbox Code Playgroud)

小提琴链接

  • @RollerCosta 请在您的答案中提及,减去/添加 `now.getTimezoneOffset()` 取决于用户(浏览器)的时区是在 UTC 之前还是之后。 (2认同)

Aar*_*man 18

浏览器可能会有所不同,您还应该记住不信任客户端生成的任何信息,如上所述,以下声明适用于我(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

  • 如果未提供参数,则构造函数会根据系统设置为当前日期和时间创建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()),如果忽略时区信息,它会在我的本地时区显示一个正确的UTC时间.

  • 我刚刚在Fx和Chrome上运行此代码,它似乎不起作用:结果与`new Date()`完全相同,时间戳和时区都没有改变 (11认同)
  • 据我所知,`new Date(new Date().getTime())`返回与`new Date()`完全相同的值.你可以解释一下你的答案在什么意义上提供了来自`new Date()`的独特价值? (7认同)
  • 那是因为时间戳是无时区的.`new Date().getTime()`将始终返回与时区无关的时间戳.除非您尝试将其格式化为自Unix时代以来毫秒数以外的其他内容,否则没有与之关联的时间戳. (3认同)

Jam*_*ore 15

var myDate = new Date(); // Set this to your date in whichever timezone.
var utcDate = myDate.toUTCString();
Run Code Online (Sandbox Code Playgroud)

  • 现在返回"Thu,2009年6月4日04:10:56 GMT",这不是OP中要求的ISO格式. (5认同)
  • 这将它变成一个字符串,这不是一个日期 (4认同)
  • 不,实际上它应该是根据OP的日期的字符串表示. (2认同)
  • 转换为UTC后,它以字符串格式返回,然后如何访问getMonth(),getDate()等方法. (2认同)

pie*_*e6k 14

无论客户端设置什么时区,我的解决方案都会使日期保持不变。也许有人会发现它很有用。

我的用例:

我正在创建一个待办事项应用程序,您可以在其中设置任务日期。无论您在哪个时区,此日期都应保持不变。

例子。你想在 6 月 25 日早上 8 点给你的朋友打电话。

您在中国的 5 天前(6 月 20 日)创建了此任务。

然后,在同一天,您飞往纽约几天。

然后在 6 月 25 日,当你还在纽约的时候,你在早上 7:30 醒来(这意味着你应该在 30 分钟内收到任务通知(即使在你创建任务时所在的中国已经是下午 1: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(),
  );
}
Run Code Online (Sandbox Code Playgroud)

然后,我保存/读取这个日期,如:

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
}
Run Code Online (Sandbox Code Playgroud)


CMc*_*ont 8

转换为UTC并将其保留为日期对象的另一种解决方案:(它的工作原理是从格式化字符串的末尾删除'GMT'部分,然后将其放回Date构造函数中)

var now = new Date();
var now_utc = new Date(now.toUTCString().slice(0, -4));
Run Code Online (Sandbox Code Playgroud)

我需要这样做才能与日期时间选择器库连接.但总的来说,以这种方式处理日期是个坏主意.

用户通常希望在本地时间使用日期时间,因此您要么更新服务器端代码以正确解析具有偏移的日期时间字符串,然后转换为UTC(最佳选项),或者在发送到UTC之前转换为UTC字符串客户端.服务器(如Will Stern的答案)


nic*_*ckf 7

您是否尝试将日期转换为类似的字符串?

我会做一个功能,虽然它有点争议,但将它添加到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
    ;
};
Run Code Online (Sandbox Code Playgroud)

如果你需要它在UTC时间,只需用getUTC*替换所有get*函数,例如:getUTCFullYear,getUTCMonth,getUTCHours ...然后只在末尾添加"+00:00"而不是用户的时区偏移量.


jco*_*ctx 7

date = '2012-07-28'; stringdate = new Date(date).toISOString();
Run Code Online (Sandbox Code Playgroud)

应该适用于大多数较新的浏览器.它2012-07-28T00:00:00.000Z在Firefox 6.0上返回


Tim*_*lez 7

处理日期时我的建议是将日期解析为用户输入的各个字段.你可以将它用作一个完整的字符串,但你正在玩火.

JavaScript可以以不同的格式处理两个相同的日期.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse

永远不要做任何事情:

new Date('date as text');
Run Code Online (Sandbox Code Playgroud)

将日期从用户输入解析为其各个字段后,创建日期对象.创建日期对象后,通过添加时区偏移将其转换为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);
Run Code Online (Sandbox Code Playgroud)

现在,您可以在UTC时间内将日期传递给服务器.我强烈建议不要使用任何日期字符串.将其传递给服务器,细分为您需要的最低粒度,例如年,月,日,分钟或者作为unix时代的毫秒值.


Ada*_*ani 6

如果你正在处理很多日期,那么值得使用moment.js(http://momentjs.com).转换为UTC的方法是:

moment(yourTime).utc()
Run Code Online (Sandbox Code Playgroud)

您可以使用格式将日期更改为您想要的任何格式:

moment(yourTime).utc().format("YYYY-MM-DD")
Run Code Online (Sandbox Code Playgroud)

目前还有偏移选项,但还有一个额外的补充库来处理时区(http://momentjs.com/timezone/).时间转换就像这样简单:

moment.tz(yourUTCTime, "America/New_York")
Run Code Online (Sandbox Code Playgroud)

  • 从文档中可能值得注意......“我们现在通常认为 Moment 是处于维护模式的遗留项目。它没有死,但确实已经完成了。有关替代建议,请参阅[此处](https://momentjs.com/docs/#/-project-status/recommendations/)。 (2认同)

dth*_*her 5

我刚刚发现 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'); 
Run Code Online (Sandbox Code Playgroud)

  • 这似乎不是您问题的最佳答案。您应该重新考虑直接回答您的问题的内容或以不同的方式提出您的问题。 (10认同)

Bri*_*lis 5

我发现jQuery Globalization Plugin日期解析效果最好。其他方法存在跨浏览器问题,并且诸如 date.js 之类的东西已经有一段时间没有更新了。

您也不需要页面上的 datePicker。您可以调用类似于文档中给出的示例的内容:

$.parseDate('yy-mm-dd', '2007-01-26');
Run Code Online (Sandbox Code Playgroud)


Yak*_*ein 5

使用moment.js UTC 方法

const moment = require('moment');
const utc = moment.utc(new Date(string));
Run Code Online (Sandbox Code Playgroud)


Ali*_*taf 5

\n

getTimezoneOffset ()方法返回当前区域设置(主机系统设置)与 UTC 之间的时区差异(以分钟为单位)。

\n
\n

来源:MDN 网络文档

\n

这意味着如果本地时区晚于 UTC,则偏移量为正;如果本地时区早于 UTC,则偏移量为负。例如,对于时区UTC+02:00,将返回-120 。

\n

\r\n
\r\n
let d = new Date();\nconsole.log(d);\nd.setTime(d.getTime() + (d.getTimezoneOffset() * 60000));\nconsole.log(d);
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

注意:这会将日期对象时间转换为UTC\xc2\xb100:00并且不转换其时区,因此日期对象时区仍将相同,但值将在UTC\xc2\xb100:00中。

\n


I a*_*m L 5

对于其他人的目标是将其作为“日期对象”而不是字符串,并且您只想显示没有 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.setYear(year);
tomorrowUTC.setMonth(month);
tomorrowUTC.setDate(day + 1); // +1 because my logic is to get "tomorrow"
tomorrowUTC.Hours(hour);

// then use the tomorrowUTC for to display/format it
// tomorrowUTC is a "Date" and not a string.
Run Code Online (Sandbox Code Playgroud)

然后你可以做类似的事情:

We will delete your account at ${format(tomorrowUTC, 'EEEE do MMMM hh:mmaaa')} UTC

format是一个date-fns函数,如果你愿意,你可以使用其他库);

这有点“hacky”,因为它仍然使用您当地的时区,但如果您只想显示日期而不是时区,那么这可以工作。