programing

자바스크립트는 1년 중 하루를 계산합니다 (1 - 366)

lastcode 2023. 10. 9. 23:19
반응형

자바스크립트는 1년 중 하루를 계산합니다 (1 - 366)

자바스크립트를 사용하여 1년 중 하루를 1에서 366까지 계산하는 방법은 무엇입니까?

예를 들어,

  • January 3 것입니다3.
  • February 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시 이전입니다(예: 00: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);

저는 UTC가 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) 사용 시 verified:

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.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;
};
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 object1970년 1월 1일 양일간 약 285616년(100,000,000일)을 다루고 있습니다. 저는 서로 다른 브라우저(가장 눈에 띄는 0~99년)에 걸쳐 모든 종류의 예기치 않은 날짜 불일치에 진저리가 났습니다.나는 그것을 어떻게 계산해야 하는지도 궁금했습니다.

그래서 저는 단순하고 무엇보다도 작은 알고리즘작성하여 연도, , 을 기준으로 정확한 날짜(프롤렉틱 그레고리안 / 천문학 / ISO 8601:2004(조항 4.3.2.1)를 계산했습니다. 그래서 연도는 존재하고 윤년이며 음년을 지원합니다.)
고에서는 을 참고합니다.AD/BC하지 않음:법, 0년 AD/BC음:년1 BC윤년입니다! 해야 할 에는 ( 연도 을 먼저 빼면 BC 표기법을 설명해야 하는 경우에는 (양의) 연도 값의 1년을 먼저 빼면 됩니다.!!

는 (자바스크립트용) 단락 비트마스크-모듈로 도약을 수정했습니다.연도 알고리즘사용하여 오프셋을 비트 단위로 조회할 수 있는 매직 넘버를 고안했습니다(jan과 feb는 제외). 따라서 10 * 3비트가 필요합니다(30비트는 31비트 미만이므로 비트 시프트에 안전하게 다른 문자를 저장할 수 있습니다).>>>)).

주의할 점은 월 또는 일이 모두 해당되지 않을 수 있습니다.0. 그것은 만약 당신이 단지 현재의 하루를 위해 이 방정식이 필요하다는 것을 의미합니다..getMonth()) 당신은 단지 그것을 제거하기만 하면 됩니다.----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>

다시 한 줄, 하지만 가독성을 위해 세 줄로 나누었습니다(그리고 설명하기).

마지막 줄은 위의 함수와 동일하지만, (동일한) 윤년 알고리즘은 (일 수 계산 전) 이전의 단락 구간으로 이동됩니다. 왜냐하면 특정 (윤년) 연도에 한 달에 며칠이 있는지도 알아야 하기 때문입니다.

중간 선은 다른 마법 번호를 사용하여 주어진 (도약) 연도의 특정 월에 대한 올바른 오프셋 수(최대 일 수)를 계산합니다.31-28=3그리고.32다이면 됩니다.12*2=24비트, 우리는 12개월 동안 저장할 수 있습니다. 수 신다)312월의 윤년 의사결정 분기를 피하기 위해, 우리는 그 매직 룩업 번호를 즉시 수정합니다.

이것은 우리에게 (매우 명백한) 첫 번째 줄을 남깁니다. 이것은 월과 날짜가 유효한 범위 내에 있는지 확인하고 범위 오류에 대한 반환 값을 보장합니다(이 함수 또한 1 jan 0000이 여전히 1일째이므로 0을 반환할 수 없음을 유의하십시오). 이는 쉬운 오류 검사를 제공합니다.if(r=dayNo(/*y, m, d*/)){}.
우음)이 수 )0), 그러면 변경할 수 있습니다.--m>=0 && m<12.m>0 && --m<12(다른 차를 저장합니다.)
는 0 월 값의 는 0입니다.----m.

:
참고로 한 달에 최대 하루만 필요한 경우 이 날의 월 알고리즘을 사용하지 마십시오.그 경우 더 효율적인 알고리즘이 있습니다.(잠만 자면 되기 때문입니다.)월이 2월인 연도) 이 질문에 답하기 위해 올렸습니다.자바스크립트로 한달의 일수를 결정하는 가장 좋은 방법은 무엇입니까?

이것이 제 해결책입니다.

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

데모:

const getDateOfYear = (date) =>
  Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 0)) / 864e5);

const dayOfYear = getDateOfYear(new Date());

console.log(dayOfYear);

moment.js를 사용하면 한 해의 날짜를 얻거나 설정할 수 있습니다.

moment().dayOfYear();
//for getting 

moment().dayOfYear(Number); 
//for setting 

moment.js는 이 코드를 사용하여 연도별 계산을 수행합니다.

휠을 다시 발명하지 않으려면 우수한 date-fns(node.js) 라이브러리를 사용할 수 있습니다.

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

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

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

음, 제가 당신을 제대로 이해하면 윤년에는 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 스크립트의 자바스크립트:

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)와 부터 2터재.new Date().setHours(23)가 입니다 23 입니다.Math.round().

현재 연도의 밀리초 수가 있으면 이 시간을 일로 변환하려면 1000으로 나눈 다음 60으로 나눈 다음 초를 분으로 변환하려면 60으로 나눈 다음 분을 시간으로 변환하려면 60으로 나눈 다음 24로 나눈 다음 시간을 일로 변환하면 됩니다.

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

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

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!

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

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

(여기서 가져옴)

이 fiddle 참조

Math.round((새 날짜().setHours(23) - 새 날짜(.getFullYear()), 0, 1, 0, 0, 0))/1000/86400;

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

또한 setHours(23) 또는 마지막-2 영점을 나중에 다른 값으로 변경하면 다른 시간대와 관련된 요일을 제공할 수 있습니다.예를 들어, 유럽에서 미국에 위치한 리소스를 검색하는 것입니다.

각 전월의 날짜를 추가하여 계산하는 솔루션을 제공하고자 합니다.

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

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

이것은 올해의 날을 문자열로 필요로 하고 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())

누구든 도와줄 수 있습니다.

let day = (date => {
   return Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24)
})(new Date())

읽을 수 있고 매우 빠르게 트릭을 수행할 수 있고 서로 다른 시간대로 JS Date 객체를 처리할 수 있는 것을 만들었습니다.

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

P.S. ECMA-262 는 UTC 합니다와합니다.을 실제 제 UTC한다면,지 1다에 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"
);

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)

우리 중에서 빠른 대안 해결을 원하는 사람들을 위해.

(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");
})();

1년 중 몇 달의 크기와 윤년의 작업 방식은 우리의 시간을 태양의 궤도에 맞추는 데 완벽하게 들어맞습니다.이런, 아주 완벽하게 작동하기 때문에 우리가 하는 일은 단지 몇 초 동안만 조정하는 것뿐입니다.우리의 현재 윤년 제도는 1582년 2월 24일부터 시행되고 있으며, 가까운 장래에도 시행될 것으로 보입니다.

그러나 DST는 매우 변경될 수 있습니다.지금으로부터 20년 후, 어떤 나라는 DST에 대해 하루 종일 또는 다른 극단적인 시간만큼 시간을 상쇄할지도 모릅니다.DST 하루 전체가 거의 틀림없이 일어나지 않을 것이지만, 그럼에도 불구하고 DST는 여전히 매우 희망적이고 결정적이지 않습니다.따라서 위의 솔루션은 매우 빠른 것 외에도 미래의 증거가 됩니다.

위의 코드 조각은 매우 빨리 실행됩니다.제 컴퓨터는 크롬에서 65536일을 ~52ms에 처리할 수 있습니다.

이 솔루션은 번거로운 날짜 개체 및 시간대 문제를 방지하는 솔루션으로, 입력 날짜가 "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)
    }
}

완전한 설명이 포함된 간단한 해결책.

var dayOfYear = function(date) {
  const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  const [yyyy, mm, dd] = date.split('-').map(Number);

  // Checks if February has 29 days
  const isLeap = (year) => new Date(year, 1, 29).getDate() === 29;

  // If it's a leap year, changes 28 to 29
  if (isLeap(yyyy)) daysInMonth[1] = 29;

  let daysBeforeMonth = 0;
  // Slice the array and exclude the current Month
  for (const i of daysInMonth.slice(0, mm - 1)) {
    daysBeforeMonth += i;
  }

  return daysBeforeMonth + dd;
};

console.log(dayOfYear('2020-1-3'));
console.log(dayOfYear('2020-2-1'));

저는 한 해의 날(1월 1일 = 1일)을 돌려주는 두 개의 자바스크립트 함수를 작성하였습니다.둘 다 윤년을 설명합니다.

function dayOfTheYear() {
// for today
var M=[31,28,31,30,31,30,31,31,30,31,30,31]; var x=new Date(); var m=x.getMonth();
var y=x.getFullYear(); if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) {++M[1];}
var Y=0; for (var i=0;i<m;++i) {Y+=M[i];}
return Y+x.getDate();
}

function dayOfTheYear2(m,d,y) {
// for any day : m is 1 to 12, d is 1 to 31, y is a 4-digit year
var m,d,y; var M=[31,28,31,30,31,30,31,31,30,31,30,31];
if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) {++M[1];}
var Y=0; for (var i=0;i<m-1;++i) {Y+=M[i];}
return Y+d;
}

한 줄:

Array.from(new Array(new Date().getMonth()), (x, i) => i).reduce((c, p, idx, array)=>{
            let returnValue =  c + new Date(new Date().getFullYear(), p, 0).getDate();
            if(idx == array.length -1){
                returnValue = returnValue + new Date().getDate();
            }
            return returnValue;
        }, 0)

이 기능을 많이 활용하는 애플리케이션을 위해 신뢰할 수 있는 ( 도약 연도시간대에 대한 저항성) 알고리즘이 필요했습니다. 90년대에 작성된 알고리즘을 발견했는데 아직도 효율적이고 안정적인 솔루션이 없다는 것을 알게 되었습니다.

function dayOfYear1 (date) {
    const year = date.getFullYear();
    const month = date.getMonth()+1;
    const day = date.getDate();

    const N1 = Math.floor(275 * month / 9);
    const N2 = Math.floor((month + 9) / 12);
    const N3 = (1 + Math.floor((year - 4 * Math.floor(year / 4) + 2) / 3));
    const N = N1 - (N2 * N3) + day - 30;
    return N;
}

알고리즘은 윤년에 정확하게 작동하며, 날짜()가 있는 시간대에 따라 달라지지 않으며, 또한 하위 시간대보다 효율적입니다.

function dayOfYear2 (date) {
    const monthsDays = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
    const year = date.getFullYear();
    const month = date.getMonth();
    const day = date.getDate();
    let N = monthsDays[month] + day;
    if ( month>1 && year%4==0 ) 
        N++;
    return N;
}


function dayOfYear3 (date) {
    const yearDate = new Date(date.getFullYear(), 0, 0);
    const timeZoneDiff = yearDate.getTimezoneOffset() - date.getTimezoneOffset();
    const N = Math.floor(((date - yearDate )/1000/60 + timeZoneDiff)/60/24);
    return N;
}

모두 정확하고 위에 언급된 조건으로 작동합니다.100k 루프에서의 성능 비교:

dayOf Year1 - 15ms

dayOf Year2 - 17ms

dayOf Year 3 - 80ms

한 줄로 대답하면 다음과 같습니다.

const today = new Date();
const dayOfYear = Math.floor((today - new Date(today.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
console.log(dayOfYear);

수학과 날짜 함수를 혼합할 때 항상 걱정이 됩니다. (윤년도 다른 세부 사항을 놓치기 쉽습니다.)예를 들어 다음과 같이 하십시오.

var d = new Date();

을 사용하여 에서 일수를 날짜가 절약됩니다.day:

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

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

언급URL : https://stackoverflow.com/questions/8619879/javascript-calculate-the-day-of-the-year-1-366

반응형