javascript add value month - javascript

I'm creating a system and I need to add a value on a variable every month. For example, Last January I have 5 vacation leaves and every month I need to add 1 leave. A breakdown would be something like this:
January = 5 leaves
February = 6 leaves (I used up 2 leaves during this month, leaving me with 4 leaves)
March = 5 leaves
April = 6 leaves
so on and so forth.
What approach or how will I able to accomplish it?
Thanks a lot!!

If it's just the calculation, then you can add months by doing d.setMonth(d.getMonth() + 1). This makes Date do all the messy stuff of working out how long each month is.
var initial_value = 5,
initial_date = new Date(2014, 0, 1), // January
end_date = new Date(2014, 3, 1); // April
var spent = 2;
var value = initial_value,
date = new Date(initial_date);
while (date.setMonth(date.getMonth() + 1), date <= end_date)
value += 1;
value -= spent;
value; // 6
This method is good for days of month < 29, for days 29 <= x <= 31 you will need additional checks
i.e. check how many months it changed by then if not 1, what behaviour do you want in those cases?
If you always want the last day of the month, then it's only a couple steps longer than above,
d.setDate(1); // go to a "safe day" to change months
d.setMonth(d.getMonth() + 2); // go 2 months forward
d.setDate(0); // roll back to the last day of the previous month
Something extra I've been playing with
var dates = (function () {
function isLeapYear(year) {
if (year % 4) // not divisible by 4
return false;
if (year % 100) // not divisible by 100
return true;
if (year % 400) // not divisible by 400
return false;
return true;
}
return {
year: new Date().getUTCFullYear(),
get leapYear() { return isLeapYear(this.year); },
isLeapYear: isLeapYear,
get total() { return 365 + isLeapYear(this.year); },
0: 31,
get 1() { return 28 + isLeapYear(this.year); },
2: 31,
3: 30,
4: 31,
5: 30,
6: 31,
7: 31,
8: 30,
9: 31,
10: 30,
11: 31
};
}());

I use this when adding months to a date and I don't want to overflow the month:
function addMonthsNoOverflow(dateParam, intParam) {
var sum = new Date(new Date(dateParam.getTime()).setMonth(dateParam.getMonth() + intParam);
if (sum.getDate() < dateParam.getDate()) { sum.setDate(0); }
return(sum);
}
Notes:
It handles cases where 29, 30 or 31 turned into 1, 2, or 3 by eliminating the overflow
Day of Month is NOT zero-indexed so .setDate(0) is last day of prior month.

Related

Exclude every 6th and 7th day from given two dates using jquery or javascript

I need to exclude every 6th and 7th day from two dates and return number of days.
For example start date is 1st sep and end date is 30th sep, then the result should be 4 + 4 = 8 days.
If I take total number of days and divide it by 7 then I can get how many 7th days occur, but for 6th days, this logic is failing.
Problem here is I need to check every 6th and 7th days after 7th day. I mean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
x x x x x x
Any simple logic I am missing here?
Its very simple logic:
var start = 1, end = 31, current = 0;
while(current <=end){
var next = current + 6, next1 = next+1;
//If you want to print other then 6th and 7th
for(var i = current +1; i< next && i <=end; i++)
console.log(i);
/*if(next <= end)
console.log(next); //Or do what you want with this.
if(next1 <= end)
console.log(next1); //Or do what you want with this.*/
current = next1;
}
I'm not entirely sure what you're trying to accomplish. My answer will leave out each 6th and 7th day of any given date range.
All days will be added to the result array, except for the 6n-th and 7n-th. The rejected days will be logged to the console so you can better see which days are rejected by the method.
const
millisecondsPerDay = 24 * 60 * 60 * 1000;
function createArrayWithDays(start, end) {
const
result = [],
// Calculate the diference between the start and end.
dateDifference = end.getTime() - start.getTime(),
// Convert the milliseconds back to days and add 1 to make the end date inclusive of the range.
days = (dateDifference / millisecondsPerDay) + 1;
let
currentDate = new Date(start);
// Iterate over the number of days in the range.
for (let day=1; day <= days; day++) {
// When the current index can be divided by 6 or 7 the modulo is 0 and the day should be in the result array.
if (
day % 6 !== 0 &&
day % 7 !== 0
) {
result.push(currentDate.getDate());
} else {
console.log(`Reject ${currentDate.toDateString()} it is the 6n-th or 7n-th day of the range.`);
}
// Continue to the next date;
currentDate.setDate(currentDate.getDate() + 1);
}
return result;
}
console.log('Days for September');
console.log(createArrayWithDays(new Date(2017, 8, 1), new Date(2017, 8, 30)));
console.log('Days for mid Sept to mid Oct');
console.log(createArrayWithDays(new Date(2017, 8, 15), new Date(2017, 9, 15)));
If you just want the total number, you could do this:
const
millisecondsPerDay = 24 * 60 * 60 * 1000;
function numberOfDays(start, end) {
const
result = [],
// Calculate the diference between the start and end.
dateDifference = end.getTime() - start.getTime(),
// Convert the milliseconds back to days and add 1 to make the
// end date inclusive of the range.
days = (dateDifference / millisecondsPerDay) + 1,
// Calculate the number of days that don't make up a full week
// but this should never be more than 5.
rest = Math.min(5, days % 7),
// Calculate the number of full weeks in the range
weeks = Math.floor(days/7);
// For each week, leave out 2 days and add the rest.
return (weeks * 5) + rest;
}
console.log('Days for September');
console.log(numberOfDays(new Date(2017, 8, 1), new Date(2017, 8, 30)));
console.log('Days for mid Sept to mid Oct');
console.log(numberOfDays(new Date(2017, 8, 15), new Date(2017, 9, 15)));
console.log('Days when a range of 6 days');
console.log(numberOfDays(new Date(2017, 8, 1), new Date(2017, 8, 6)));
Make a function like:
function numberOfDays(days) {
const c67 = 6/7.;
var days7 = days / 7.;
return days - (Math.floor(days7) * 2) - ((days7 - Math.floor(days7)) >= c67 ? 1 : 0);
}
Then just pass it the total number of days and it will return the number of days without 6th and 7th days.
Logic:
c67 simbolises the ratio of 6 / 7, because every 7 days MUST have day 6 also, but we can have 6 days without 7th day
days7 calculate the occurance of 7 days (as float) - note the dot
from the total number of days subtract a total number of 7 day occurrences times 2 (since they also have day 6) Math.floor(days7) * 2
check if the remaining value of the division is equal to the constant, if it is, then the number of days is 6 and we need to subtract another day, if not then the number of days is 5 or less
Hope this helps
Tested values:
numberOfDays(5) // 5
numberOfDays(6) // 5
numberOfDays(7) // 5
numberOfDays(8) // 6
numberOfDays(20) // 15
numberOfDays(21) // 15
numberOfDays(22) // 16
https://jsfiddle.net/ye21m683/ Fiddle example
I ended up doing following simple logic
var counter = 1;
var daysAfterSixSvn = 0;
for (var i = 1; i <= days; i++)
{
if (counter == 6) {
counter = counter;
}
else if(counter == 7){
counter = 0;
}
else{
daysAfterSixSvn = daysAfterSixSvn + 1;
}
counter = counter + 1;
}
console.log(daysAfterSixSvn);

populate dates in dropdown using javascript [duplicate]

I've been using this function but I'd like to know what's the most efficient and accurate way to get it.
function daysInMonth(iMonth, iYear) {
return 32 - new Date(iYear, iMonth, 32).getDate();
}
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.
Day 0 is the last day in the previous month. Because the month constructor is 0-based, this works nicely. A bit of a hack, but that's basically what you're doing by subtracting 32.
See more :
Number of days in the current month
Some answers (also on other questions) had leap-year problems or used the Date-object. Although javascript's Date object covers approximately 285616 years (100,000,000 days) on either side of January 1 1970, I was fed up with all kinds of unexpected date inconsistencies across different browsers (most notably year 0 to 99). I was also curious how to calculate it.
So I wrote a simple and above all, small algorithm to calculate the correct (Proleptic Gregorian / Astronomical / ISO 8601:2004 (clause 4.3.2.1), so year 0 exists and is a leap year and negative years are supported) number of day's for a given month and year.
It uses the short-circuit bitmask-modulo leapYear algorithm (slightly modified for js) and common mod-8 month algorithm.
Note that in AD/BC notation, year 0 AD/BC does not exist: instead year 1 BC is the leap-year!
IF you need to account for BC notation then simply subtract one year of the (otherwise positive) year-value first!! (Or subtract the year from 1 for further year-calculations.)
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>
Note, months must be 1-based!
Note, this is a different algorithm then the magic number lookup I used in my Javascript calculate the day of the year (1 - 366) answer, because here the extra branch for the leap-year is only needed for February.
If you call this function often, it may be useful to cache the value for better performance.
Here is caching version of FlySwat's answer:
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();
}
})();
With moment.js you can use daysInMonth() method:
moment().daysInMonth(); // number of days in the current month
moment("2012-02", "YYYY-MM").daysInMonth() // 29
moment("2012-01", "YYYY-MM").daysInMonth() // 31
To take away confusion I would probably make the month string based as it is currently 0 based.
function daysInMonth(month,year) {
var 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
One-liner direct computation (no Date object):
//m is 0-based, Jan = 0, Dec = 11
function daysInMonth(m,y){
return 31-(m-1?m%7&1:y&(y%25?3:15)?3:2);
}
console.log(daysInMonth(1, 2003), "days in February in the non-leap year 2003");
console.log(daysInMonth(1, 2004), "days in February in the leap year 2004");
console.log(daysInMonth(1, 2100), "days in February in the non-leap year 2100");
console.log(daysInMonth(1, 2000), "days in February in the leap year 2000");
console.log(daysInMonth(0, 2022), "days in January 2022");
console.log(daysInMonth(1, 2022), "days in February 2022");
console.log(daysInMonth(2, 2022), "days in March 2022");
console.log(daysInMonth(3, 2022), "days in April 2022");
console.log(daysInMonth(4, 2022), "days in May 2022");
console.log(daysInMonth(5, 2022), "days in June 2022");
console.log(daysInMonth(6, 2022), "days in July 2022");
console.log(daysInMonth(7, 2022), "days in August 2022");
console.log(daysInMonth(8, 2022), "days in September 2022");
console.log(daysInMonth(9, 2022), "days in October 2022");
console.log(daysInMonth(10, 2022), "days in November 2022");
console.log(daysInMonth(11, 2022), "days in December 2022");
Explanation
The main idea is to assume that months have 31 days, but subtract 1 if the month is April, June, September, or November; subtract 2 if the month is February in a leap year; or subtract 3 if the month is February in a non-leap year.
In the ternary expression (m - 1 ? /* Not February */ : /* February */), the expression m - 1 checks whether the month is February.
For other months than February, the expression m % 7 makes m even for months with 31 days, and odd for the rest. Subtracting the lowest bit (& 1) results in 31 − 1 days for April, June, September, and November, and 31 − 0 days for the rest.
For February, the expression y & (y % 25 ? 3 : 15) is falsy for leap years, resulting in 31 − 2 days in February. Otherwise, February is 31 − 3 days.
Here is goes
new Date(2019,2,0).getDate(); //28
new Date(2020,2,0).getDate(); //29
May be bit over kill when compared to selected answer :) But here it is:
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));
I found the above code over here: 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));
I found the above code over here: https://github.com/datejs/Datejs/blob/master/src/core.js
ES6 syntax
const d = (y, m) => new Date(y, m, 0).getDate();
returns
console.log( d(2020, 2) );
// 29
console.log( d(2020, 6) );
// 30
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
}
Considering leap years:
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];
}
If you want the number of days in the current month of a Date object, consider the following method:
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();
}
}
Then you can run it like this:
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!
In a single line:
// 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;
}
Perhaps not the most elegant solution, but easy to understand and maintain; and, it's battle-tested.
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;
},
If you are going to pass a date variable this may helpful
const getDaysInMonth = date =>
new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
daysInThisMonth = getDaysInMonth(new Date());
console.log(daysInThisMonth);
One-liner, without using Date objects:
const countDays = (month, year) => 30 + (month === 2 ? (year % 4 === 0 && 1) - 2 : (month + Number(month > 7)) % 2);
returns:
countDays(11,2020) // 30
countDays(2,2020) // 29
countDays(2,2021) // 28
To get the number of days in the current month
var nbOfDaysInCurrentMonth = new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), 0)).getDate()
console.log(nbOfDaysInCurrentMonth)
You can get days in month by this command:
new Date(year, month, 0).getDate();
Try this - it returns dictionary with month: days mapping, I think it will be very useful in most cases when people enter this topic:
const getMonthsDaysForYear = (year) => {
let monthDaysDictionary = {};
for(let i = 1; i <= 11; i++) {
const date = new Date(year, i + 1, 0);
const monthName = date.toLocaleString('en-GB', { month: 'long' });
monthDaysDictionary[monthName] = date.getDate();
}
return monthDaysDictionary;
}
getMonthsDaysForYear(2022);
Note: that month should be started with 1 as it is mentioned in this answer.
See my function and a test of it:
function numberOfDays(year, month)
{
// Reference:
// https://arslankuyumculuk.com/how-to-calculate-leap-year-formula/ (2022-05-20 16:45 UTC)
numDays=0;
switch(month)
{
case 1:
numDays=31;
break;
case 2:
numDays=28;
break;
case 3:
numDays=31;
break;
case 4:
numDays=30;
break;
case 5:
numDays=31;
break;
case 6:
numDays=30;
break;
case 7:
numDays=31;
break;
case 8:
numDays=31;
break;
case 9:
numDays=30;
break;
case 10:
numDays=31;
break;
case 11:
numDays=30;
break;
case 12:
numDays=31;
break;
}
if(month==2)
{
if( (year % 100) == 0 )
{
if( (year % 400) == 0 )
{
numDays=29;
}
}
else
{
if( (year % 4) == 0 )
{
numDays=29;
}
}
}
//
return numDays;
}
// Test:
const years = [2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2100,2400];
month=2;
for (let i = 0; i < years.length; i++)
{
let text = "";
text += years[i] + '/' + month.toString() + ": " + numberOfDays(years[i], month).toString();
alert(text);
}
for (let m = 1; m <= 12; m++)
{
let text2 = "";
text2 += "2022/" + m.toString() + ": " + numberOfDays(2022, m).toString();
alert(text2);
}
#Tomas Langkaas : I've implemented essentially the same function you've mentioned above in awk, with some minor improvements :
using conventional arithmetic instead of bit-wise AND ( & ), plus not using implementation-dependent features, making it fully POSIX-awk-complaint and portable (tested and confirmed working on mawk, gawk, and nawk)
2. user can now directly input actual month numbers of 1 - 12 instead of having to remember to pre-adjust them to 0 - 11
instead of relying on hard-coded numerics, every constant, offset, modulo base etc now dynamically generated on the fly by the function itself ,
while simultaneously being extremely temp variables efficient by recycling both the input month and year variables the moment their original values are no longer required, thus
when February is being called without a year-value, it defaults to NOT-being a leap year, regardless of what the present year is
{m,g,n}awk '
function _____(_,__) {
#
# _| Month mm: [1-12]
# __| Year yyyy:
# |---> #-days:
# in yyyy:mm: combo
return -(\
_^(_<_) != --_ \
? (_ %((_+=_+=_^=_<_) +--_)) %--_\
: (_+=_^=_<_) + (__ == "" ||
__ % (_+=_) ||
__% (_*(_*=_++)+_) == ! (__ % (_*_))\
) ) \
-(_^=_<_) -+- ++_^_^_*_
}'
2 1600 29
2 1700 28
2 1800 28
2 1868 29
2 1900 28
2 1912 29
2 1956 29
2 2000 29
2 2012 29
2 2016 29
2 2018 28
2 2020 29
2 2022 28
2 2024 29

Calculate Final Due Date In JavaScript From Term

I need to find a way to calculate the final due date of a loan using JavaScript, but need to account for months with less than 31 or 30 days.
For example, if I have a term of 60 months (5 years) and my start_date is 01/31/2015, my final due date would be 12/31/2019. Now, if my term was 62 months, my final due date would be 02/28/2020. The problem with most JavaScript math is that I get a result of 03/03/2020 which is not correct. Any ideas?
This is not well-tested, but it might do what you want. It involves redoing some of the calculations that the Date API does automatically, but they're not too difficult:
var addMonths = (function() {
var counts = {
normal: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
leap: [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
};
return function(startDate, months) {
var endYear = startDate.getFullYear() + Math.ceil((months + startDate.getMonth()) / 12) - 1;
var yearType = ((endYear % 4 == 0) && (endYear % 100 != 0)) || (endYear % 400 == 0) ? 'leap' : 'normal';
var endMonth = (startDate.getMonth() + months) % 12;
var endDate = Math.min(startDate.getDate(), counts[yearType][endMonth]);
return new Date(endYear, endMonth, endDate);
};
}());
var date = new Date(2015, 0, 31); // 2015-01-31
addMonths(date, 60); //=> 2020-01-31
addMonths(date, 61); //=> 2020-02-29
addMonths(date, 62); //=> 2020-03-31
addMonths(date, 63); //=> 2020-04-30
addMonths(date, 73); //=> 2021-02-28
Note that my numbers seem to be a month off from yours. I'm guessing you're using a first-payment as your start date, and not actually adding a full complement of, say, 62 months to it. But obviously this would be easy to adjust by one if you so desired.
Add the number of years and months you want, then find the last day of that month. Javascript date addition will give you the results you found so it takes a couple of extra steps:
function addMonths(month, year, term) {
var endTerm = term - 1; // adjust for zero index
var newYear = year + parseInt(endTerm / 12); // add the years
var newMonth = month + (endTerm % 12); // add the remaining months
if (newMonth > 12) { // remaining months into next year?
newYear = newYear + 1;
newMonth = newMonth - 12;
}
var endDate = new Date(newYear, newMonth, 0); // get last day of month
return endDate;
}
This solution meets the parameters you set. You'll need to check for corner cases. For example, a term of 1 month gives an end date of the current month, a term of 2 months gives an end date of next month.
This is a very simple solution for your specific problem. If you're going to do a bunch of date manipulation then consider using a library.
Here's a real quick jsFiddle: https://jsfiddle.net/8gnb0s0s/3/

Is there an easy way to find the last date a day of week occurs in the current month

I am trying to display the date of the last Wednesday in the current month... so that it will automatically change to the correct date when the next month occurs. (So instead of having to say: "Performing the last wednesday of every month", I can dymanmically give the actual date.)
For example, I would want the date to show on the webpage as Wednesday, Sept 25th for this month, and then appear as Wednesday, Oct 30th next month.
A bonus additional solution would be if I could get the next month's date to display after the previous date has past. In my above example, when the current date is Sept 26-30 (any date after that last wednesday, but still in the same month).. the date would show the next performance date of Oct 30th.
It would be great if the solution was through html, javascript/jquery or asp.
Thanks,
SunnyOz
It depends on your criteria for "easy". Here's a simple function to do as required, it's 5 lines of working code that can be reduced to 4, but will lose a bit of clarity if that's done:
function lastDayInMonth(dayName, month, year) {
// Day index map - modify to suit whatever you want to pass to the function
var dayNums = {Sunday: 0, Monday:1, Tuesday:2, Wednesday:3,
Thursday:4, Friday:5, Saturday:6};
// Create a date object for last day of month
var d = new Date(year, month, 0);
// Get day index, make Sunday 7 (could be combined with following line)
var day = d.getDay() || 7;
// Adjust to required day
d.setDate(d.getDate() - (7 - dayNums[dayName] + day) % 7);
return d;
}
You can change the map to whatever, just determine what you want to pass to the function (day name, abbreviation, index, whatever) that can be mapped to an ECMAScript day number.
Edit
So in the case of always wanting to show the last Wednesday of the month or next month if it's passed:
function showLastWed() {
var now = new Date();
var lastWedOfThisMonth = lastDayInMonth('Wednesday', now.getMonth()+1, now.getFullYear());
if (now.getDate() > lastWedOfThisMonth().getDate()) {
return lastDayInMonth('Wednesday', now.getMonth()+2, now.getFullYear());
} else {
return lastWedOfThisMonth;
}
}
Note that the function expects the calendar month number (Jan = 1, Feb = 2, etc.) whereas the getMonth method returns the ECMAScript month index (Jan = 0, Feb = 1, etc.) hence the +1 and +2 to get the calendar month number.
You could use a javascript library such as moment.js:
http://momentjs.com/
and then get it with this:
moment().add('months', 1).date(1).subtract('days', 1).day(-4)
Here is an approach in JS:
var monthLengths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
function getLastWednesday() {
var d = new Date();
var month = d.getMonth();
var lastDay = monthLengths[month];
// mind leap years
if (month == 1) {
var year = d.getFullYear();
var isLeapYear = ((year % 4 == 0 && year % 100 > 0) || year % 400 == 0);
if (isLeapYear) lastDay++;
}
// get the weekday of last day in the curent mont
d.setDate(lastDay);
var weekday = d.getDay();
// calculate return value (wednesday is day 3)
if (weekday == 3) {
return lastDay;
}
else {
var offset = weekday - 3;
if (offset < 0) offset += 7;
return lastDay - offset;
}
}
I prefer to use an abstraction like moment.js as #Aralo suggested. To do it in raw JavaScript, however, you can use some code like this... create a function that gets all the days in a month. Then reverse-traverse the list to find the last day number. Wednesday is 3.
function getDaysInMonth(date) {
var dayCursor = new Date(today.getFullYear(), today.getMonth()); // first day of month
var daysInMonth = [];
while(dayCursor.getMonth() == date.getMonth()) {
daysInMonth.push(new Date(dayCursor));
dayCursor.setDate(dayCursor.getDate() + 1);
}
return daysInMonth;
}
function findLastDay(date, dayNumber) {
var daysInMonth = getDaysInMonth(date);
for(var i = daysInMonth.length - 1; i >= 0; i--) {
var day = daysInMonth[i];
if(day.getDay() === dayNumber) return day;
}
}
Then, to get the last Wednesday in the current month:
var today = new Date();
var lastWednesday = findLastDay(today, 3);

JavaScript calculate the day of the year (1 - 366)

How do I use JavaScript to calculate the day of the year, from 1 - 366?
For example:
January 3 should be 3.
February 1 should be 32.
Following OP's edit:
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);
Edit: The code above will fail when now is a date in between march 26th and October 29th andnow's time is before 1AM (eg 00:59:59). This is due to the code not taking daylight savings time into account. You should compensate for this:
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);
I find it very interesting that no one considered using UTC since it is not subject to DST. Therefore, I propose the following:
function daysIntoYear(date){
return (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000;
}
You can test it with the following:
[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`));
Which outputs for the leap year 2016 (verified using 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
This works across Daylight Savings Time changes in all countries (the "noon" one above doesn't work in Australia):
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())
Luckily this question doesn't specify if the number of the current day is required, leaving room for this answer.
Also some answers (also on other questions) had leap-year problems or used the Date-object. Although javascript's Date object covers approximately 285616 years (100,000,000 days) on either side of January 1 1970, I was fed up with all kinds of unexpected date inconsistencies across different browsers (most notably year 0 to 99). I was also curious how to calculate it.
So I wrote a simple and above all, small algorithm to calculate the correct (Proleptic Gregorian / Astronomical / ISO 8601:2004 (clause 4.3.2.1), so year 0 exists and is a leap year and negative years are supported) day of the year based on year, month and day.
Note that in AD/BC notation, year 0 AD/BC does not exist: instead year 1 BC is the leap-year! IF you need to account for BC notation then simply subtract one year of the (otherwise positive) year-value first!!
I modified (for javascript) the short-circuit bitmask-modulo leapYear algorithm and came up with a magic number to do a bit-wise lookup of offsets (that excludes jan and feb, thus needing 10 * 3 bits (30 bits is less than 31 bits, so we can safely save another character on the bitshift instead of >>>)).
Note that neither month or day may be 0. That means that if you need this equation just for the current day (feeding it using .getMonth()) you just need to remove the -- from --m.
Note this assumes a valid date (although error-checking is just some characters more).
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>
Here is the version with correct range-validation.
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>
Again, one line, but I split it into 3 lines for readability (and following explanation).
The last line is identical to the function above, however the (identical) leapYear algorithm is moved to a previous short-circuit section (before the day-number calculation), because it is also needed to know how much days a month has in a given (leap) year.
The middle line calculates the correct offset number (for max number of days) for a given month in a given (leap)year using another magic number: since 31-28=3 and 3 is just 2 bits, then 12*2=24 bits, we can store all 12 months. Since addition can be faster then subtraction, we add the offset (instead of subtract it from 31). To avoid a leap-year decision-branch for February, we modify that magic lookup-number on the fly.
That leaves us with the (pretty obvious) first line: it checks that month and date are within valid bounds and ensures us with a false return value on range error (note that this function also should not be able to return 0, because 1 jan 0000 is still day 1.), providing easy error-checking: if(r=dayNo(/*y, m, d*/)){}.
If used this way (where month and day may not be 0), then one can change --m>=0 && m<12 to m>0 && --m<12 (saving another char).
The reason I typed the snippet in it's current form is that for 0-based month values, one just needs to remove the -- from --m.
Extra:
Note, don't use this day's per month algorithm if you need just max day's per month. In that case there is a more efficient algorithm (because we only need leepYear when the month is February) I posted as answer this question: What is the best way to determine the number of days in a month with javascript?.
If used moment.js, we can get or even set the day of the year.
moment().dayOfYear();
//for getting
moment().dayOfYear(Number);
//for setting
moment.js is using this code for day of year calculation
If you don't want to re-invent the wheel, you can use the excellent date-fns (node.js) library:
var getDayOfYear = require('date-fns/get_day_of_year')
var dayOfYear = getDayOfYear(new Date(2017, 1, 1)) // 1st february => 32
This is my solution:
Math.floor((Date.now() - new Date(new Date().getFullYear(), 0, 0)) / 86400000)
Demo:
const getDateOfYear = (date) =>
Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 0)) / 864e5);
const dayOfYear = getDateOfYear(new Date());
console.log(dayOfYear);
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);
Well, if I understand you correctly, you want 366 on a leap year, 365 otherwise, right? A year is a leap year if it's evenly divisible by 4 but not by 100 unless it's also divisible by 400:
function daysInYear(year) {
if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
// Leap year
return 366;
} else {
// Not a leap year
return 365;
}
}
Edit after update:
In that case, I don't think there's a built-in method; you'll need to do this:
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();
}
(Yes, I actually did that without copying or pasting. If there's an easy way I'll be mad)
This is a simple way to find the current day in the year, and it should account for leap years without a problem:
Javascript:
Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);
Javascript in Google Apps Script:
Math.round((new Date().setHours(23) - new Date(new Date().getYear(), 0, 1, 0, 0, 0))/1000/60/60/24);
The primary action of this code is to find the number of milliseconds that have elapsed in the current year and then convert this number into days. The number of milliseconds that have elapsed in the current year can be found by subtracting the number of milliseconds of the first second of the first day of the current year, which is obtained with new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0) (Javascript) or new Date(new Date().getYear(), 0, 1, 0, 0, 0) (Google Apps Script), from the milliseconds of the 23rd hour of the current day, which was found with new Date().setHours(23). The purpose of setting the current date to the 23rd hour is to ensure that the day of year is rounded correctly by Math.round().
Once you have the number of milliseconds of the current year, then you can convert this time into days by dividing by 1000 to convert milliseconds to seconds, then dividing by 60 to convert seconds to minutes, then dividing by 60 to convert minutes to hours, and finally dividing by 24 to convert hours to days.
Note: This post was edited to account for differences between JavaScript and JavaScript implemented in Google Apps Script. Also, more context was added for the answer.
I think this is more straightforward:
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!
This method takes into account timezone issue and daylight saving time
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;
}
(took from here)
See also this fiddle
Math.round((new Date().setHours(23) - new Date(new Date().getFullYear(), 0, 1, 0, 0, 0))/1000/86400);
further optimizes the answer.
Moreover, by changing setHours(23) or the last-but-two zero later on to another value may provide day-of-year related to another timezone.
For example, to retrieve from Europe a resource located in America.
This might be useful to those who need the day of the year as a string and have jQuery UI available.
You can use jQuery UI Datepicker:
day_of_year_string = $.datepicker.formatDate("o", new Date())
Underneath it works the same way as some of the answers already mentioned ((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())
maybe help anybody
let day = (date => {
return Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24)
})(new Date())
I've made one that's readable and will do the trick very quickly, as well as handle JS Date objects with disparate time zones.
I've included quite a few test cases for time zones, DST, leap seconds and Leap years.
P.S. ECMA-262 ignores leap seconds, unlike UTC. If you were to convert this to a language that uses real UTC, you could just add 1 to 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"
);
I would like to provide a solution that does calculations adding the days for each previous month:
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));
This way you don't have to manage the details of leap years and daylight saving.
A alternative using UTC timestamps. Also as others noted the day indicating 1st a month is 1 rather than 0. The month starts at 0 however.
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);
You can pass parameter as date number in setDate function:
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)
For those among us who want a fast alternative solution.
(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.
This is a solution that avoids the troublesome Date object and timezone issues, it requires that your input date be in the format "yyyy-dd-mm". If you want to change the format, then modify date_str_to_parts function:
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)
}
}
A straightforward solution with complete explanation.
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'));
I wrote these two javascript functions which return the day of the year (Jan 1 = 1).
Both of them account for leap years.
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;
}
One Line:
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)
I needed a reliable (leap year and time zone resistant) algorithm for an application that makes heavy use of this feature, I found some algorithm written in the 90s and found that there is still no such efficient and stable solution here:
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;
}
Algorithm works correctly in leap years, it does not depend on time zones with Date() and on top of that it is more efficient than any of the lower ones:
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;
}
All of them are correct and work under the conditions mentioned above.
Performance comparison in 100k loop:
dayOfYear1 - 15 ms
dayOfYear2 - 17 ms
dayOfYear3 - 80 ms
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).

Categories

Resources