JavaScript로 한 달의 일수를 결정하는 가장 좋은 방법은 무엇입니까?


107

이 기능을 사용해 왔지만 가장 효율적이고 정확한 방법이 무엇인지 알고 싶습니다.

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

답변:


200

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를 빼서 수행하는 작업입니다.


42
이 구문은 한동안 저를 혼란스럽게했습니다. JS 패턴을 따라하기 위해이 같은 트릭을 구현하기 위해 추천 해드립니다 :return new Date(year, month + 1, 0).getDate();
fguillen

2
불행히도 이것은 SetFullYear ()를 사용하여 연도를 올바르게 설정할 수있는 AD 1000 년 이전의 날짜에서는 실패합니다. 방탄으로 만들려면 new Date (2000+ (year % 2000), month, 0) .getDate ()
Noel Walters

4
내 미래에 대한 메모 : '+ 1'이 포함 된 fguillen의 방정식은 연도가 2014 년이고 월이 1 일 때 28 일을 제공합니다 (JavaScript Date-object에서는 2 월을 의미 함). 아마 놀랍게도 그와 함께 가고 싶을 것입니다. 그러나 FlySwat의 멋진 아이디어입니다!
Harry Pehkonen 2014

@ NoelWalters— 일부 브라우저가 2 자리 연도를 20 세기의 날짜로 잘못 변환하는 것이 맞습니다 (따라서 AD 1000 년이 아닌 100 년 이전의 날짜).하지만 수정을해도 해당 브라우저에서는 수정되지 않습니다. 두 자리 연도를 안정적으로 설정하는 유일한 방법은 setFullYear : 를 사용하는 것 var d=new Date();d.setFullYear(year, month, date);입니다.
RobG 2014

1
어떤 경우 month이다 (12)는 ? Date생성자는 0에서 11 사이의 값을 가져야하지 않습니까?
anddero

8

이 함수를 자주 호출하면 성능 향상을 위해 값을 캐시하는 것이 유용 할 수 있습니다.

다음은 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();
    }
})();

6
내부 C / C ++ 루틴이 너무 느려서 캐싱이 필요합니까?
Pete Alvin

1
@PeteAlvin 구현에 따라 다릅니다 Date(따라서 해당 질문에 대한 보편적 인 대답은 없습니다) dayInMonth. 따라서 유일한 현명한 대답은 코드를 프로파일 링하고 벤치마킹하는 것입니다!
고인돌

1
나는 그것을 좋아한다! 하지만 그 대신 새로운 객체를 사용하는 cache, 내가 사용 localStorage.
앤드류

5

일부 답변 (다른 질문에서도)은 윤년 문제가 있거나 Date-object를 사용했습니다. 자바 스크립트 Date object는 1970 년 1 월 1 일 양쪽에서 약 285616 년 (100,000,000 일)을 다루지 만, 여러 브라우저 (특히 0 ~ 99 년) 에서 예기치 않은 모든 종류의 날짜 불일치에 지쳤습니다 . 계산 방법도 궁금했습니다.

그래서 나는 정확한 계산을 위해 간단하고 무엇보다도 작은 알고리즘을 작성했습니다 ( Proleptic Gregorian / Astronomical / ISO 8601 : 2004 (clause 4.3.2.1), so year는 존재하고 윤년이고 음의 연도는 지원됩니다 ). 주어진 월과 연도. 그것은 사용 단락 비트 마스크 모듈 leapYear 알고리즘 0
(약간 JS 위해 수정) 및 공통 모드-8 달 알고리즘.

에주의 AD/BC표기 년 0 AD가 / BC가 존재하지 않는이 : 대신 올해는 1 BC도약 년입니다!
BC 표기법을 설명해야한다면 먼저 연도 값 (그렇지 않으면 양수)에서 1 년을 빼면됩니다 !! (또는 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부터 시작해야합니다!

여기에서는 윤년에 대한 추가 분기가 2 월에만 필요하기 때문에 Javascript 에서 사용한 매직 넘버 조회와 다른 알고리즘이 1 년 (1-366) 답변을 계산합니다 .


4

혼란을 없애기 위해 현재 1 기반이므로 월 문자열을 기반으로 할 것입니다.

function daysInMonth(month,year) {
    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

4

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

2

여기 간다

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

2

ES6 구문

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

보고

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

console.log( d(2020, 6) );
// 30

1
기존 질문에 14 개의 기존 답변이있는 새 답변을 추가 할 때 답변이 다루는 질문의 새로운 측면을 기록하는 것이 정말 중요합니다. ES6 구문입니까?
Jason Aller

알았다. 지금부터 답변에 컨텍스트를 추가합니다.
RASG

1
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
        }

1

윤년 고려 :

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];
}

좋은. 보기 쉽습니다. Inline-Map / Immediately-Keyed Value 사용을위한 속성.
Cody

1

한 줄 직접 계산 (Date 객체 없음) :

function daysInMonth(m, y) {//m is 1-based, feb = 2
   return 31 - (--m ^ 1? m % 7 & 1:  y & 3? 3: y % 25? 2: y & 15? 3: 2);
}

console.log(daysInMonth(2, 1999)); // February in a non-leap year
console.log(daysInMonth(2, 2000)); // February in a leap year

0 기반 월의 변형 :

function daysInMonth(m, y) {//m is 0-based, feb = 1
   return 31 - (m ^ 1? m % 7 & 1:  y & 3? 3: y % 25? 2: y & 15? 3: 2);
}

1

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!

1

한 줄로 :

// 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;
}

1

선택한 답변과 비교할 때 약간 오버 킬 수 있습니다. :) 그러나 여기에 있습니다.

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


1

날짜 변수를 전달하려는 경우 도움이 될 수 있습니다.

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

daysInThisMonth = getDaysInMonth(new Date());

console.log(daysInThisMonth);


-1

아마도 가장 우아한 솔루션은 아니지만 이해하고 유지하기 쉽습니다. 그리고 전투 테스트를 거쳤습니다.

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;
},
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.