Рассчитать последний день месяца в JavaScript - PullRequest
238 голосов
/ 21 октября 2008

Если вы укажете 0 как dayValue в Date.setFullYear, вы получите последний день предыдущего месяца:

d = new Date(); d.setFullYear(2008, 11, 0); //  Sun Nov 30 2008

Существует ссылка на это поведение на mozilla . Это надежная функция кросс-браузер или я должен искать альтернативные методы?

Ответы [ 16 ]

356 голосов
/ 21 октября 2008
var month = 0; // January
var d = new Date(2008, month + 1, 0);
alert(d); // last day in January

IE 6: Thu Jan 31 00:00:00 CST 2008
IE 7: Thu Jan 31 00:00:00 CST 2008
IE 8: Beta 2: Thu Jan 31 00:00:00 CST 2008
Opera 8.54: Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.27: Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.60: Thu Jan 31 2008 00:00:00 GMT-0600
Firefox 2.0.0.17: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Firefox 3.0.3: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Google Chrome 0.2.149.30: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Safari for Windows 3.1.2: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)

Различия в выходных данных связаны с различиями в реализации toString(), а не с тем, что даты разные.

Конечно, только потому, что браузеры, указанные выше, используют 0 как последний день предыдущего месяца, не означает, что они будут продолжать это делать, или что браузеры, не перечисленные в списке, будут делать это, но это вселяет доверие к убеждению, что это должен работать одинаково в каждом браузере.

72 голосов
/ 21 октября 2008

Я бы использовал промежуточную дату с первым днем ​​следующего месяца и возвратил бы дату предыдущего дня:

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);
56 голосов
/ 08 декабря 2012

Я считаю, что это лучшее решение для меня. Пусть объект Date рассчитает это для вас.

var today = new Date();
var lastDayOfMonth = new Date(today.getFullYear(), today.getMonth()+1, 0);

Установка параметра дня в 0 означает, что на один день меньше первого дня месяца, который является последним днем ​​предыдущего месяца.

22 голосов
/ 14 января 2015

С точки зрения компьютера, решения new Date() и regular expression являются медленными! Если вам нужен супер-быстрый (и супер-загадочный) однострочный текст, попробуйте этот вариант (при условии, что m в формате Jan=1). Я продолжаю пробовать разные изменения кода, чтобы добиться максимальной производительности.

Мой текущий Самый быстрый версия:

После рассмотрения этого связанного вопроса Проверка високосного года с использованием побитовых операторов (удивительная скорость) и обнаружение, что представляет собой магическое число 25 и 15, я пришел к этому оптимизированному гибриду ответов:

function getDaysInMonth(m, y) {
    return m===2 ? y & 3 || !(y%25) && y & 15 ? 28 : 29 : 30 + (m+(m>>3)&1);
}

Учитывая сдвиг битов, это, очевидно, предполагает, что ваши параметры m & y являются целыми числами, так как передача чисел в виде строк приведет к странным результатам.

JSFiddle: http://jsfiddle.net/TrueBlueAussie/H89X3/22/

Результаты JSPerf: http://jsperf.com/days-in-month-head-to-head/5

По какой-то причине (m+(m>>3)&1) более эффективен, чем (5546>>m&1) на почти во всех браузерах.

Единственное реальное соревнование за скорость - от @GitaarLab, поэтому я создал JSPerf, чтобы мы могли проверить: http://jsperf.com/days-in-month-head-to-head/5


Он работает на основе моего ответа о високосном году здесь: JavaScript, чтобы найти високосный год этот ответ здесь Проверка високосного года с использованием побитовых операторов (потрясающая скорость) , а также следующая двоичная логика .

Быстрый урок в двоичных месяцах:

Если вы интерпретируете индекс нужных месяцев (Jan = 1) в двоичном формате , вы заметите, что месяцы с 31 днем ​​либо имеют очищенный бит 3 и бит 0, либо установлен бит 3 и бит 0 ясно.

Jan = 1  = 0001 : 31 days
Feb = 2  = 0010
Mar = 3  = 0011 : 31 days
Apr = 4  = 0100
May = 5  = 0101 : 31 days
Jun = 6  = 0110
Jul = 7  = 0111 : 31 days
Aug = 8  = 1000 : 31 days
Sep = 9  = 1001
Oct = 10 = 1010 : 31 days
Nov = 11 = 1011
Dec = 12 = 1100 : 31 days

Это означает, что вы можете сдвинуть значение на 3 позиции с помощью >> 3, XOR для битов с оригинальным ^ m и посмотреть, будет ли результат 1 или 0 в битовой позиции 0 , используя & 1. Примечание. Оказывается, + немного быстрее, чем XOR (^), а (m >> 3) + m дает тот же результат в бите 0.

Результаты JSPerf : http://jsperf.com/days-in-month-perf-test/6

17 голосов
/ 14 марта 2011

Мой коллега наткнулся на следующее, что может быть более простым решением

function daysInMonth(iMonth, iYear)
{
    return 32 - new Date(iYear, iMonth, 32).getDate();
}

украдено у http://snippets.dzone.com/posts/show/2099

12 голосов
/ 22 декабря 2011

Небольшая модификация решения, предоставленная lebreeze :

function daysInMonth(iMonth, iYear)
{
    return new Date(iYear, iMonth, 0).getDate();
}
3 голосов
/ 08 сентября 2018

Мне недавно пришлось сделать нечто подобное, вот что я придумал:

/**
* Returns a date set to the begining of the month
* 
* @param {Date} myDate 
* @returns {Date}
*/
function beginningOfMonth(myDate){    
  let date = new Date(myDate);
  date.setDate(1)
  date.setHours(0);
  date.setMinutes(0);
  date.setSeconds(0);   
  return date;     
}

/**
 * Returns a date set to the end of the month
 * 
 * @param {Date} myDate 
 * @returns {Date}
 */
function endOfMonth(myDate){
  let date = new Date(myDate);
  date.setMonth(date.getMonth() +1)
  date.setDate(0);
  date.setHours(23);
  date.setMinutes(59);
  date.setSeconds(59);
  return date;
}

Передайте его в дате, и он вернет дату, установленную либо на начало месяца, либо на конец месяца.

Функция begninngOfMonth довольно понятна, но в функции endOfMonth происходит то, что я увеличиваю месяц до следующего месяца, а затем использую setDate(0) для отката дня до последний день предыдущего месяца, который является частью спецификации setDate:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate https://www.w3schools.com/jsref/jsref_setdate.asp

Затем я устанавливаю часы / минуты / секунды на конец дня, чтобы, если вы используете какой-то API, ожидающий диапазон дат, вы смогли зафиксировать весь этот последний день. Эта часть может выходить за рамки того, о чем просит оригинальный пост, но она может помочь кому-то еще, ищущему подобное решение.

Редактировать: Вы также можете пройти лишнюю милю и установить миллисекунды с setMilliseconds(), если хотите быть более точным.

3 голосов
/ 24 февраля 2016

Это работает для меня. Укажите последний день данного года и месяца:

var d = new Date(2012,02,0);
var n = d.getDate();
alert(n);
3 голосов
/ 01 августа 2012

попробуйте это.

lastDateofTheMonth = new Date(year, month, 0)

пример:

new Date(2012, 8, 0)

Выход:

Date {Fri Aug 31 2012 00:00:00 GMT+0900 (Tokyo Standard Time)}
1 голос
/ 20 марта 2018

Это даст вам текущий месяц первого и последнего дня.

Если вам нужно изменить год, удалите d.getFullYear () и укажите свой год.

Если вам нужно изменить «месяц», удалите d.getMonth () и установите свой год.

var d = new Date();
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var fistDayOfMonth = days[(new Date(d.getFullYear(), d.getMonth(), 1).getDay())];
	var LastDayOfMonth = days[(new Date(d.getFullYear(), d.getMonth() + 1, 0).getDay())]; 
console.log("First Day :" + fistDayOfMonth); 
console.log("Last Day:" + LastDayOfMonth);
alert("First Day :" + fistDayOfMonth); 
alert("Last Day:" + LastDayOfMonth);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...