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);
편집 : 위의 코드는 실패 할 때 now
3 월 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가 존재하지 않는이 : 대신 올해는 도약 년입니다! BC 표기법을 설명해야한다면 먼저 연도 값 (그렇지 않으면 양수)에서 1 년을 빼면됩니다 !! 0
AD/BC
1 BC
나는 (자바 스크립트의 경우) 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=3
과 3
다음 단 2 비트이며, 12*2=24
비트, 우리 모두 12개월 저장할 수 있습니다. 덧셈이 뺄셈보다 빠를 수 있으므로 오프셋을 추가합니다 (에서 빼는 대신 31
). 2 월 윤년 결정 분기를 피하기 위해 매직 조회 번호를 즉시 수정합니다.
그것은 우리에게 (아주 명백한) 첫 번째 줄을 남깁니다. 월과 날짜가 유효한 경계 내에 있는지 확인하고 false
범위 오류에 대한 반환 값을 보장 합니다 (이 함수도 0을 반환 할 수 없습니다. 여전히 1 일차입니다.), 간편한 오류 검사 제공 : if(r=dayNo(/*y, m, d*/)){}
.
(월, 일을하지 않을 수 있습니다이 방법을 사용하는 경우 0
), 다음 하나는 변경할 수 --m>=0 && m<12
에 m>0 && --m<12
(다른 문자를 저장).
나는 그것의 현재 형태의 조각을 입력하는 이유는 0 기반의 달의 값을 하나의 단지를 제거 할 필요가 있다는 점이다 --
에서 --m
.
추가 :
월별 최대 일수 만 필요한 경우에는이 날짜 별 알고리즘을 사용하지 마십시오. 이 경우 더 효율적인 알고리즘이 있습니다 (2 월일 때 leepYear 만 필요하기 때문입니다).이 질문에 대한 답변으로 게시했습니다. 자바 스크립트로 한 달의 일 수를 결정하는 가장 좋은 방법은 무엇입니까? .
글쎄, 내가 당신을 올바르게 이해한다면 윤년에 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();
}
(예, 실제로 복사하거나 붙여 넣지 않고 했어요. 쉬운 방법이 있으면 화를 낼 거예요)
이것은 연중 현재 날짜를 찾는 간단한 방법이며 문제없이 윤년을 설명해야합니다.
자바 스크립트 :
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의 차이점을 설명하기 위해 편집되었습니다. 또한 답변에 대한 더 많은 컨텍스트가 추가되었습니다.
휠을 재발 명하고 싶지 않다면 훌륭한 date-fns (node.js) 라이브러리를 사용할 수 있습니다 .
var getDayOfYear = require('date-fns/get_day_of_year')
var dayOfYear = getDayOfYear(new Date(2017, 1, 1)) // 1st february => 32
이 방법은 시간대 문제와 일광 절약 시간을 고려합니다.
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;
}
이 바이올린 참조
Math.round ((new Date (). setHours (23)-new Date (new Date (). getFullYear (), 0, 1, 0, 0, 0)) / 1000/86400);
답변을 더욱 최적화합니다.
또한 setHours (23) 또는 마지막 2 개 0을 나중에 다른 값으로 변경하면 다른 시간대와 관련된 날짜를 제공 할 수 있습니다. 예를 들어 유럽에서 미국에있는 리소스를 검색합니다.
나는 이것이 더 간단하다고 생각합니다.
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!
Math.floor((Date.now() - Date.parse(new Date().getFullYear(), 0, 0)) / 86400000)
이것이 내 해결책이다
읽을 수 있고 매우 빠르게 트릭을 수행 할뿐만 아니라 다른 시간대의 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"
);
이전 달의 날짜를 더하는 계산을 수행하는 솔루션을 제공하고 싶습니다.
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));
이렇게하면 윤년 및 일광 절약의 세부 사항을 관리 할 필요가 없습니다.
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);
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)
이것은 일년 중 날짜를 문자열로 필요로하고 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())
빠른 대안 솔루션을 원하는 사람들을 위해.
(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");
})();
The size of the months of the year and the way that Leap Years work fits perfectly into keeping our time on track with the sun. Heck, it works so perfectly that all we ever do is just adjust mere seconds here and there. Our current system of leap years has been in effect since February 24th, 1582, and will likely stay in effect for the foreseeable future.
DST, however, is very subject to change. It may be that 20 years from now, some country may offset time by a whole day or some other extreme for DST. A whole DST day will almost certainly never happen, but DST is still nevertheless very up-in-the-air and indecisive. Thus, the above solution is future proof in addition to being very very fast.
The above code snippet runs very fast. My computer can process 65536 dates in ~52ms on Chrome.
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);
It always get's me worried when mixing maths with date functions (it's so easy to miss some leap year other detail). Say you have:
var d = new Date();
I would suggest using the following, days will be saved in day
:
for(var day = d.getDate(); d.getMonth(); day += d.getDate())
d.setDate(0);
Can't see any reason why this wouldn't work just fine (and I wouldn't be so worried about the few iterations since this will not be used so intensively).
/*USE THIS SCRIPT */
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");
참고URL : https://stackoverflow.com/questions/8619879/javascript-calculate-the-day-of-the-year-1-366
'IT박스' 카테고리의 다른 글
ORM을 사용해야하는 이유는 무엇입니까? (0) | 2020.08.09 |
---|---|
MySQL에 Python datetime.datetime 객체 삽입 (0) | 2020.08.09 |
MySQL 데이터베이스 이름 바꾸기 (0) | 2020.08.09 |
Java 8이 값이나 기능을 반복하는 좋은 방법을 제공합니까? (0) | 2020.08.09 |
JavaScript에서 regex \ S는 무엇을 의미합니까? (0) | 2020.08.09 |