Как использовать javascript для вычисления дня в году от 1 до 366? Например:
- 3 января должно быть 3 .
- 1 февраля должно быть 32 .
javascript
Кирк Уолл
источник
источник
var days = new Date().getFullYear() % 4 == 0 ? 366 : 365;
Ответы:
После редактирования OP:
Изменить: приведенный выше код завершится ошибкой, если
now
дата находится между 26 марта и 29 октября иnow
время до 1 часа ночи (например, 00:59:59). Это связано с тем, что код не учитывает летнее время. Вы должны это компенсировать :источник
Math.floor
стабильно давал мне результат на 1 день меньше, чем ожидалось после определенного дня в апреле.Math.ceil
работал, как ожидалось, но я видел, что вам рекомендуется использоватьMath.round
вместо них.new Date(2014, 0, 1)
, а неnew Date(2014, 0, 0)
как здесь. Это намеренно? Возможно, это то, что составляет один день, когдаnew Date(2014, 0, 0)
вернется12/31/2013
..setUTCHours
иDate.UTC()
для более надежного решения.ceil
вместоfloor
, это даст вам систему нумерации, в которой 1 января = 1. Если вы хотите, чтобы 1 января = 0 (floor
что и даст вам), просто вычтите 1 из окончательного результата.var diff = now - start + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
Это работает при переходе на летнее время во всех странах (указанное выше «полдень» не работает в Австралии):
источник
getDay()
нужно изменить наgetDate()
. Первый возвращает день недели (0 = воскресенье..6 = суббота), а не день.Мне очень интересно, что никто не рассматривал возможность использования UTC, поскольку он не подлежит переходу на летнее время. Поэтому предлагаю следующее:
Вы можете проверить это следующим образом:
Какие результаты для високосного 2016 года (проверено с помощью http://www.epochconverter.com/days/2016 ):
источник
function doyToDate(doy, year) { return new Date(year, 0, doy); }
new Date(8640000000000000)
это все еще меньшеNumber.MAX_SAFE_INTEGER
. см. этот ответ: stackoverflow.com/a/11526569/18511источник
К счастью, в этом вопросе не указывается, требуется ли номер текущего дня, оставляя место для этого ответа.
Также в некоторых ответах (также на другие вопросы) были проблемы с високосным годом или использовался объект Date. Хотя javascript
Date object
охватывает примерно 285616 лет (100000000 дней) по обе стороны от 1 января 1970 года, мне надоели всевозможные неожиданные несоответствия дат в разных браузерах (особенно с 0 по 99 год). Мне также было любопытно, как это рассчитать.Поэтому я написал простой и, прежде всего, небольшой алгоритм для вычисления правильного ( Proleptic Gregorian / Astronomical / ISO 8601: 2004 (пункт 4.3.2.1), поэтому год
0
существует и является високосным, и поддерживаются отрицательные годы ) дня года. по году , месяцу и дню .Обратите внимание, что в
AD/BC
нотации год 0 AD / BC не существует: вместо этого год1 BC
является високосным! ЕСЛИ вам нужно учесть нотацию BC, тогда просто сначала вычтите один год из (в противном случае положительного) годового значения !!Я изменил (для javascript) алгоритм короткого замыкания битовой маски по модулю leapYear и придумал магическое число для побитового поиска смещений (которое исключает jan и feb, поэтому требуется 10 * 3 бит (30 бит меньше, чем 31 бит, поэтому мы можем спокойно сохранить другой символ при битовом сдвиге вместо
>>>
)).Обратите внимание, что ни месяц, ни день не могут быть
0
. Это означает, что если вам нужно это уравнение только на текущий день (кормление с помощью.getMonth()
), вам просто нужно удалить--
из--m
.Обратите внимание, это предполагает действительную дату (хотя для проверки ошибок требуется всего лишь несколько символов).
Вот версия с правильной проверкой диапазона.
Опять же, одна строка, но я разделил ее на 3 строки для удобства чтения (и следующих пояснений).
Последняя строка идентична приведенной выше функции, однако (идентичный) алгоритм leapYear перемещен в предыдущий раздел короткого замыкания (перед вычислением числа дней), потому что также необходимо знать, сколько дней в месяце имеет данный (високосный) год.
Средняя строка вычисляет правильное число смещения (для максимального количества дней) для данного месяца в данном (високосном) году с использованием другого магического числа: поскольку
31-28=3
и3
составляет всего 2 бита, то12*2=24
биты, мы можем сохранить все 12 месяцев. Поскольку сложение может быть быстрее, чем вычитание, мы добавляем смещение (вместо того, чтобы вычитать его31
). Чтобы избежать ветки принятия решения о високосном году для февраля, мы изменяем это волшебное число поиска на лету.Это оставляет нам (довольно очевидную) первую строку: она проверяет, находятся ли месяц и дата в допустимых пределах, и гарантирует нам
false
возвращаемое значение при ошибке диапазона (обратите внимание, что эта функция также не должна возвращать 0, потому что 1 января 0000 еще день 1.), обеспечивая легкие проверки ошибок:if(r=dayNo(/*y, m, d*/)){}
.Если использовать этот способ (где месяц и день могут не быть
0
), то можно изменить--m>=0 && m<12
наm>0 && --m<12
(сохранение другого символа).Причина, по которой я набрал фрагмент в его текущей форме, заключается в том, что для значений месяца, отсчитываемых от 0, нужно просто удалить
--
из--m
.Дополнительно:
обратите внимание, не используйте алгоритм этого дня в месяц, если вам нужно только максимальное количество дней в месяц. В этом случае есть более эффективный алгоритм (потому что leepYear нам нужен только тогда, когда месяц - февраль), который я опубликовал в качестве ответа на этот вопрос: Как лучше всего определить количество дней в месяце с помощью javascript? ,
источник
Date.prototype.dayNo = function(){ var y = this.getFullYear(); var m = this.getMonth()+1; var d = this.getDate(); return --m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+d; };
+1
от ,this.getMonth()+1
если вы удалите--
из--m
. ИЗМЕНИТЬ Итак, я бы сделал (для библиотеки):Date.prototype.dayNo = function(){ var y=this.getFullYear(), m=this.getMonth(); return m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+this.getDate(); };
2^31 - 2016
года, js, вероятно, немного устареет.:)
Но до тех пор он будет давать по крайней мере предсказуемые и последовательные результаты, ха-ха. РЕДАКТИРОВАТЬ , просто ради теории, используя более медленный обычный алгоритм с полным модулем для високосного года, диапазон можно расширить до 2 ^ 53. Алгоритм поиска по месяцам не является ограничивающим фактором.Если вы не хотите заново изобретать колесо, вы можете использовать отличную библиотеку date-fns (node.js):
источник
Ну, если я вас правильно понял, вы хотите 366 в високосный год, 365 в противном случае, не так ли? Год считается високосным, если он делится без остатка на 4, но не на 100, если он также не делится на 400:
Редактировать после обновления:
В этом случае я не думаю, что есть встроенный метод; вам нужно будет сделать это:
(Да, я действительно сделал это без копирования и вставки. Если есть простой способ, я буду зол)
источник
:)
Это простой способ найти текущий день в году, и он должен без проблем учитывать високосные годы:
Javascript:
Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);
Javascript в Google Apps Script:
Math.round((new Date().setHours(23) - new Date(new Date().getYear(), 0, 1, 0, 0, 0))/1000/60/60/24);
Основное действие этого кода - найти количество миллисекунд, прошедших в текущем году, а затем преобразовать это число в дни. Количество миллисекунд, прошедших в текущем году, можно найти, вычтя количество миллисекунд первой секунды первого дня текущего года, полученное с помощью
new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0)
(Javascript) илиnew Date(new Date().getYear(), 0, 1, 0, 0, 0)
(Google Apps Script), из миллисекунд. 23 часа текущих суток, который был найден сnew Date().setHours(23)
. Целью установки текущей даты на 23-й час является обеспечение правильного округления дня года наMath.round()
.Когда у вас есть количество миллисекунд текущего года, вы можете преобразовать это время в дни, разделив на 1000, чтобы преобразовать миллисекунды в секунды, затем разделив на 60, чтобы преобразовать секунды в минуты, затем разделив на 60, чтобы преобразовать минуты в часы, и, наконец, деление на 24 для преобразования часов в дни.
Примечание. Этот пост был отредактирован, чтобы учесть различия между JavaScript и JavaScript, реализованными в Google Apps Script. Кроме того, для ответа был добавлен дополнительный контекст.
источник
.setHours
метод для первого объекта даты и указал время дня для второго объекта даты, изменение летнего времени на 1 час не повлияет на время объектов Date, используемых в этом вычислении.Я думаю, что это проще:
источник
Этот метод учитывает проблему с часовым поясом и летнее время.
(взял отсюда )
См. Также эту скрипку
источник
Math.round ((new Date (). SetHours (23) - новая Дата (new Date (). GetFullYear (), 0, 1, 0, 0, 0)) / 1000/86400);
дополнительно оптимизирует ответ.
Более того, изменив setHours (23) или предпоследний ноль позже на другое значение, можно получить день года, связанный с другим часовым поясом. Например, чтобы получить из Европы ресурс, расположенный в Америке.
источник
это мое решение
источник
Я сделал один из них, который можно читать и он очень быстро справится с задачей, а также обработает объекты JS Date с разными часовыми поясами.
Я включил довольно много тестовых примеров для часовых поясов, летнего времени, дополнительных секунд и високосных лет.
PS ECMA-262 игнорирует дополнительные секунды, в отличие от UTC. Если бы вы преобразовали это в язык, использующий реальный UTC, вы могли бы просто добавить 1 к
oneDay
.источник
Я хотел бы предоставить решение, которое выполняет вычисления, добавляя дни для каждого предыдущего месяца:
Таким образом, вам не нужно управлять деталями високосных лет и летнего времени.
источник
Альтернатива с использованием меток времени в формате UTC. Также, как отмечали другие, день, обозначающий 1-й месяц, равен 1, а не 0. Однако месяц начинается с 0.
источник
Вы можете передать параметр как номер даты в
setDate
функции:источник
Это может быть полезно для тех, кому нужен день года в виде строки и доступен пользовательский интерфейс jQuery.
Вы можете использовать jQuery UI Datepicker:
Ниже он работает так же, как некоторые из уже упомянутых ответов (
(date_ms - first_date_of_year_ms) / ms_per_day
):источник
Для тех из нас, кто хочет быстрое альтернативное решение.
Размер месяцев в году и то, как работают високосные годы, идеально подходят для того, чтобы наше время соответствовало солнечным. Черт возьми, это работает так идеально, что все, что мы когда-либо делаем, это просто настраиваем за несколько секунд здесь и там . Наша нынешняя система високосных лет действует с 24 февраля 1582 г. года и, вероятно, останется в силе в обозримом будущем.
Однако летнее время очень подвержено изменениям. Может случиться так, что через 20 лет какая-то страна может компенсировать время на целый день или какое-то другое экстремальное время для перехода на летнее время. Целого дня летнего времени почти наверняка никогда не произойдет, но, тем не менее, летнее время все еще очень актуально и нерешительно. Таким образом, вышеуказанное решение является перспективным в дополнение к тому, что оно очень и очень быстрое.
Приведенный выше фрагмент кода выполняется очень быстро. Мой компьютер может обработать 65536 дат за ~ 52 мс в Chrome.
источник
источник
Это решение, которое позволяет избежать неприятных проблем с объектом Date и часовым поясом, оно требует, чтобы дата ввода была в формате «гггг-дд-мм». Если вы хотите изменить формат, измените функцию date_str_to_parts:
источник
Меня всегда беспокоит смешивание математики с функциями даты (так легко упустить какой-то високосный год и другие детали). Скажите, что у вас есть:
Я бы предложил использовать следующее, дни будут сохранены в
day
:Не вижу причин, по которым это не будет работать нормально (и я бы не стал так беспокоиться о нескольких итерациях, поскольку это не будет использоваться так интенсивно).
источник
/ * ИСПОЛЬЗУЙТЕ ЭТОТ СКРИПТ * /
источник