[javascript] Javascript는 연중 일을 계산합니다 (1-366).

1에서 366까지의 일을 계산하기 위해 자바 스크립트를 어떻게 사용합니까? 예를 들면 :

  • 1월 3일는 해야한다 3 .
  • 2 월 1 일은 32 여야합니다 .


답변

OP의 편집에 따라 :

var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = now - start;
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);

편집 : 위의 코드는 실패 할 때 now3 월 26 10 월 29 일 사이의 날짜 인 now의 시간이 오전 1시 전에 (예를 0시 59분 59초). 이는 일광 절약 시간을 고려하지 않은 코드 때문입니다. 이를 보상 해야 합니다.

var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = (now - start) + ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);


답변

이는 모든 국가의 일광 절약 시간제 변경에 적용됩니다 (위의 “정오”는 오스트레일리아에서는 적용되지 않음).

Date.prototype.isLeapYear = function() {
    var year = this.getFullYear();
    if((year & 3) != 0) return false;
    return ((year % 100) != 0 || (year % 400) == 0);
};

// Get Day of Year
Date.prototype.getDOY = function() {
    var dayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
    var mn = this.getMonth();
    var dn = this.getDate();
    var dayOfYear = dayCount[mn] + dn;
    if(mn > 1 && this.isLeapYear()) dayOfYear++;
    return dayOfYear;
};


답변

DST가 적용되지 않기 때문에 아무도 UTC 사용을 고려하지 않았다는 것이 매우 흥미 롭습니다. 따라서 다음을 제안합니다.

function daysIntoYear(date){
    return (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000;
}

다음과 같이 테스트 할 수 있습니다.

[new Date(2016,0,1), new Date(2016,1,1), new Date(2016,2,1), new Date(2016,5,1), new Date(2016,11,31)]
    .forEach(d =>
        console.log(`${d.toLocaleDateString()} is ${daysIntoYear(d)} days into the year`));

윤년 2016에 대한 출력 ( http://www.epochconverter.com/days/2016을 사용하여 확인 ) :

1/1/2016 is 1 days into the year
2/1/2016 is 32 days into the year
3/1/2016 is 61 days into the year
6/1/2016 is 153 days into the year
12/31/2016 is 366 days into the year


답변

Date.prototype.dayOfYear= function(){
    var j1= new Date(this);
    j1.setMonth(0, 0);
    return Math.round((this-j1)/8.64e7);
}

alert(new Date().dayOfYear())


답변

의 수 있으면 다행스럽게도이 질문은 지정하지 않는 현재의 일이 필요한이 답변을위한 공간을 떠나.
또한 일부 답변 (다른 질문에서도)은 윤년 문제가 있거나 Date 객체를 사용했습니다. 자바 스크립트 Date object는 1970 년 1 월 1 일 양측에 약 285616 년 (100,000,000 일)을 다루지 만 모든 종류의 예상치 못한 날짜 불일치에 지쳤습니다. 다른 브라우저 (특히 0 ~ 99 년) . 계산 방법도 궁금했습니다.

그래서 정확한 계산을 위한 간단하고 무엇보다 작은 알고리즘을 작성했습니다 ( Proleptic Gregorian / Astronomical / ISO 8601 : 2004 (4.3.2.1 절), 따라서 연도는 존재하고 윤년이고 음의 연도는 지원됨 ). , , 일을 기준으로 합니다 .
주에 있음을 표기 해 0 AD는 / BC가 존재하지 않습니다 : 대신 년 0
AD/BC1 BC 도약 년입니다! BC 표기법을 설명해야한다면 먼저 연도 값 (그렇지 않으면 양수)에서 1 년을 빼면됩니다 !!

나는 (자바 스크립트의 경우) short-circuit bitmask-modulo leapYear 알고리즘을 수정 하고 오프셋 의 비트 단위 조회를 수행하기 위해 매직 넘버를 생각해 냈습니다 (jan 및 feb 제외, 따라서 10 * 3 비트 필요 (30 비트는 31 비트이므로 >>>) 대신 비트 시프트에서 다른 문자를 안전하게 저장할 수 있습니다 .

월이나 일 모두 0. 즉, 현재 날짜 에만이 방정식이 필요한 경우 (를 사용하여 먹이기 .getMonth()) --from --m.

이것은 유효한 날짜를 가정합니다 (오류 검사는 몇 문자 이상일뿐입니다).

function dayNo(y,m,d){
  return --m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
  var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
  this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>

<br><hr><br>

<button onclick="
  var d=new Date();
  this.nextSibling.innerHTML=dayNo(d.getFullYear(), d.getMonth()+1, d.getDate()) + ' Day(s)';
">get current dayno:</button><span></span>


다음은 올바른 범위 유효성 검사 가있는 버전입니다 .

function dayNo(y,m,d){
  return --m>=0 && m<12 && d>0 && d<29+(
           4*(y=y&3||!(y%25)&&y&15?0:1)+15662003>>m*2&3
         ) && m*31-(m>1?(1054267675>>m*3-6&7)-y:0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
  var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
  this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>

다시 한 번, 한 줄이지 만 가독성을 위해 3 줄로 나누었습니다 (그리고 다음 설명).

마지막 줄은 위의 함수와 동일하지만 (동일한) leapYear 알고리즘은 이전 단락 섹션 (일수 계산 전)으로 이동합니다. 왜냐하면 한 달에 몇 일이 있는지 알아야하기 때문입니다. 주어진 (윤) 년.

중간 라인은 정확한 계산 오프셋 다른 매직 넘버를 사용하여 주어진 (도약) 년에 주어진 달 (일 최대 번호) 번호를 보낸 사람 31-28=33다음 단 2 비트이며, 12*2=24비트, 우리 모두 12개월 저장할 수 있습니다. 덧셈이 뺄셈보다 빠를 수 있으므로 오프셋을 추가합니다 (에서 빼는 대신 31). 2 월 윤년 결정 분기를 피하기 위해 매직 조회 번호를 즉시 수정합니다.

그것은 우리에게 (아주 명백한) 첫 번째 줄을 남깁니다. 월과 날짜가 유효한 경계 내에 있는지 확인하고 false범위 오류에 대한 반환 값을 보장 합니다 (이 함수도 0을 반환 할 수 없습니다. 여전히 1 일차입니다.), 간편한 오류 검사 제공 : if(r=dayNo(/*y, m, d*/)){}.
(월, 일을하지 않을 수 있습니다이 방법을 사용하는 경우 0), 다음 하나는 변경할 수 --m>=0 && m<12m>0 && --m<12(다른 문자를 저장).
나는 그것의 현재 형태의 조각을 입력하는 이유는 0 기반의 달의 값을 하나의 단지를 제거 할 필요가 있다는 점이다 --에서 --m.

추가 :
월별 최대 일수 만 필요한 경우에는이 날짜 별 알고리즘을 사용하지 마십시오. 이 경우 더 효율적인 알고리즘이 있습니다 (2 월일 때 leepYear 만 필요하기 때문입니다).이 질문에 대한 답변으로 게시했습니다. 자바 스크립트로 한 달의 일 수를 결정하는 가장 좋은 방법은 무엇입니까? .


답변

휠을 재발 명하고 싶지 않다면 훌륭한 date-fns (node.js) 라이브러리를 사용할 수 있습니다 .

var getDayOfYear = require('date-fns/get_day_of_year')

var dayOfYear = getDayOfYear(new Date(2017, 1, 1)) // 1st february => 32


답변

글쎄, 내가 당신을 올바르게 이해한다면 윤년에 366을 원하고 그렇지 않으면 365를 원합니다. 1 년은 4로 균등하게 나눌 수있는 경우 윤년이지만 400으로 나눌 수없는 경우에는 100으로 나눌 수 없습니다.

function daysInYear(year) {
    if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
        // Leap year
        return 366;
    } else {
        // Not a leap year
        return 365;
    }
}

업데이트 후 편집 :

이 경우에는 기본 제공 방법이 없다고 생각합니다. 다음을 수행해야합니다.

function daysInFebruary(year) {
    if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
        // Leap year
        return 29;
    } else {
        // Not a leap year
        return 28;
    }
}

function dateToDay(date) {
    var feb = daysInFebruary(date.getFullYear());
    var aggregateMonths = [0, // January
                           31, // February
                           31 + feb, // March
                           31 + feb + 31, // April
                           31 + feb + 31 + 30, // May
                           31 + feb + 31 + 30 + 31, // June
                           31 + feb + 31 + 30 + 31 + 30, // July
                           31 + feb + 31 + 30 + 31 + 30 + 31, // August
                           31 + feb + 31 + 30 + 31 + 30 + 31 + 31, // September
                           31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30, // October
                           31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, // November
                           31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, // December
                         ];
    return aggregateMonths[date.getMonth()] + date.getDate();
}

(예, 실제로 복사 나 붙여 넣기없이 했어요. 쉬운 방법이 있으면 화를 낼 거예요)