【问题标题】:Javascript date 01/01/0001Javascript 日期 01/01/0001
【发布时间】:2015-04-30 12:44:37
【问题描述】:

我想在 javascript 中创建一个 Date 对象,它代表 0001 年,2014 年前。

我试过了

d = new Date(); d.setYear(1);
console.log(d);

但它给出了 1901 年

d = new Date(1,1,1)
console.log(d);

没办法。

如何创建这个日期?

【问题讨论】:

    标签: javascript date datetime


    【解决方案1】:

    首先,这根本不是千年虫问题!(更新:在某些情况下 - 它与千年虫问题有关,但这里不是问题)

    正确答案是您无法可靠地做到这一点。夏令时是否适用于第一年?有多少个闰年?有吗?等等。但是@Daniel 的回答会用到!

    更新: 更不用说@MattJohnson 关于 DST 的帖子了。 DST in year 1, actually JS (ES5 anyway) will lie and use the current DST rule for all years

    所以请不要自欺欺人,认为您可以可靠地处理低于 1970 年的日期。(即使在那个时间范围内,您也会遇到很多问题和惊喜。)

    但如果你真的、真的需要你可以使用new Date('0001-01-01')(ISO 8601 格式)或@Daniel 的方法:

    var d = new Date(); d.setFullYear(1);
    

    但在你使用它之前,请阅读这个......


    在 JS 中创建日期有 4 种方式:

    new Date()
    new Date(milliseconds)
    new Date(dateString)
    new Date(year, month, day, hours, minutes, seconds, milliseconds)
    

    1) new Date() 创建当前日期(在您当地的时区),所以我们暂时不感兴趣。


    2) new Date(number) 创建一个新的日期对象作为零时间加上数字。零时间是 1970 年 1 月 1 日 00:00:00 UTC。

    所以在这种情况下,JS 中的时间从 1970 年开始计算。

    (new Date(0)).toUTCString()
    "Thu, 01 Jan 1970 00:00:00 GMT
    

    如果你使用负数,你可以“退回”到 1970 年之前的时间

    (new Date(-62167219200000)).toUTCString()
    "Sat, 01 Jan 0 00:00:00 GMT"
    -62167219200000             <- milliseconds
    -62167219200000 / 1000
    -62167219200             <- seconds
    -62167219200 / 60
    -1036120320             <- minutes
    -1036120320 / 60
    -17268672             <- hours
    -17268672 / 24
    -719528             <- days
    -719528 / 365
    -1971.309589041096 <- years ( this is roughly calculated value )
    

    问题在于它不可靠。有多少个闰年?有吗?夏令时?等等。我不喜欢它,因为这个神奇的数字 -62167219200000


    3) new Date(dateString) 这是最“可靠”的方式。 DateString - 表示 RFC2822 或 ISO 8601 日期的字符串。

    RFC2822 / IETF 日期语法(RFC2822 第 3.3 节),例如“格林威治标准时间 1995 年 12 月 25 日星期一 13:30:00”

    它的问题是,如果你使用负数,你会在所有方法的结果中得到一个不正确的 NaN 日期

    (new Date('01 January -1 00:00:00 UTC')).getFullYear()
    NaN
    

    如果您使用高于或等于 0 且低于 50 的年份,则将自动添加 2000。

    (new Date('01 January 0 00:00:00 UTC')).getFullYear()
    2000
    (new Date('01 January 1 00:00:00 UTC')).getFullYear()
    2001
    (new Date('01 January 10 00:00:00 UTC')).getFullYear()
    2010
    (new Date('01 January 01 00:00:00 UTC')).getFullYear()
    2001
    (new Date('01 January 30 00:00:00 UTC')).getFullYear()
    2030
    (new Date('01 January 49 00:00:00 UTC')).getFullYear()
    2049
    

    如果您使用高于或等于 50 且低于 100 的年份,则将添加 1900。

    (new Date('01 January 50 00:00:00 UTC')).getFullYear()
    1950
    (new Date('01 January 51 00:00:00 UTC')).getFullYear()
    1951
    (new Date('01 January 90 00:00:00 UTC')).getFullYear()
    1990
    (new Date('01 January 99 00:00:00 UTC')).getFullYear()
    1999
    

    等于或大于 100 的年份将获得正确的年份编号

    (new Date('01 January 100 00:00:00 UTC')).getFullYear()
    100
    (new Date('01 January 101 00:00:00 UTC')).getFullYear()
    101
    (new Date('01 January 999 00:00:00 UTC')).getFullYear()
    999
    (new Date('01 January 9999 00:00:00 UTC')).getFullYear()
    9999
    

    因此我们无法使用 RFC2822 / IETF 日期语法创建第 1 年

    关于 ISO 8601:

    http://www.w3.org/TR/NOTE-datetime

    实际格式是

    Year:
          YYYY (eg 1997)
    Year and month:
          YYYY-MM (eg 1997-07)
    Complete date:
          YYYY-MM-DD (eg 1997-07-16)
    Complete date plus hours and minutes:
          YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
    Complete date plus hours, minutes and seconds:
          YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
    Complete date plus hours, minutes, seconds and a decimal fraction of a second
          YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
    

    我们最感兴趣的是“完成日期”

    (new Date('0001-01-01')).toUTCString()
    "Mon, 01 Jan 1 00:00:00 GMT"
    

    雅虎!!! (或者说谷歌更好!:)),我们可以使用 ISO 8601 来创建带有第 1 年的日期

    但要小心,不要尝试使用负数或短年份数字,因为这些解析可能会因本地化或精神错乱而有所不同:)

    (new Date('-0001-01-01')).toUTCString()
    "Sun, 31 Dec 2000 21:00:00 GMT"
    (new Date('01-01-01')).toUTCString()
    "Sun, 31 Dec 2000 21:00:00 GMT"
    (new Date('02-01-01')).toUTCString()
    "Wed, 31 Jan 2001 21:00:00 GMT"
    (new Date('02-01-05')).toUTCString()
    "Mon, 31 Jan 2005 21:00:00 GMT"
    

    4) 新日期(年、月、日、小时、分钟、秒、毫秒)

    要使用这个,您必须传递两个参数(年和月),所有其他参数都是可选的。要小心,因为这里的月份将从 0 到 11 开始,与其他地方不同。笏? o_O

    警告!此日期将在您当前的时区创建!!!所以要小心使用!

    UPD:@matt-johnson 澄清

    ...实际上 Date 对象总是反映本地时区。你不能把它放在另一个时区,即使你用 UTC 时间戳初始化它,它仍然会在大多数函数中反映本地时区。在内部,它通过数字时间戳跟踪 UTC,并且有一些函数显式公开 UTC 值,但其他一切都是本地的。

    负数将被解释为负数

    (new Date(-1, 0)).toString()
    "Fri Jan 01 -1 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    (new Date(-234, 0)).toString()
    "Wed Jan 01 -234 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    

    0到99的数字会自动加1900

    (new Date(0, 0)).toString()
    "Mon Jan 01 1900 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    (new Date(1, 0)).toString()
    "Tue Jan 01 1901 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    (new Date(11, 0)).toString()
    "Sun Jan 01 1911 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    (new Date(50, 0)).toString()
    "Sun Jan 01 1950 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    (new Date(99, 0)).toString()
    "Fri Jan 01 1999 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    

    从 100 到 275760 的数字将被解释为年份数字

    (new Date(100, 0)).toString()
    "Fri Jan 01 100 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    (new Date(102, 0)).toString()
    "Sun Jan 01 102 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    (new Date(2002, 0)).toString()
    "Tue Jan 01 2002 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    

    高于 275760 的数字将是无效日期

    (new Date(275760, 0)).toString()
    "Tue Jan 01 275760 00:00:00 GMT+0300 (Russia TZ 2 Standard Time)"
    (new Date(275761, 0)).toString()
    "Invalid Date"
    

    UPD:

    new Date(Date.UTC(1,1,1)) 与 new Date(year, month, day, hours, minutes, seconds, milliseconds) 一样,不会出现相同的症状。由于 Date.UTC 函数。

    【讨论】:

    • new Date(Date.UTC(1,1,1)) 不会出现与 new Date(年、月、日、小时、分钟、秒、毫秒)相同的症状。由于 Date.UTC 函数...
    • 很好的回应。全面而准确。不过需要澄清一点,当您调用它将在本地时区创建一个日期时 - 实际上 Date 对象 always 反映了本地时区。你不能把它放在另一个时区,即使你用 UTC 时间戳初始化它,它仍然会在大多数函数中反映本地时区。在内部,它通过数字时间戳跟踪 UTC,并且有一些函数显式公开 UTC 值,但其他一切都是本地的。
    • 不,他们不是,或者我们不能确定。当时(或没有)还有其他各种日历系统。 Gregorian calendar 从 1582 年开始慢慢逐步采用。JS(和大多数其他人)使用 ISO-8601 日历,这是一个 proleptic 公历。这意味着它的行为就好像这个日历总是有效,即使我们清楚地知道它不是。换句话说,JavaScript 的“第 1 年”是 我们 年前的 2014 年,但它与当时使用的其他日历上的“第 1 年”不同。
    • 这是你的说法:“一团糟”吗?
    • 这是一个很好的答案,但如果您将这些“更新”整合到一个单一的、流畅的叙述中会更好。
    【解决方案2】:

    使用 setFullYear - 这是 JavaScript 的千年虫问题。

    var d = new Date(); d.setFullYear(1);
    document.write(d);

    【讨论】:

    • 多么复古 :) 也为了怀旧的目的扔了一个 document.write
    • @RGraham 我只是为了剪辑而这样做。
    • 我知道,只是认为它适合 Y2K 问题
    【解决方案3】:

    (已弃用)Date.setYear 方法设置指定日期的年份,但请注意:

    如果 yearValue 是 0 到 99(含)之间的数字,则年份 对于 dateObj 设置为 1900 + yearValue。否则,年为 dateObj 设置为 yearValue。

    var theBigDay = new Date();
    
    theBigDay.setYear(96);   // sets year to 1996
    theBigDay.setYear(1996); // sets year to 1996
    theBigDay.setYear(2000); // sets year to 2000
    

    你应该使用Date.setFullYear 方法。另一种方法已弃用。

    【讨论】:

      【解决方案4】:

      可以使用字符串版本的构造函数:

      console.log(new Date("0001-01-01"));

      【讨论】:

      • 等等,你是不是刚刚从stackoverflow.com/questions/52245886/… 那里偷了 James Aylett 的答案 ;-)
      • @DanielF - 哈哈! (可能听不懂 Daniel 的玩笑的潜伏者:不,我也在那里发帖,但是当 Raja 找到欺骗目标时,我删除了它以支持在此处发帖。)
      【解决方案5】:

      在处理 JavaScript 日期对象时,您必须指定完整的年份,例如 1950 而不是 50。文档中提到了这一点。所以代码也应该像丹尼尔所说的那样,

      d = new Date(); d.setFullYear(1);
      console.log(d);
      

      【讨论】:

      • um 数字文字 0001 是八进制的 1
      • 10001 的值相同
      • 这与丹尼尔斯的回答究竟有何不同?
      • @Mathemats 一个登录控制台,另一个写入文档。 :P
      • @Sp0T 无论如何,它应该是评论而不是答案。
      猜你喜欢
      • 2018-12-06
      • 2015-12-31
      • 2021-04-23
      • 2013-07-23
      • 1970-01-01
      • 2011-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多