【问题标题】:Parse date without timezone javascript解析没有时区javascript的日期
【发布时间】:2013-07-06 21:51:59
【问题描述】:

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

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

返回 2005 年 7 月 8 日星期五 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. 我必须生成 Date 对象,而不是 String

【问题讨论】:

  • 您可以省略Date.parse btw 直接将字符串传递给Date 构造函数。
  • 我不确定你为什么需要这个,但我很确定 Date 总是有用户的本地时区。如果您希望您的 JavaScript 与其他时区一起工作,而不是必须为 Date 使用包装器对象,也许这对您有用:github.com/mde/timezone-js
  • 不幸的是,我不得不复制 Date 对象以获得正确的对象来比较 MongoDB 中的日期:new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate())
  • 如果要解析没有时间的日期,则需要指定要假设的时区,因为“2005-07-08”在不同的时区表示不同的东西。截至 2020 年 5 月,由于实现上的差异,MDN 文档建议不要使用任何内置的日期解析功能。但是,使用 Date.parse("2005-07-08") 可能会返回 00:00 UTC 的时间。另一方面,date-fns parse,在解析相同的日期字符串时将返回本地时间 00:00

标签: javascript date timestamp-with-timezone


【解决方案1】:

我也有同样的问题。我得到一个日期作为字符串,例如:'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() 将返回以太负值或正值。必须减去它才能在世界上的每个位置工作。

【讨论】:

  • 我有同样的问题,发现这很有帮助。但是,我发现由于夏令时,这不能处理时区偏移。示例:我在 PST,因此我当前与 GMT 的偏移量(3 月)为 -8:00,但 5 月为 -7:00。我的解决方案是计算var userTimezoneOffset = date.getTimezoneOffset()*60000;
  • 除非我是个十足的白痴,否则这实际上会返回错误的时间。 getTimezoneOffset() 返回与您认为相反方向的分钟数——我的时区现在是 UTC-4,但 getTimezoneOffset() 返回正数 240。因此应该从 date.getTime() 中减去 userTimezoneOffset,而不是添加给它。
  • 我同意@vaindil 你应该减去。 wakwa 的解决方案仅在您是格林威治的正确一方时才有效。 Wakwas 应该纠正它。
  • @vaindil 现在结果与new Date('2016-08-25T00:00:00Z') 相同,我认为关键是要操纵new Date('2016-08-25T00:00:00Z'),以便本地时间显示为时间0:00,但此代码错过了Z跨度>
  • 应该是new Date(date.getTime() + userTimezoneOffset);,因为-会影响UTC之前的时区。
【解决方案2】:

日期被正确解析,只是 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 方法之一)。

上面的例子表明日期被正确解析了——也就是说,它实际上包含了对应于格林威治标准时间“2005-07-08T11:22:33”的毫秒数。

【讨论】:

  • 不幸的是,我必须生成 Date 对象,而不是 String。
  • @Athlan:添加了一些解释。
  • 我已经检查过了。我已将解析后的日期传递给 MongoDB 查询 new Date(Date.parse("2005-07-08T11:22:33+0000")),并通过构造函数复制日期:new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate())。两种解决方案,不同的结果,第二次正确!你的回复很有用,刚刚在hunlock.com/blogs/Javascript_Dates-The_Complete_Reference中提到。向上。
  • 对我来说非常有效 - .toUTCString() 是让我从原始给定字符串返回正确时间的票。即 new Date("2016-08-22T19:45:00.0000000").toUTCString()
  • JavaScript 日期和时间中万恶之源包含在您的第一句话中...只是 toString 将其转换为您当地的时区...这其中的单一责任在哪里? toString 方法应该只是对结果进行字符串化而不是对其进行转换。如果我想转换日期,我应该有其他方法来做到这一点。
【解决方案3】:

我遇到了同样的问题,然后想起了我正在从事的一个遗留项目以及他们如何处理这个问题的一些奇怪之处。我当时不明白,直到我自己遇到问题才真正关心它

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 类中的一个侥幸,但它存在于前一段时间并存在于今天。它似乎可以跨浏览器工作。自己试试吧。

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

【讨论】:

  • 我认为这是故意的,因为“Z”指定了 JS 然后转换的 UTC,但是没有时区它不能转换它,所以它基本上假定用户的时区。不过希望得到一些确认或更好的解释。
  • 这种不稳定的行为是由于破折号造成的。 Chrome、Firefox 和 IE11 都将 2014/5/312014/05/31 解释为 Sat May 31 2014 00:00:00 GMT-0600(山地夏令时间)`(MDT 是我当前的时区)。使用破折号...所有浏览器将 2014-05-31 解释为 Fri May 30 2014 18:00:00 GMT-0600(山地夏令时间)。奇怪的是,使用2014-5-31,Chrome 返回星期六,Firefox 返回星期五,IE11 说日期无效。似乎date.replace('-','/') 可以解决问题。
  • @atheaos 我今天尝试了这个,因为我遇到了这个问题 - 完全修复了它!这可以是一个答案并投票给一些人看吗?
  • 这里也一样!这个答案救了我!应该是公认的答案!
【解决方案4】:

由于在显示日期时确实是一个格式问题(例如以当地时间显示),我喜欢使用 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');
today.toLocaleDateString('en-US', dateOptions); // "June 1, 2019"

【讨论】:

  • 拯救了我的一天。这是一种非常干净的方式来传播时间标签,因为它们没有时区修改。它还解决了由于夏令时导致的时间切换问题,这将与当前的 GMT/本地时间时间偏移补偿相结合。
【解决方案5】:

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

【讨论】:

  • 不幸的是,我必须生成 Date 对象,而不是 String。
【解决方案6】:

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));

【讨论】:

    【解决方案7】:

    在 youtube 上找到了这个解决方案,感谢 Maker At Playing Code https://www.youtube.com/watch?v=oKFb2Us9kmg

    这会修复/重置本地时区的偏移量。视频中很好地解释了这个问题。

    // 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();

    【讨论】:

      【解决方案8】:

      简单的解决方案

      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);
      

      【讨论】:

        【解决方案9】:

        您可以使用此代码

        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);
        

        【讨论】:

        • 我认为这不考虑夏令时
        【解决方案10】:

        解决方案与@wawka's 几乎相同,但它使用Math.abs 处理不同时区的正负号:

        const date = new Date("2021-05-24T22:00:18.512Z")
        const userTimezoneOffset = Math.abs(date.getTimezoneOffset() * 60000);
        new Date(date.getTime() - userTimezoneOffset);
        

        【讨论】:

          【解决方案11】:

          只是一个通用的注释。一种保持灵活性的方法。

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

          我们可以使用 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. 
          

          【讨论】:

            【解决方案12】:

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


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

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

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

            第 2 步。 从之前创建的 moment 对象中提取 hoursminutes 值:

              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 现在将显示原始日期,没有任何时区差异。即使是夏令时更改也不会对日期对象产生任何影响,因为我们是手动设置原始小时和分钟。

            希望这会有所帮助。

            【讨论】:

              【解决方案13】:

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

              看下面的代码sn-p:

              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 日期字符串,因此不会为其添加时区差异。

              【讨论】:

                【解决方案14】:

                (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

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

                【讨论】:

                  【解决方案15】:

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

                  -人类可读的日期中有隐含的时区
                  - 网络上有许多广泛使用的日期格式不明确

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

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

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

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

                  享受吧!

                  【讨论】:

                    猜你喜欢
                    • 2012-11-03
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-02-19
                    • 1970-01-01
                    • 2020-07-15
                    • 2012-05-19
                    • 1970-01-01
                    相关资源
                    最近更新 更多