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


119

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

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

4
var days = new Date().getFullYear() % 4 == 0 ? 366 : 365;
Alex Turpin 2011

하지만 정말 무슨 뜻인지 잘 모르겠습니다. 1 년의 일수 만 원하십니까? 아니면 두 날짜 사이에?
Alex Turpin 2011

16
fyi @ xeon06, 윤년 계산은 4로 모딩하는 것보다 조금 더 복잡합니다. 참조 : 윤년 알고리즘
Matt Felzani 2011

4
@ Xeon06 : 대부분의 경우에만 맞습니다. 에서 위키 백과 : 그들은이 경우, 400에 의해 나누어도하지 않는 한 100에 의해 균등하게 나눌 년은 윤년되지 않습니다 이다 윤년.
Cameron

아 글쎄요. @minitech가 정답을 가지고있는 것 같습니다.
Alex Turpin 2011

답변:


138

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);


5
Math.floor4 월의 특정 일 이후 예상보다 1 일 적었다. Math.ceil예상대로 작동했지만 Math.round둘 중 하나 대신 사용 하는 것이 좋습니다 .
baacke 2014 년

3
요일 구성 요소는 base-1입니다. 즉, 올해 1 월 1 일을 표현하기 위해, 당신은 사용하는 것 new Date(2014, 0, 1), 그리고 new Date(2014, 0, 0)당신이 여기 가지고있다. 의도적입니까? 아마도 그것은 new Date(2014, 0, 0)돌아올 것 12/31/2013입니다.
Kirk Woll 2014

1
아마도 사용 .setUTCHours하고 Date.UTC()더 신뢰할 수있는 솔루션.
Noyo

6
@AlexTurpin, @ T30 : 이것이 조금 오래되었다는 것을 알고 있지만 궁금한 점이 있다면 ... 문제는 3 월부터 시작되는 일광 절약 시간 때문에 발생합니다. 이는 DST 이전 날짜의 자정과 DST 이후 날짜의 자정의 차이를 계산할 때 1000 * 60 * 60 * 24로 균등하게 나눌 수있는 밀리 초 수가 없기 때문입니다 (정확히 한 시간 쉬게 됨). . 가장 쉬운 해결책은 대신를 사용 ceil하는 것입니다 floor. 이렇게하면 1 월 1 일 = 1 인 번호 매기기 시스템이 제공됩니다. 1 월 1 일 = 0을 원하면 floor최종 결과에서 1을 빼면됩니다.
Warren R.

2
시간대 및 일광 절약 시간을 고려하려면 3 행을 다음으로 변경하십시오. var diff = now - start + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
Marlon

46

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

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

1
수락 된 답변에 일광 절약과 관련된 버그가 있다는 데 동의합니다. 위의 솔루션이 더 좋고 빠릅니다. 다음은 jsPerf jsperf.com/date-getdayofyear-perf에서
Shyam Habarakada dec

@ShyamHabarakada : 벤치 마크의 코드가 손상 getDay()되었습니다 getDate().. 전자는 요일이 아닌 요일 (0 = 일요일 ..6 = 토요일)을 반환합니다.
CodeManX 2015 년

32

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

밀리 초가 너무 커서 오버플로 될 수 있습니다.
knt5784 19

@ knt5784 수학은 오버플로 될 수 있지만 그의 예제는 가능한 가장 큰 실제 값이 잘 작동하므로 정수 오버플로와 관련된 브라우저 기반 문제가없는 한 이것을 사용해도 괜찮습니다.
Per Fagrell

저는 개인적으로이 접근 방식을 좋아합니다. DST 문제를 피할 수있는 훨씬 깔끔하고 영리한 방법. DOY에서 현재로 변환하는 방법을 궁금해하는 사람이 있다면 훨씬 간단합니다. 기본적으로 1 월 DOYth의 날짜를 만듭니다. 예 : 1 월 59 일 === 2 월 28 일. 윤일은 정상적으로 처리됩니다. function doyToDate(doy, year) { return new Date(year, 0, doy); }
Kip

@ knt5784이 코드로 밀리 초 오버플로의 위험이 없습니다. 적어도 200,000 년 동안은 그렇지 않습니다. 날짜가 지원하는 최대 날짜는 new Date(8640000000000000)아직 미만이다, Number.MAX_SAFE_INTEGER. 이 답변을 참조하십시오 : stackoverflow.com/a/11526569/18511
Kip

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

alert(new Date().dayOfYear())

3
이것은 lint를 전달하지 않을 것입니다 ... 귀하의 것이 아닌 개체, 특히 전역 개체 수정. 이것은 일광 절약 시간이 12 시간 이상인 극도로 기울어 진 행성에서도 실패 할 것입니다. 그러나 좀 더 현실적으로 Date 객체의 시간대를 변경할 수있는 브라우저를 코딩하는 경우 j1의 시간대는 오스트레일리아가 될 수 있고이 시간대는 알래스카가되어 반올림이 깨질 수 있습니다.
Ray Foss

11

의 수 있으면 다행스럽게도이 질문은 지정하지 않는 현재의 일이 필요한이 답변을위한 공간을 떠나.
또한 일부 답변 (다른 질문에서도)은 윤년 문제가 있거나 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 만 필요하기 때문입니다).이 질문에 대한 답변으로 게시했습니다. 자바 스크립트로 한 달의 일 수를 결정하는 가장 좋은 방법은 무엇입니까? .


1
사용하기 쉽도록 날짜 기능에 넣었습니다. Date () 불일치가 여전히 문제이지만 2015 년 이상을 사용하고 있으므로 일관성이 있기를 바랍니다. 불쌍한 JSHint가 코드 유효성 검사를 위해 죽었습니다. 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; };
freshvolk

네가 좋다 니 기쁘다. 이 알고리즘은 0의 양쪽에서 2 ^ 31-1 년 동안 (자바 스크립트의 date-object 범위의> 7500 배인 무려 2147483647) 완전히 테스트되었습니다. ( 2 ^ 32에서도 작동 할 수 있지만 테스트하지는 않았습니다. 아직). 또한, 당신은 다시는 내 대답을 읽을 수 있습니다 당신은 면도 할 수 있습니다 +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(); };
GitaarLAB

나는 그것을보고있을 때 실제로 그것을했다! 나는 하나를 더하고 즉시 빼는 것을 깨달았습니다. 나는 우리가 2^31 - 2016지금으로부터 몇 년이 될 때 쯤이면 js는 아마도 조금 구식이 될 것이라고 생각합니다.
freshvolk

@Freshvolk : ㅋㅋ, 그래서 2 ^ 31 이상으로 테스트 한 적이 없었지만 :)그때까지는 적어도 예측 가능하고 일관된 결과를 제공 할 것입니다 하하. EDIT , 이론상 더 느린 기존의 all-modulo algo를 윤년에 사용하면 범위를 2 ^ 53으로 확장 할 수 있습니다. 월별 조회 알고리즘은 제한 요소가 아닙니다.
GitaarLAB

5

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

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

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

4

글쎄, 내가 당신을 올바르게 이해한다면 윤년에 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();
}

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


내 쉬운 방법은 매직 번호 사용 1054267675를 모두 입력 내가 게으른 방법을 해요, 그리고 하루에 전화:)
GitaarLAB

4

이것은 연중 현재 날짜를 찾는 간단한 방법이며 문제없이 윤년을 설명해야합니다.

자바 스크립트 :

Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);

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)(자바 스크립트) 또는 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로 나누어 시간을 일로 변환합니다.

참고 :이 게시물은 Google Apps Script에 구현 된 JavaScript와 JavaScript의 차이점을 설명하기 위해 편집되었습니다. 또한 답변에 대한 더 많은 컨텍스트가 추가되었습니다.


작동한다고 말하는 것보다 조금 더 설명해 주시겠습니까?
Stephen Reindl

예! 처음에 더 자세한 정보를 제공하지 못해 죄송합니다. "Math.round"문 내부의 표현식은 해당 연도의 마지막 시간의 밀리 초에서 1 년의 첫 번째 날을 빼서 현재 연도의 밀리 초 수를 찾습니다. 그런 다음 밀리 초 수를 1000으로 나누어 초로 변환하고 60을 분으로 변환하고 60을 시간으로 변환하고 24를 일로 변환합니다. 표현식은 "Math.round ()"함수 내에서 래핑되어 연중 날짜에 대한 정수로 반올림됩니다.
Liz Page-Gould

또한이 솔루션은 한 줄의 코드로 모든 작업을 수행한다는 점을 제외하면 "허용 된"솔루션과 본질적으로 동일하다는 점을 추가해야합니다.
Liz Page-Gould

이것이 일광 절약 시간을 어떻게 설명합니까? 그것은 그것을 조금 버리지 않을까요?
Dan Oswalt

아니요, 일광 절약 시간은이 계산에 영향을주지 않습니다. 일광 절약 시간에는 시간 단위가 있고이 코드는 연중 일 수를 계산하기 때문입니다. 또한 .setHours첫 번째 날짜 개체에 메서드를 사용하고 두 번째 날짜 개체에 시간을 지정 했기 때문에 일광 절약 시간에서 1 시간을 변경해도이 계산에 사용 된 날짜 개체의 시간에는 영향을주지 않습니다.
Liz Page-Gould

4

나는 이것이 더 간단하다고 생각합니다.

var date365 = 0;

var currentDate = new Date();
var currentYear = currentDate.getFullYear();
var currentMonth = currentDate.getMonth(); 
var currentDay = currentDate.getDate(); 

var monthLength = [31,28,31,30,31,30,31,31,30,31,30,31];

var leapYear = new Date(currentYear, 1, 29); 
if (leapYear.getDate() == 29) { // If it's a leap year, changes 28 to 29
    monthLength[1] = 29;
}

for ( i=0; i < currentMonth; i++ ) { 
    date365 = date365 + monthLength[i];
}
date365 = date365 + currentDay; // Done!

3

이 방법은 시간대 문제와 일광 절약 시간을 고려합니다.

function dayofyear(d) {   // d is a Date object
    var yn = d.getFullYear();
    var mn = d.getMonth();
    var dn = d.getDate();
    var d1 = new Date(yn,0,1,12,0,0); // noon on Jan. 1
    var d2 = new Date(yn,mn,dn,12,0,0); // noon on input date
    var ddiff = Math.round((d2-d1)/864e5);
    return ddiff+1; 
}

( 여기 에서 가져옴 )

바이올린 참조


이것은 약간 비효율적이지만 완벽하게 작동합니다. 개체의 시간을 얻고 setDate는 날짜를 1 일로 변경할 수 있습니다. 둘 다 완벽하게 지원됩니다. 아이디어는 시간대를 이동하지 않을 것입니다. 이것은 또한 일광 절약 시간이 12 시간 미만이라고 가정합니다. 이것은 지구상에서 안전한 가정입니다.
Ray Foss

2

Math.round ((new Date (). setHours (23)-new Date (new Date (). getFullYear (), 0, 1, 0, 0, 0)) / 1000/86400);

답변을 더욱 최적화합니다.

또한 setHours (23) 또는 마지막 2 개 0을 나중에 다른 값으로 변경하면 다른 시간대와 관련된 날짜를 제공 할 수 있습니다. 예를 들어 유럽에서 미국에있는 리소스를 검색합니다.


1
Math.floor((Date.now() - Date.parse(new Date().getFullYear(), 0, 0)) / 86400000)

이것이 내 해결책이다


전년도의 12 월 31 일을 사용하여 Jan 01 = DOY 01을 만듭니다. 또한 3 월 10 일은 3 월 11 일과 같은 DOY를가집니다. 하나는 69 개이고 다른 하나는 69.9 개 였기 때문입니다. 두 바닥은 모두 69 개였습니다. 대신 Math.round를 사용하여이 문제를 해결했습니다. . 나도 월 10 년 3 월 (11)는 매우하지 3 월 (11)의 원인이되는 일광 절약 시간 스위치입니다 생각 DOY (70)
user3015682

0

읽을 수 있고 매우 빠르게 트릭을 수행 할뿐만 아니라 다른 시간대의 JS Date 객체를 처리 할 수있는 하나를 만들었습니다.

시간대, DST, 윤초 및 윤년에 대한 몇 가지 테스트 사례를 포함했습니다.

PS ECMA-262는 UTC와 달리 윤초를 무시합니다. 이것을 실제 UTC를 사용하는 언어로 변환하려면 1을 oneDay.

// returns 1 - 366
findDayOfYear = function (date) {
  var oneDay = 1000 * 60 * 60 * 24; // A day in milliseconds
  var og = {                        // Saving original data
    ts: date.getTime(),
    dom: date.getDate(),            // We don't need to save hours/minutes because DST is never at 12am.
    month: date.getMonth()
  }
  date.setDate(1);                  // Sets Date of the Month to the 1st.
  date.setMonth(0);                 // Months are zero based in JS's Date object
  var start_ts = date.getTime();    // New Year's Midnight JS Timestamp
  var diff = og.ts - start_ts;

  date.setDate(og.dom);             // Revert back to original date object
  date.setMonth(og.month);          // This method does preserve timezone
  return Math.round(diff / oneDay) + 1; // Deals with DST globally. Ceil fails in Australia. Floor Fails in US.
}

// Tests
var pre_start_dst = new Date(2016, 2, 12);
var on_start_dst = new Date(2016, 2, 13);
var post_start_dst = new Date(2016, 2, 14);

var pre_end_dst_date = new Date(2016, 10, 5);
var on_end_dst_date = new Date(2016, 10, 6);
var post_end_dst_date = new Date(2016, 10, 7);

var pre_leap_second = new Date(2015, 5, 29);
var on_leap_second = new Date(2015, 5, 30);
var post_leap_second = new Date(2015, 6, 1);

// 2012 was a leap year with a leap second in june 30th
var leap_second_december31_premidnight = new Date(2012, 11, 31, 23, 59, 59, 999);

var january1 = new Date(2016, 0, 1);
var january31 = new Date(2016, 0, 31);

var december31 = new Date(2015, 11, 31);
var leap_december31 = new Date(2016, 11, 31);

alert( ""
  + "\nPre Start DST: " + findDayOfYear(pre_start_dst) + " === 72"
  + "\nOn Start DST: " + findDayOfYear(on_start_dst) + " === 73"
  + "\nPost Start DST: " + findDayOfYear(post_start_dst) + " === 74"
      
  + "\nPre Leap Second: " + findDayOfYear(pre_leap_second) + " === 180"
  + "\nOn Leap Second: " + findDayOfYear(on_leap_second) + " === 181"
  + "\nPost Leap Second: " + findDayOfYear(post_leap_second) + " === 182"
      
  + "\nPre End DST: " + findDayOfYear(pre_end_dst_date) + " === 310"
  + "\nOn End DST: " + findDayOfYear(on_end_dst_date) + " === 311"
  + "\nPost End DST: " + findDayOfYear(post_end_dst_date) + " === 312"
      
  + "\nJanuary 1st: " + findDayOfYear(january1) + " === 1"
  + "\nJanuary 31st: " + findDayOfYear(january31) + " === 31"
  + "\nNormal December 31st: " + findDayOfYear(december31) + " === 365"
  + "\nLeap December 31st: " + findDayOfYear(leap_december31) + " === 366"
  + "\nLast Second of Double Leap: " + findDayOfYear(leap_second_december31_premidnight) + " === 366"
);


0

이전 달의 날짜를 더하는 계산을 수행하는 솔루션을 제공하고 싶습니다.

function getDayOfYear(date) {
    var month = date.getMonth();
    var year = date.getFullYear();
    var days = date.getDate();
    for (var i = 0; i < month; i++) {
        days += new Date(year, i+1, 0).getDate();
    }
    return days;
}
var input = new Date(2017, 7, 5);
console.log(input);
console.log(getDayOfYear(input));

이렇게하면 윤년과 일광 절약의 세부 사항을 관리 할 필요가 없습니다.


0

UTC 타임 스탬프를 사용하는 대안. 또한 다른 사람들이 언급했듯이 월 1 일을 나타내는 날은 0이 아니라 1입니다. 그러나 월은 0에서 시작합니다.

var now = Date.now();
var year =  new Date().getUTCFullYear();
var year_start = Date.UTC(year, 0, 1);
var day_length_in_ms = 1000*60*60*24;
var day_number = Math.floor((now - year_start)/day_length_in_ms)
console.log("Day of year " + day_number);

0

setDate함수 에서 날짜 번호로 매개 변수를 전달할 수 있습니다 .

var targetDate = new Date();
targetDate.setDate(1);

// Now we can see the expected date as: Mon Jan 01 2018 01:43:24
console.log(targetDate);

targetDate.setDate(365);

// You can see: Mon Dec 31 2018 01:44:47
console.log(targetDate)

0

이것은 일년 중 날짜를 문자열로 필요로하고 jQuery UI를 사용할 수있는 사람들에게 유용 할 수 있습니다.

jQuery UI Datepicker를 사용할 수 있습니다.

day_of_year_string = $.datepicker.formatDate("o", new Date())

아래에서는 이미 언급 한 일부 답변 ( (date_ms - first_date_of_year_ms) / ms_per_day) 과 동일한 방식으로 작동합니다 .

function getDayOfTheYearFromDate(d) {
    return Math.round((new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime() 
- new Date(d.getFullYear(), 0, 0).getTime()) / 86400000);
}

day_of_year_int = getDayOfTheYearFromDate(new Date())

0

빠른 대안 솔루션을 원하는 사람들을 위해.

(function(){"use strict";
function daysIntoTheYear(dateInput){
    var fullYear = dateInput.getFullYear()|0;
	// "Leap Years are any year that can be exactly divided by 4 (2012, 2016, etc)
 	//	except if it can be exactly divided by 100, then it isn't (2100, 2200, etc)
 	//		except if it can be exactly divided by 400, then it is (2000, 2400)"
	// (https://www.mathsisfun.com/leap-years.html).
    var isLeapYear = ((fullYear & 3) | (fullYear/100 & 3)) === 0 ? 1 : 0;
	// (fullYear & 3) = (fullYear % 4), but faster
    //Alternative:var isLeapYear=(new Date(currentYear,1,29,12)).getDate()===29?1:0
    var fullMonth = dateInput.getMonth()|0;
    return ((
        // Calculate the day of the year in the Gregorian calendar
        // The code below works based upon the facts of signed right shifts
        //    • (x) >> n: shifts n and fills in the n highest bits with 0s 
        //    • (-x) >> n: shifts n and fills in the n highest bits with 1s
        // (This assumes that x is a positive integer)
        (31 & ((-fullMonth) >> 4)) + // January // (-11)>>4 = -1
        ((28 + isLeapYear) & ((1-fullMonth) >> 4)) + // February
        (31 & ((2-fullMonth) >> 4)) + // March
        (30 & ((3-fullMonth) >> 4)) + // April
        (31 & ((4-fullMonth) >> 4)) + // May
        (30 & ((5-fullMonth) >> 4)) + // June
        (31 & ((6-fullMonth) >> 4)) + // July
        (31 & ((7-fullMonth) >> 4)) + // August
        (30 & ((8-fullMonth) >> 4)) + // September
        (31 & ((9-fullMonth) >> 4)) + // October
        (30 & ((10-fullMonth) >> 4)) + // November
        // There are no months past December: the year rolls into the next.
        // Thus, fullMonth is 0-based, so it will never be 12 in Javascript

        (dateInput.getDate()|0) // get day of the month

    )&0xffff);
}
// Demonstration:
var date = new Date(2100, 0, 1)
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
    console.log(date.getMonth()+":\tday "+daysIntoTheYear(date)+"\t"+date);
date = new Date(1900, 0, 1);
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
    console.log(date.getMonth()+":\tday "+daysIntoTheYear(date)+"\t"+date);

// Performance Benchmark:
console.time("Speed of processing 65536 dates");
for (var i=0,month=date.getMonth()|0; i<65536; i=i+1|0)
    date.setMonth(month=month+1+(daysIntoTheYear(date)|0)|0);
console.timeEnd("Speed of processing 65536 dates");
})();

일년 중 월의 크기와 윤년의 작동 방식은 우리의 시간을 태양과 함께 유지하는 데 완벽하게 맞습니다. 도대체 완벽하게 작동하여 우리가하는 일은 단지 몇 초만 여기 저기 조정 하는 것뿐입니다 . 현재의 윤년 시스템은 1582 년 2 월 24 일 부터 시행되었으며 가까운 미래에도 계속 적용될 것입니다.

그러나 DST는 매우 변경 될 수 있습니다. 지금으로부터 20 년 후 일부 국가는 DST에 대해 하루 종일 또는 다른 극단적 인 시간으로 시간을 상쇄 할 수 있습니다. DST 하루 종일은 거의 절대 일어나지 않을 것이지만, 그럼에도 불구하고 DST는 여전히 매우 최신이며 우유부단합니다. 따라서 위의 솔루션은 매우 빠르다는 것 외에도 미래의 증거입니다.

위의 코드 조각은 매우 빠르게 실행됩니다. 내 컴퓨터는 Chrome에서 ~ 52ms 안에 65536 개의 날짜를 처리 할 수 ​​있습니다.


0

const dayOfYear = date => {
    const myDate = new Date(date);
    const year = myDate.getFullYear();
    const firstJan = new Date(year, 0, 1);
    const differenceInMillieSeconds = myDate - firstJan;
    return (differenceInMillieSeconds / (1000 * 60 * 60 * 24) + 1);
};

const result = dayOfYear("2019-2-01");
console.log(result);


0

이것은 귀찮은 Date 객체 및 시간대 문제를 피하는 솔루션이며 입력 날짜가 "yyyy-dd-mm"형식이어야합니다. 형식을 변경하려면 date_str_to_parts 함수를 수정하십시오.

    function get_day_of_year(str_date){
    var date_parts = date_str_to_parts(str_date);
    var is_leap = (date_parts.year%4)==0;
    var acct_for_leap = (is_leap && date_parts.month>2);
    var day_of_year = 0;

    var ary_months = [
        0,
        31, //jan
        28, //feb(non leap)
        31, //march
        30, //april
        31, //may
        30, //june
        31, //july
        31, //aug
        30, //sep
        31, //oct
        30, //nov   
        31  //dec
        ];


    for(var i=1; i < date_parts.month; i++){
        day_of_year += ary_months[i];
    }

    day_of_year += date_parts.date;

    if( acct_for_leap ) day_of_year+=1;

    return day_of_year;

}

function date_str_to_parts(str_date){
    return {
        "year":parseInt(str_date.substr(0,4),10),
        "month":parseInt(str_date.substr(5,2),10),
        "date":parseInt(str_date.substr(8,2),10)
    }
}

-1

수학을 날짜 함수와 혼합 할 때 항상 걱정이됩니다 (윤년 기타 세부 사항을 놓치기 쉽습니다). 당신이 가지고 있다고 :

var d = new Date();

다음을 사용하는 것이 좋습니다. 날짜는 다음 위치에 저장됩니다 day.

for(var day = d.getDate(); d.getMonth(); day += d.getDate())
    d.setDate(0);

이것이 잘 작동하지 않는 이유를 알 수 없습니다 (그리고 이것이 그렇게 집중적으로 사용되지 않기 때문에 몇 번의 반복에 대해 그렇게 걱정하지 않을 것입니다).


-1

/ *이 스크립트 사용 * /

var today = new Date();
var first = new Date(today.getFullYear(), 0, 1);
var theDay = Math.round(((today - first) / 1000 / 60 / 60 / 24) + .5, 0);
alert("Today is the " + theDay + (theDay == 1 ? "st" : (theDay == 2 ? "nd" : (theDay == 3 ? "rd" : "th"))) + " day of the year");
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.