【发布时间】: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
我想在 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
首先,这根本不是千年虫问题!(更新:在某些情况下 - 它与千年虫问题有关,但这里不是问题)
正确答案是您无法可靠地做到这一点。夏令时是否适用于第一年?有多少个闰年?有吗?等等。但是@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 函数。
【讨论】:
Date 对象 always 反映了本地时区。你不能把它放在另一个时区,即使你用 UTC 时间戳初始化它,它仍然会在大多数函数中反映本地时区。在内部,它通过数字时间戳跟踪 UTC,并且有一些函数显式公开 UTC 值,但其他一切都是本地的。
使用 setFullYear - 这是 JavaScript 的千年虫问题。
var d = new Date(); d.setFullYear(1);
document.write(d);
【讨论】:
document.write!
(已弃用)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 方法。另一种方法已弃用。
【讨论】:
可以使用字符串版本的构造函数:
console.log(new Date("0001-01-01"));
【讨论】:
在处理 JavaScript 日期对象时,您必须指定完整的年份,例如 1950 而不是 50。文档中提到了这一点。所以代码也应该像丹尼尔所说的那样,
d = new Date(); d.setFullYear(1);
console.log(d);
【讨论】:
0001 是八进制的 1
1 和 0001 的值相同。