Javascript дата 01/01/0001
Я хочу создать объект Date в javascript, который представляет год 0001, 2014 года назад.
Я пробовал с
d = new Date(); d.setYear(1);
console.log(d);
но это дает 1901 год
с
d = new Date(1,1,1)
console.log(d);
ни за что.
Как я могу создать эту дату?
6 ответов
Во-первых, это вообще не проблема 2000 года! (ОБНОВЛЕНИЕ: в некоторых случаях - это связано с проблемами 2000 года, но это не проблема здесь)
Правильный ответ заключается в том, что вы не можете сделать это надежно. Относится ли летнее время к 1 году? Сколько високосных лет было там? Были ли они? И т.д. Но ответ @Daniel будет использовать его!
ОБНОВЛЕНИЕ: не говоря уже о сообщении @MattJohnson о DST. Летнее время в 1-м году, фактически JS (ES5 в любом случае) будет лежать и использовать текущее правило летнего времени для всех лет
Поэтому, пожалуйста, не обманывайте себя идеей, что вы можете надежно работать с датами ниже 1970 года. (У вас будет много проблем и сюрпризов даже в этом временном диапазоне.)
Но если вам действительно очень нужно, вы можете использовать new Date('0001-01-01')
(Формат ISO 8601) или метод @ Daniel:
var d = new Date(); d.setFullYear(1);
Но прежде чем использовать его, прочитайте это...
Существует 4 способа создания даты в JS:
new Date()
new Date(milliseconds)
new Date(dateString)
new Date(year, month, day, hours, minutes, seconds, milliseconds)
1) new Date () создает текущую дату (в вашем местном часовом поясе), поэтому нас это пока не интересует.
2) новая Дата (число) создает новый объект даты как нулевое время плюс число. Ноль времени 01 января 1970 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) новая дата (dateString) Это наиболее "надежный" способ. DateString - Строка, представляющая дату RFC2822 или ISO 8601.
RFC2822 / IETF синтаксис даты (RFC2822, раздел 3.3), например, "Пн, 25 декабря 1995 г., 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
Поэтому мы не можем создать год 1, используя синтаксис даты RFC2822 / IETF
О 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"
Yahoo!!! (или лучше сказать Google!:)), мы можем использовать 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, а не везде. WAT? о_О
ПРЕДУПРЕЖДЕНИЕ! Эта дата будет создана в вашем текущем часовом поясе!!! Так что будьте осторожны, используя его!
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:
Новая Дата (Date.UTC(1,1,1)) будет защищена от тех же симптомов, что и новая Дата (год, месяц, день, часы, минуты, секунды, миллисекунды). Из-за функции Date.UTC.
Использование setFullYear
- это проблема 2000 года с JavaScript.
var d = new Date(); d.setFullYear(1);
document.write(d);
Вы можете использовать строковую версию конструктора:
console.log(new Date("0001-01-01"));
(Не рекомендуется) 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
метод тем не менее. Другой метод устарел.
При обработке объектов дат в JavaScript вы должны указывать полный год, например, 1950, а не 50. Это упоминается в документе. Таким образом, код должен быть таким, как сказал Даниил:
d = new Date(); d.setFullYear(1);
console.log(d);
На самом деле вы можете использовать конструктор Date для годов, абсолютное значение которых меньше 100, используя отрицательный год вместо положительного, а затем устанавливая его обратно в положительное значение с помощью надежных / методов. Это связано с тем, что проблема получения лет 20-го или 21-го века в случае исторических проявляется только для менее чем 100 положительных лет. Хотя для базового использования это работает без проблем, следует соблюдать осторожность при использовании
new Date(...)
конструктор, чтобы добавить или вычесть время в момент создания объекта, так как вы также хотите соответствующим образом переключить знак операции. Кроме того, если желаемый исторический год в первую очередь отрицательный и вам нужно прибавить или вычесть его во время строительства, вопрос подвергается дополнительным осложнениям.
Поэтому, чтобы избежать путаницы и быть ясным и последовательным в отношении вещей, используя расширенную форму
.setFullYear()
/
.setUTCFullYear()
а также
.setHours()
/
.setUTCHours()
установка всей части даты и времени после строительства объекта должна быть оптимальной альтернативой и не иметь никаких недостатков, а также аналогична установке вещей во время строительства.
Ниже приведены примеры для каждого из двух упомянутых выше методов, а также для локальных дат и дат UTC (необязательный 365-дневный или 31536000000 мс год «добавляется» во всех случаях, чтобы проиллюстрировать, если и как это меняет ситуацию):
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript Historic Dates Problem</h2>
<p>Construct negative dates and switch them to positive (1) or <br>Set the full date and time parts separately (2)</p>
<p id="examples"></p>
<script>
var loc1 = new Date(- 37, 11, 24, 10, 33, 30, - 31536000000); loc1.setFullYear(- loc1.getFullYear());
var utc1 = new Date(Date.UTC(- 37, 11, 24, 10, 33, 30, - 31536000000)); utc1.setUTCFullYear(- utc1.getUTCFullYear());
var loc2 = new Date(); loc2.setFullYear(37, 11, 24); loc2.setHours(10, 33, 30, 31536000000);
var utc2 = new Date(); utc2.setUTCFullYear(37, 11, 24); utc2.setUTCHours(10, 33, 30, 31536000000);
document.getElementById("examples").innerHTML = "LOC1: " + loc1 + "<br>UTC1: " + utc1 + "<br>LOC2: " + loc2 + "<br>UTC2: " + utc2;
</script>
</body>
</html>