簡體   English   中英

用 JavaScript 確定一個月天數的最佳方法是什么?

[英]What is the best way to determine the number of days in a month with JavaScript?

我一直在使用這個 function 但我想知道最有效和最准確的方法是什么。

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

 function daysInMonth (month, year) { // Use 1 for January, 2 for February, etc. return new Date(year, month, 0).getDate(); } console.log(daysInMonth(2, 1999)); // February in a non-leap year. console.log(daysInMonth(2, 2000)); // February in a leap year.

第 0 天是上個月的最后一天。 因為月份構造函數是從 0 開始的,所以這很好用。 有點小技巧,但這基本上就是你通過減去 32 所做的。

查看更多:當月的天數

一些答案(也在其他問題上)有閏年問題或使用了日期對象。 盡管 javascript 的Date object涵蓋了 1970 年 1 月 1 日前后大約 285616 年(100,000,000 天),但我厭倦了不同瀏覽器(最明顯的是 0 年到 99 年)之間出現的各種意外日期不一致 我也很好奇如何計算它。

所以我寫了一個簡單的,最重要的是,算法來計算正確的( Proleptic Gregorian / Astronomical / ISO 8601:2004(條款 4.3.2.1),所以0存在並且是閏年並且支持負年)天數對於給定的月份和年份。
它使用短路位掩碼模leapYear算法(針對js稍作修改)和常見的mod-8月算法。

請注意,在AD/BC表示法中,不存在公元 0 年:公元前1 BC是閏年!
如果您需要考慮 BC 表示法,那么只需先減去(否則為正)年份值的一年! (或從1中減去年份以進行進一步的年份計算。)

 function daysInMonth(m, y){ return m===2?y&3||!(y%25)&&y&15?28:29:30+(m+(m>>3)&1); }
 <!-- example for the snippet --> <input type="text" value="enter year" onblur=" for( var r='', i=0, y=+this.value ; 12>i++ ; r+= 'Month: ' + i + ' has ' + daysInMonth(i, y) + ' days<br>' ); this.nextSibling.innerHTML=r; " /><div></div>

注意,月份必須從 1 開始!

請注意,這是一種不同的算法,與我在Javascript 中使用的幻數查找計算一年中的哪一天 (1 - 366)答案不同,因為這里只需要二月的閏年的額外分支。

如果您經常調用此函數,則緩存該值以獲得更好的性能可能很有用。

這是FlySwat 答案的緩存版本:

var daysInMonth = (function() {
    var cache = {};
    return function(month, year) {
        var entry = year + '-' + month;

        if (cache[entry]) return cache[entry];

        return cache[entry] = new Date(year, month, 0).getDate();
    }
})();

為了消除混淆,我可能會基於月份字符串,因為它目前是基於 0 的。

function daysInMonth(month,year) {
    var monthNum =  new Date(Date.parse(month +" 1,"+year)).getMonth()+1
    return new Date(year, monthNum, 0).getDate();
}

daysInMonth('feb', 2015)
//28

daysInMonth('feb', 2008)
//29

使用moment.js ,您可以使用 daysInMonth() 方法:

moment().daysInMonth(); // number of days in the current month
moment("2012-02", "YYYY-MM").daysInMonth() // 29
moment("2012-01", "YYYY-MM").daysInMonth() // 31

單線直接計算(無 Date 對象):

 //m is 0-based, Jan = 0, Dec = 11 function daysInMonth(m,y){ return 31-(m-1?m%7&1:y&(y%25?3:15)?3:2); } console.log(daysInMonth(1, 2003), "days in February in the non-leap year 2003"); console.log(daysInMonth(1, 2004), "days in February in the leap year 2004"); console.log(daysInMonth(1, 2100), "days in February in the non-leap year 2100"); console.log(daysInMonth(1, 2000), "days in February in the leap year 2000"); console.log(daysInMonth(0, 2022), "days in January 2022"); console.log(daysInMonth(1, 2022), "days in February 2022"); console.log(daysInMonth(2, 2022), "days in March 2022"); console.log(daysInMonth(3, 2022), "days in April 2022"); console.log(daysInMonth(4, 2022), "days in May 2022"); console.log(daysInMonth(5, 2022), "days in June 2022"); console.log(daysInMonth(6, 2022), "days in July 2022"); console.log(daysInMonth(7, 2022), "days in August 2022"); console.log(daysInMonth(8, 2022), "days in September 2022"); console.log(daysInMonth(9, 2022), "days in October 2022"); console.log(daysInMonth(10, 2022), "days in November 2022"); console.log(daysInMonth(11, 2022), "days in December 2022");

解釋

主要思想是假設月份有 31 天,但如果月份是 4 月、6 月、9 月或 11 月,則減去 1; 如果月份是閏年的二月,則減 2; 如果月份是非閏年的二月,則減去 3。

在三元表達式(m - 1 ? /* Not February */ : /* February */)中,表達式m - 1檢查月份是否為二月。

對於 2 月以外的其他月份,表達式m % 7使m在 31 天的月份中為偶數,其余為奇數。 減去最低位 ( & 1 ) 會導致 4 月、6 月、9 月和 11 月為 31 - 1 天,其余為 31 - 0 天。

對於二月,表達式y & (y % 25 ? 3 : 15)對於閏年是虛假的,導致二月有 31 - 2 天。 否則,二月是 31 - 3 天。

這里是

new Date(2019,2,0).getDate(); //28
new Date(2020,2,0).getDate(); //29

與選定的答案相比,可能有點過分殺戮:)但這里是:

 function getDayCountOfMonth(year, month) { if (month === 3 || month === 5 || month === 8 || month === 10) { return 30; } if (month === 1) { if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) { return 29; } else { return 28; } } return 31; }; console.log(getDayCountOfMonth(2020, 1));

我在這里找到了上面的代碼: https ://github.com/ElemeFE/element/blob/dev/src/utils/date-util.js

 function isLeapYear(year) { return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); }; const getDaysInMonth = function (year, month) { return [31, (isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; }; console.log(getDaysInMonth(2020, 1));

我在這里找到了上面的代碼: https ://github.com/datejs/Datejs/blob/master/src/core.js

ES6 語法

const d = (y, m) => new Date(y, m, 0).getDate();

返回

console.log( d(2020, 2) );
// 29

console.log( d(2020, 6) );
// 30
function numberOfDays(iMonth, iYear) {
         var myDate = new Date(iYear, iMonth + 1, 1);  //find the fist day of next month
         var newDate = new Date(myDate - 1);  //find the last day
            return newDate.getDate();         //return # of days in this month
        }

考慮閏年:

function (year, month) {
    var isLeapYear = ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);

    return [31, (isLeapYear ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
}

如果您想要 Date 對象當前月份的天數,請考慮以下方法:

Date.prototype.getNumberOfDaysInMonth = function(monthOffset) {
    if (monthOffset !== undefined) {
        return new Date(this.getFullYear(), this.getMonth()+monthOffset, 0).getDate();
    } else {
        return new Date(this.getFullYear(), this.getMonth(), 0).getDate();
    }
}

然后你可以像這樣運行它:

var myDate = new Date();
myDate.getNumberOfDaysInMonth(); // Returns 28, 29, 30, 31, etc. as necessary
myDate.getNumberOfDaysInMonth(); // BONUS: This also tells you the number of days in past/future months!

在一行中:

// month is 1-12
function getDaysInMonth(year, month){
    return month == 2 ? 28 + (year % 4 == 0 ? (year % 100 == 0 ? (year % 400 == 0 ? 1 : 0) : 1):0) : 31 - (month - 1) % 7 % 2;
}

也許不是最優雅的解決方案,但易於理解和維護; 而且,它經過了實戰考驗。

function daysInMonth(month, year) {
    var days;
    switch (month) {
        case 1: // Feb, our problem child
            var leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
            days = leapYear ? 29 : 28;
            break;
        case 3: case 5: case 8: case 10: 
            days = 30;
            break;
        default: 
            days = 31;
        }
    return days;
},

如果您要傳遞日期變量,這可能會有所幫助

 const getDaysInMonth = date => new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); daysInThisMonth = getDaysInMonth(new Date()); console.log(daysInThisMonth);

單線,不使用 Date 對象:

const countDays = (month, year) => 30 + (month === 2 ? (year % 4 === 0 && 1) - 2 : (month + Number(month > 7)) % 2);

返回:

countDays(11,2020) // 30
countDays(2,2020) // 29
countDays(2,2021) // 28

獲取當月的天數

 var nbOfDaysInCurrentMonth = new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), 0)).getDate() console.log(nbOfDaysInCurrentMonth)

您可以通過以下命令獲取月份中的天數:

new Date(year, month, 0).getDate();

查看我的功能並對其進行測試:

function numberOfDays(year, month) { // 參考: // https://arslankuyumculuk.com/how-to-calculate-leap-year-formula/ (2022-05-20 16:45 UTC)

numDays=0;
switch(month)
{
    case 1:
        numDays=31;
        break;
    case 2:
        numDays=28;
        break;
    case 3:
        numDays=31;
        break;
    case 4:
        numDays=30;
        break;
    case 5:
        numDays=31;
        break;
    case 6:
        numDays=30;
        break;
    case 7:
        numDays=31;
        break;
    case 8:
        numDays=31;
        break;
    case 9:
        numDays=30;
        break;
    case 10:
        numDays=31;
        break;
    case 11:
        numDays=30;
        break;
    case 12:
        numDays=31;
        break;
}

if(month==2)
{
    if( (year % 100) == 0 )
    {
        if( (year % 400) == 0 )
        {
            numDays=29;
        }
    }
    else
    {
        if( (year % 4) == 0 )
        {
            numDays=29;
        }
    }
}

//
return numDays;

}

// 測試:

const years = [2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2100,2400];
month=2;
for (let i = 0; i < years.length; i++) 
{
    let text = "";
    text += years[i] + '/' + month.toString() + ": " + numberOfDays(years[i], month).toString();
    alert(text);
} 

for (let m = 1; m <= 12; m++) 
{
    let text2 = "";
    text2 += "2022/" + m.toString() + ": " + numberOfDays(2022, m).toString();
    alert(text2);
} 

試試這個 - 它返回帶有month: days映射的字典,我認為在大多數情況下當人們進入這個主題時它會非常有用:

const getMonthsDaysForYear = (year) => {
  let monthDaysDictionary = {};

  for(let i = 1; i <= 11; i++) {
      const date = new Date(year, i + 1, 0);
      const monthName = date.toLocaleString('en-GB', { month: 'long' });
      monthDaysDictionary[monthName] = date.getDate();
  }

  return monthDaysDictionary;
}
getMonthsDaysForYear(2022);

注意:該月應以1開頭,如本答案中所述。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM