193

我想在 JavaScript 中解析没有时区的日期。我试过了:

new Date(Date.parse("2005-07-08T00:00:00+0000"));

返回Fri Jul 08 2005 02:00:00 GMT+0200(中欧夏令时间):

new Date(Date.parse("2005-07-08 00:00:00 GMT+0000"));

返回相同的结果并且:

new Date(Date.parse("2005-07-08 00:00:00 GMT-0000"));

也返回相同的结果。

我想解析时间:

  1. 没有时区。
  2. 无需调用构造函数Date.UTC或 new Date(year, month, day)
  3. 通过简单地将字符串传递给 Date 构造函数(没有原型方法)。

我必须生成一个日期对象,而不是字符串。

4

15 回答 15

158

我有同样的问题。我得到一个日期作为字符串,例如:'2016-08-25T00:00:00',但我需要有正确时间的 Date 对象。要将字符串转换为对象,我使用 getTimezoneOffset:

var date = new Date('2016-08-25T00:00:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);

getTimezoneOffset()将返回以太负值或正值。必须减去它才能在世界上的每个位置工作。

于 2016-08-29T15:25:34.317 回答
143

日期已正确解析,只是toString将其转换为您的本地时区:

let s = "2005-07-08T11:22:33+0000";
let d = new Date(Date.parse(s));

// this logs for me 
// "Fri Jul 08 2005 13:22:33 GMT+0200 (Central European Summer Time)" 
// and something else for you

console.log(d.toString()) 

// this logs
// Fri, 08 Jul 2005 11:22:33 GMT
// for everyone

console.log(d.toUTCString())

Javascript Date 对象是时间戳 - 它们仅包含自纪元以来的毫秒数。Date 对象中没有时区信息。这个时间戳代表哪个日历日期(天、分、秒)取决于解释(to...String方法之一)。

上面的示例显示日期被正确解析 - 也就是说,它实际上包含与 GMT 中的“2005-07-08T11:22:33”相对应的毫秒数。

于 2013-07-09T10:26:26.583 回答
17

我遇到了同样的问题,然后想起了一些关于我正在从事的遗留项目以及他们如何处理这个问题的事情。我当时不明白,也没有真正在意,直到我自己遇到了问题

var date = '2014-01-02T00:00:00.000Z'
date = date.substring(0,10).split('-')
date = date[1] + '-' + date[2] + '-' + date[0]

new Date(date) #Thu Jan 02 2014 00:00:00 GMT-0600

无论出于何种原因,将日期传递为“01-02-2014”都会将时区设置为零并忽略用户的时区。这可能是 Date 类中的一个侥幸,但它存在于前一段时间并存在于今天。它似乎可以跨浏览器工作。自己试试吧。

这段代码是在一个全球项目中实现的,其中时区很重要,但查看日期的人并不关心它被引入的确切时间。

于 2015-01-04T18:17:46.340 回答
8

由于在显示日期时确实是一个格式问题(例如以当地时间显示),我喜欢使用 new(ish)Intl.DateTimeFormat对象来执行格式设置,因为它更明确并提供更多输出选项:

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };

const dateFormatter = new Intl.DateTimeFormat('en-US', dateOptions);
const dateAsFormattedString = dateFormatter.format(new Date('2019-06-01T00:00:00.000+00:00'));

console.log(dateAsFormattedString) // "June 1, 2019"

如图所示,通过将 设置timeZone为“UTC”,它不会执行本地转换。作为奖励,它还允许您创建更精美的输出。您可以在Mozilla - Intl.DateTimeFormat中阅读有关该Intl.DateTimeFormat对象的更多信息。

无需创建新Intl.DateTimeFormat对象即可实现相同的功能。只需将语言环境和日期选项直接传递到toLocaleDateString()函数中。

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };
const myDate = new Date('2019-06-01T00:00:00.000+00:00');
myDate.toLocaleDateString('en-US', dateOptions); // "June 1, 2019"
于 2020-03-30T13:37:59.530 回答
6

无论如何,Date对象本身都会包含时区,返回的结果是以默认方式将其转换为字符串的效果。即你不能创建没有时区的日期对象。但是您可以做的是Date通过创建自己的对象来模仿对象的行为。但是,最好将其交给诸如moment.js 之类的库。

于 2013-07-09T10:25:27.797 回答
6

我找到了JavaScript 日期对象和时区 | 修复YouTube 上的“关闭 1 天”错误。这修复/重置了本地时区的偏移量。视频中有一个很好的解释这个问题。

// date as YYYY-MM-DDT00:00:00Z

let dateFormat = new Date(date)

// Methods on Date Object will convert from UTC to users timezone
// Set minutes to current minutes (UTC) + User local time UTC offset

dateFormat.setMinutes(dateFormat.getMinutes() + dateFormat.getTimezoneOffset())

// Now we can use methods on the date obj without the timezone conversion

let dateStr = dateFormat.toDateString();

于 2021-05-19T08:24:21.433 回答
5

JavaScript 中的日期只是在内部保持简单,因此日期时间数据存储在 UTC Unix 纪元(毫秒或毫秒)中。

如果您想拥有一个在地球上的任何时区都不会改变的“固定”时间,您可以调整 UTC 时间以匹配您当前的本地时区并保存它。并且在检索它时,无论您在哪个本地时区,它都会根据保存它的时间显示调整后的 UTC 时间,然后添加本地时区偏移量以获得“固定”时间。

保存日期(以毫秒为单位):

toUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC - offset; // UTC - OFFSET
}

检索/显示日期(以毫秒为单位):

fromUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC + offset; // UTC + OFFSET
}

那么你也能:

const saveTime = new Date(toUTC(Date.parse("2005-07-08T00:00:00+0000")));
// SEND TO DB....

// FROM DB...
const showTime = new Date(fromUTC(saveTime));
于 2020-03-23T10:43:51.390 回答
4

您可以使用此代码

var stringDate = "2005-07-08T00:00:00+0000";
var dTimezone = new Date();
var offset = dTimezone.getTimezoneOffset() / 60;
var date = new Date(Date.parse(stringDate));
date.setHours(date.getHours() + offset);
于 2019-09-10T15:58:36.933 回答
4

这是一个简单的解决方案:

const handler1 = {
  construct(target, args) {
    let newDate = new target(...args);
    var tzDifference = newDate.getTimezoneOffset();
    return new target(newDate.getTime() + tzDifference * 60 * 1000);
  }
};

Date = new Proxy(Date, handler1);
于 2018-03-07T16:11:35.027 回答
3

该解决方案与@wawka 的解决方案几乎相同,但是它使用以下方式处理带有加号和减号的不同时区Math.abs

const date = new Date("2021-05-24T22:00:18.512Z")
const userTimezoneOffset = Math.abs(date.getTimezoneOffset() * 60000);
new Date(date.getTime() - userTimezoneOffset);
于 2021-05-28T15:49:20.997 回答
1

就像一般注释一样,Mozilla 的“日期”显示了一种保持其灵活性的方法。

我们可以使用getMinutes(),但它在前 9 分钟只返回一个数字。

let epoch = new Date() // Or any unix timestamp

let za = new Date(epoch),
    zaR = za.getUTCFullYear(),
    zaMth = za.getUTCMonth(),
    zaDs = za.getUTCDate(),
    zaTm = za.toTimeString().substr(0,5);

console.log(zaR +"-" + zaMth + "-" + zaDs, zaTm)

Date.prototype.getDate()
    Returns the day of the month (1-31) for the specified date according to local time.
Date.prototype.getDay()
    Returns the day of the week (0-6) for the specified date according to local time.
Date.prototype.getFullYear()
    Returns the year (4 digits for 4-digit years) of the specified date according to local time.
Date.prototype.getHours()
    Returns the hour (0-23) in the specified date according to local time.
Date.prototype.getMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to local time.
Date.prototype.getMinutes()
    Returns the minutes (0-59) in the specified date according to local time.
Date.prototype.getMonth()
    Returns the month (0-11) in the specified date according to local time.
Date.prototype.getSeconds()
    Returns the seconds (0-59) in the specified date according to local time.
Date.prototype.getTime()
    Returns the numeric value of the specified date as the number of milliseconds since January 1, 1970, 00:00:00 UTC (negative for prior times).
Date.prototype.getTimezoneOffset()
    Returns the time-zone offset in minutes for the current locale.
Date.prototype.getUTCDate()
    Returns the day (date) of the month (1-31) in the specified date according to universal time.
Date.prototype.getUTCDay()
    Returns the day of the week (0-6) in the specified date according to universal time.
Date.prototype.getUTCFullYear()
    Returns the year (4 digits for 4-digit years) in the specified date according to universal time.
Date.prototype.getUTCHours()
    Returns the hours (0-23) in the specified date according to universal time.
Date.prototype.getUTCMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to universal time.
Date.prototype.getUTCMinutes()
    Returns the minutes (0-59) in the specified date according to universal time.
Date.prototype.getUTCMonth()
    Returns the month (0-11) in the specified date according to universal time.
Date.prototype.getUTCSeconds()
    Returns the seconds (0-59) in the specified date according to universal time.
Date.prototype.getYear()
    Returns the year (usually 2-3 digits) in the specified date according to local time. Use getFullYear() instead. 
于 2018-11-13T18:49:21.513 回答
0

我个人更喜欢@wawka 的答案,但是,我也想出了一个不太干净的技巧来解决这个问题,如果您确定要转换的字符串的格式,它更简单并且可以工作。

看下面的代码片段:

var dateString = '2021-08-02T00:00:00'

var dateObj = new Date(dateString + 'Z')
console.log("No Timezone manipulation: ", dateObj)

var dateObjWithTZ = new Date(dateString)
console.log("Normal conversion: ", dateObjWithTZ)

这在这种情况下有效,因为在日期时间字符串的末尾添加 Z 将使 JS 将此字符串视为 UTC 日期字符串,因此不会为其添加时区差异。

于 2021-08-03T02:28:04.883 回答
-1

这是我为这个问题提出的解决方案,它对我有用。


使用的库:momentjs 和普通的 javascript Date 类。

Step 1. 将String日期转换为moment对象(PS:只要toDate()不调用方法,moment就会保留原来的日期和时间):

const dateMoment = moment("2005-07-08T11:22:33+0000");

步骤 2.从先前创建的时刻对象中提取hours和值:minutes

  const hours = dateMoment.hours();
  const mins = dateMoment.minutes();

步骤 3. 将时刻转换为日期(PS:这将根据您的浏览器/机器的时区更改原始日期,但不要担心并阅读步骤 4。):

  const dateObj = dateMoment.toDate();

步骤 4. 手动设置在步骤 2 中提取的小时和分钟。

  dateObj.setHours(hours);
  dateObj.setMinutes(mins);

第 5 步 dateObj现在将显示原始日期,没有任何时区差异。即使是夏令时更改也不会对日期对象产生任何影响,因为我们手动设置了原始小时和分钟。

希望这可以帮助。

于 2018-11-13T18:17:22.243 回答
-2

(new Date().toString()).replace(/ \w+-\d+ \(.*\)$/,"")

这将有输出:Tue Jul 10 2018 19:07:11

(new Date("2005-07-08T11:22:33+0000").toString()).replace(/ \w+-\d+ \(.*\)$/,"")

这将有输出:Fri Jul 08 2005 04:22:33

注意:返回的时间将取决于您当地的时区

于 2018-07-11T02:07:37.757 回答
-7

日期解析存在一些固有问题,遗憾的是默认情况下没有很好地解决这些问题。

- 人类可读的日期中包含隐含的时区
- 网络上有许多广泛使用的日期格式是模棱两可的

为了简单而干净地解决这些问题,需要一个这样的函数:

>parse(whateverDateTimeString,expectedDatePattern,timezone)
"unix time in milliseconds"

我已经搜索过这个,但没有找到类似的东西!

所以我创建了: https ://github.com/zsoltszabo/timestamp-grabber

享受!

于 2014-02-20T00:01:42.503 回答