How do I get the current weeknumber of the year, like PHP's date('W')?
It should be the ISO-8601 week number of year, weeks starting on Monday.
You should be able to get what you want here: http://www.merlyn.demon.co.uk/js-date6.htm#YWD.
A better link on the same site is: Working with weeks.
Edit
Here is some code based on the links provided and that posted eariler by Dommer. It has been lightly tested against results at http://www.merlyn.demon.co.uk/js-date6.htm#YWD. Please test thoroughly, no guarantee provided.
Edit 2017
There was an issue with dates during the period that daylight saving was observed and years where 1 Jan was Friday. Fixed by using all UTC methods. The following returns identical results to Moment.js.
/* For a given date, get the ISO week number
*
* Based on information at:
*
* THIS PAGE (DOMAIN EVEN) DOESN'T EXIST ANYMORE UNFORTUNATELY
* http://www.merlyn.demon.co.uk/weekcalc.htm#WNR
*
* Algorithm is to find nearest thursday, it's year
* is the year of the week number. Then get weeks
* between that date and the first day of that year.
*
* Note that dates in one year can be weeks of previous
* or next year, overlap is up to 3 days.
*
* e.g. 2014/12/29 is Monday in week 1 of 2015
* 2012/1/1 is Sunday in week 52 of 2011
*/
function getWeekNumber(d) {
// Copy date so don't modify original
d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay()||7));
// Get first day of year
var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
// Calculate full weeks to nearest Thursday
var weekNo = Math.ceil(( ( (d - yearStart) / 86400000) + 1)/7);
// Return array of year and week number
return [d.getUTCFullYear(), weekNo];
}
var result = getWeekNumber(new Date());
document.write('It\'s currently week ' + result[1] + ' of ' + result[0]);
Hours are zeroed when creating the "UTC" date.
Minimized, prototype version (returns only week-number):
Date.prototype.getWeekNumber = function(){
var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate()));
var dayNum = d.getUTCDay() || 7;
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
return Math.ceil((((d - yearStart) / 86400000) + 1)/7)
};
document.write('The current ISO week number is ' + new Date().getWeekNumber());
Test section
In this section, you can enter any date in YYYY-MM-DD format and check that this code gives the same week number as Moment.js ISO week number (tested over 50 years from 2000 to 2050).
Date.prototype.getWeekNumber = function(){
var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate()));
var dayNum = d.getUTCDay() || 7;
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
return Math.ceil((((d - yearStart) / 86400000) + 1)/7)
};
function checkWeek() {
var s = document.getElementById('dString').value;
var m = moment(s, 'YYYY-MM-DD');
document.getElementById('momentWeek').value = m.format('W');
document.getElementById('answerWeek').value = m.toDate().getWeekNumber();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
Enter date YYYY-MM-DD: <input id="dString" value="2021-02-22">
<button onclick="checkWeek(this)">Check week number</button><br>
Moment: <input id="momentWeek" readonly><br>
Answer: <input id="answerWeek" readonly>
You can use momentjs library also:
moment().format('W')
Not ISO-8601 week number but if the search engine pointed you here anyway.
As said above but without a class:
let now = new Date();
let onejan = new Date(now.getFullYear(), 0, 1);
let week = Math.ceil((((now.getTime() - onejan.getTime()) / 86400000) + onejan.getDay() + 1) / 7);
console.log(week);
Accordily http://javascript.about.com/library/blweekyear.htm
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(), 0, 1);
var millisecsInDay = 86400000;
return Math.ceil((((this - onejan) / millisecsInDay) + onejan.getDay() + 1) / 7);
};
let d = new Date(2020,11,30);
for (let i=0; i<14; i++) {
console.log(`${d.toDateString()} is week ${d.getWeek()}`);
d.setDate(d.getDate() + 1);
}
Jacob Wright's Date.format() library implements date formatting in the style of PHP's date() function and supports the ISO-8601 week number:
new Date().format('W');
It may be a bit overkill for just a week number, but it does support PHP style formatting and is quite handy if you'll be doing a lot of this.
The code below calculates the correct ISO 8601 week number. It matches PHP's date("W") for every week between 1/1/1970 and 1/1/2100.
/**
* Get the ISO week date week number
*/
Date.prototype.getWeek = function () {
// Create a copy of this date object
var target = new Date(this.valueOf());
// ISO week date weeks start on Monday, so correct the day number
var dayNr = (this.getDay() + 6) % 7;
// ISO 8601 states that week 1 is the week with the first Thursday of that year
// Set the target date to the Thursday in the target week
target.setDate(target.getDate() - dayNr + 3);
// Store the millisecond value of the target date
var firstThursday = target.valueOf();
// Set the target to the first Thursday of the year
// First, set the target to January 1st
target.setMonth(0, 1);
// Not a Thursday? Correct the date to the next Thursday
if (target.getDay() !== 4) {
target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
}
// The week number is the number of weeks between the first Thursday of the year
// and the Thursday in the target week (604800000 = 7 * 24 * 3600 * 1000)
return 1 + Math.ceil((firstThursday - target) / 604800000);
}
Source: Taco van den Broek
If you're not into extending prototypes, then here's a function:
function getWeek(date) {
if (!(date instanceof Date)) date = new Date();
// ISO week date weeks start on Monday, so correct the day number
var nDay = (date.getDay() + 6) % 7;
// ISO 8601 states that week 1 is the week with the first Thursday of that year
// Set the target date to the Thursday in the target week
date.setDate(date.getDate() - nDay + 3);
// Store the millisecond value of the target date
var n1stThursday = date.valueOf();
// Set the target to the first Thursday of the year
// First, set the target to January 1st
date.setMonth(0, 1);
// Not a Thursday? Correct the date to the next Thursday
if (date.getDay() !== 4) {
date.setMonth(0, 1 + ((4 - date.getDay()) + 7) % 7);
}
// The week number is the number of weeks between the first Thursday of the year
// and the Thursday in the target week (604800000 = 7 * 24 * 3600 * 1000)
return 1 + Math.ceil((n1stThursday - date) / 604800000);
}
Sample usage:
getWeek(); // Returns 37 (or whatever the current week is)
getWeek(new Date('Jan 2, 2011')); // Returns 52
getWeek(new Date('Jan 1, 2016')); // Returns 53
getWeek(new Date('Jan 4, 2016')); // Returns 1
getWeekOfYear: function(date) {
var target = new Date(date.valueOf()),
dayNumber = (date.getUTCDay() + 6) % 7,
firstThursday;
target.setUTCDate(target.getUTCDate() - dayNumber + 3);
firstThursday = target.valueOf();
target.setUTCMonth(0, 1);
if (target.getUTCDay() !== 4) {
target.setUTCMonth(0, 1 + ((4 - target.getUTCDay()) + 7) % 7);
}
return Math.ceil((firstThursday - target) / (7 * 24 * 3600 * 1000)) + 1;
}
Following code is timezone-independent (UTC dates used) and works according to the https://en.wikipedia.org/wiki/ISO_8601
Get the weeknumber of any given Date
function week(year,month,day) {
function serial(days) { return 86400000*days; }
function dateserial(year,month,day) { return (new Date(year,month-1,day).valueOf()); }
function weekday(date) { return (new Date(date)).getDay()+1; }
function yearserial(date) { return (new Date(date)).getFullYear(); }
var date = year instanceof Date ? year.valueOf() : typeof year === "string" ? new Date(year).valueOf() : dateserial(year,month,day),
date2 = dateserial(yearserial(date - serial(weekday(date-serial(1))) + serial(4)),1,3);
return ~~((date - date2 + serial(weekday(date2) + 5))/ serial(7));
}
Example
console.log(
week(2016, 06, 11),//23
week(2015, 9, 26),//39
week(2016, 1, 1),//53
week(2016, 1, 4),//1
week(new Date(2016, 0, 4)),//1
week("11 january 2016")//2
);
I found useful the Java SE's SimpleDateFormat class described on Oracle's specification:
http://goo.gl/7MbCh5. In my case in Google Apps Script it worked like this:
function getWeekNumber() {
var weekNum = parseInt(Utilities.formatDate(new Date(), "GMT", "w"));
Logger.log(weekNum);
}
For example in a spreadsheet macro you can retrieve the actual timezone of the file:
function getWeekNumber() {
var weekNum = parseInt(Utilities.formatDate(new Date(), SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(), "w"));
Logger.log(weekNum);
}
This adds "getWeek" method to Date.prototype which returns number of week from the beginning of the year. The argument defines which day of the week to consider the first. If no argument passed, first day is assumed Sunday.
/**
* Get week number in the year.
* #param {Integer} [weekStart=0] First day of the week. 0-based. 0 for Sunday, 6 for Saturday.
* #return {Integer} 0-based number of week.
*/
Date.prototype.getWeek = function(weekStart) {
var januaryFirst = new Date(this.getFullYear(), 0, 1);
if(weekStart !== undefined && (typeof weekStart !== 'number' || weekStart % 1 !== 0 || weekStart < 0 || weekStart > 6)) {
throw new Error('Wrong argument. Must be an integer between 0 and 6.');
}
weekStart = weekStart || 0;
return Math.floor((((this - januaryFirst) / 86400000) + januaryFirst.getDay() - weekStart) / 7);
};
If you are already in an Angular project you could use $filter('date').
For example:
var myDate = new Date();
var myWeek = $filter('date')(myDate, 'ww');
The code snippet which works pretty well for me is this one:
var yearStart = +new Date(d.getFullYear(), 0, 1);
var today = +new Date(d.getFullYear(),d.getMonth(),d.getDate());
var dayOfYear = ((today - yearStart + 1) / 86400000);
return Math.ceil(dayOfYear / 7).toString();
Note:
d is my Date for which I want the current week number.
The + converts the Dates into numbers (working with TypeScript).
With Luxon (https://github.com/moment/luxon) :
import { DateTime } from 'luxon';
const week: number = DateTime.fromJSDate(new Date()).weekNumber;
This week number thing has been a real pain in the a**. Most trivial solutions around the web didn't really work for me as they worked most of the time but all of them broke at some point, especially when year changed and last week of the year was suddenly next year's first week etc. Even Angular's date filter showed incorrect data (it was the 1st week of next year, Angular gave week 53).
Note: The examples are designed to work with European weeks (Mon first)!
getWeek()
Date.prototype.getWeek = function(){
// current week's Thursday
var curWeek = new Date(this.getTime());
curWeek.setDay(4);
// current year's first week's Thursday
var firstWeek = new Date(curWeek.getFullYear(), 0, 4);
firstWeek.setDay(4);
return (curWeek.getDayIndex() - firstWeek.getDayIndex()) / 7 + 1;
};
setDay()
/**
* Make a setDay() prototype for Date
* Sets week day for the date
*/
Date.prototype.setDay = function(day){
// Get day and make Sunday to 7
var weekDay = this.getDay() || 7;
var distance = day - weekDay;
this.setDate(this.getDate() + distance);
return this;
}
getDayIndex()
/*
* Returns index of given date (from Jan 1st)
*/
Date.prototype.getDayIndex = function(){
var start = new Date(this.getFullYear(), 0, 0);
var diff = this - start;
var oneDay = 86400000;
return Math.floor(diff / oneDay);
};
I have tested this and it seems to be working very well but if you notice a flaw in it, please let me know.
Here is my implementation for calculating the week number in JavaScript. corrected for summer and winter time offsets as well.
I used the definition of the week from this article: ISO 8601
Weeks are from mondays to sunday, and january 4th is always in the first week of the year.
// add get week prototype functions
// weeks always start from monday to sunday
// january 4th is always in the first week of the year
Date.prototype.getWeek = function () {
year = this.getFullYear();
var currentDotw = this.getWeekDay();
if (this.getMonth() == 11 && this.getDate() - currentDotw > 28) {
// if true, the week is part of next year
return this.getWeekForYear(year + 1);
}
if (this.getMonth() == 0 && this.getDate() + 6 - currentDotw < 4) {
// if true, the week is part of previous year
return this.getWeekForYear(year - 1);
}
return this.getWeekForYear(year);
}
// returns a zero based day, where monday = 0
// all weeks start with monday
Date.prototype.getWeekDay = function () {
return (this.getDay() + 6) % 7;
}
// corrected for summer/winter time
Date.prototype.getWeekForYear = function (year) {
var currentDotw = this.getWeekDay();
var fourjan = new Date(year, 0, 4);
var firstDotw = fourjan.getWeekDay();
var dayTotal = this.getDaysDifferenceCorrected(fourjan) // the difference in days between the two dates.
// correct for the days of the week
dayTotal += firstDotw; // the difference between the current date and the first monday of the first week,
dayTotal -= currentDotw; // the difference between the first monday and the current week's monday
// day total should be a multiple of 7 now
var weeknumber = dayTotal / 7 + 1; // add one since it gives a zero based week number.
return weeknumber;
}
// corrected for timezones and offset
Date.prototype.getDaysDifferenceCorrected = function (other) {
var millisecondsDifference = (this - other);
// correct for offset difference. offsets are in minutes, the difference is in milliseconds
millisecondsDifference += (other.getTimezoneOffset()- this.getTimezoneOffset()) * 60000;
// return day total. 1 day is 86400000 milliseconds, floor the value to return only full days
return Math.floor(millisecondsDifference / 86400000);
}
for testing i used the following JavaScript tests in Qunit
var runweekcompare = function(result, expected) {
equal(result, expected,'Week nr expected value: ' + expected + ' Actual value: ' + result);
}
test('first week number test', function () {
expect(5);
var temp = new Date(2016, 0, 4); // is the monday of the first week of the year
runweekcompare(temp.getWeek(), 1);
var temp = new Date(2016, 0, 4, 23, 50); // is the monday of the first week of the year
runweekcompare(temp.getWeek(), 1);
var temp = new Date(2016, 0, 10, 23, 50); // is the sunday of the first week of the year
runweekcompare(temp.getWeek(), 1);
var temp = new Date(2016, 0, 11, 23, 50); // is the second week of the year
runweekcompare(temp.getWeek(), 2);
var temp = new Date(2016, 1, 29, 23, 50); // is the 9th week of the year
runweekcompare(temp.getWeek(), 9);
});
test('first day is part of last years last week', function () {
expect(2);
var temp = new Date(2016, 0, 1, 23, 50); // is the first last week of the previous year
runweekcompare(temp.getWeek(), 53);
var temp = new Date(2011, 0, 2, 23, 50); // is the first last week of the previous year
runweekcompare(temp.getWeek(), 52);
});
test('last day is part of next years first week', function () {
var temp = new Date(2013, 11, 30); // is part of the first week of 2014
runweekcompare(temp.getWeek(), 1);
});
test('summer winter time change', function () {
expect(2);
var temp = new Date(2000, 2, 26);
runweekcompare(temp.getWeek(), 12);
var temp = new Date(2000, 2, 27);
runweekcompare(temp.getWeek(), 13);
});
test('full 20 year test', function () {
//expect(20 * 12 * 28 * 2);
for (i = 2000; i < 2020; i++) {
for (month = 0; month < 12; month++) {
for (day = 1; day < 29 ; day++) {
var temp = new Date(i, month, day);
var expectedweek = temp.getWeek();
var temp2 = new Date(i, month, day, 23, 50);
var resultweek = temp.getWeek();
equal(expectedweek, Math.round(expectedweek), 'week number whole number expected ' + Math.round(expectedweek) + ' resulted week nr ' + expectedweek);
equal(resultweek, expectedweek, 'Week nr expected value: ' + expectedweek + ' Actual value: ' + resultweek + ' for year ' + i + ' month ' + month + ' day ' + day);
}
}
}
});
Here is a slight adaptation for Typescript that will also return the dates for the week start and week end. I think it's common to have to display those in a user interface, since people don't usually remember week numbers.
function getWeekNumber(d: Date) {
// Copy date so don't modify original
d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
// Set to nearest Thursday: current date + 4 - current day number Make
// Sunday's day number 7
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
// Get first day of year
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
// Calculate full weeks to nearest Thursday
const weekNo = Math.ceil(
((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7
);
const weekStartDate = new Date(d.getTime());
weekStartDate.setUTCDate(weekStartDate.getUTCDate() - 3);
const weekEndDate = new Date(d.getTime());
weekEndDate.setUTCDate(weekEndDate.getUTCDate() + 3);
return [d.getUTCFullYear(), weekNo, weekStartDate, weekEndDate] as const;
}
This is my typescript implementation which I tested against some dates. This implementation allows you to set the first day of the week to any day.
//sunday = 0, monday = 1, ...
static getWeekNumber(date: Date, firstDay = 1): number {
const d = new Date(date.getTime());
d.setHours(0, 0, 0, 0);
//Set to first day of the week since it is the same weeknumber
while(d.getDay() != firstDay){
d.setDate(d.getDate() - 1);
}
const dayOfYear = this.getDayOfYear(d);
let weken = Math.floor(dayOfYear/7);
// add an extra week if 4 or more days are in this year.
const daysBefore = ((dayOfYear % 7) - 1);
if(daysBefore >= 4){
weken += 1;
}
//if the last 3 days onf the year,it is the first week
const t = new Date(d.getTime());
t.setDate(t.getDate() + 3);
if(t.getFullYear() > d.getFullYear()){
return 1;
}
weken += 1;
return weken;
}
private static getDayOfYear(date: Date){
const start = new Date(date.getFullYear(), 0, 0);
const diff = (date.getTime() - start.getTime()) + ((start.getTimezoneOffset() - date.getTimezoneOffset()) * 60 * 1000);
const oneDay = 1000 * 60 * 60 * 24;
const day = Math.floor(diff / oneDay);
return day;
}
Tests:
describe('getWeeknumber', () => {
it('should be ok for 0 sunday', () => {
expect(DateUtils.getWeekNumber(new Date(2015, 0, 4), 0)).toBe(1);
expect(DateUtils.getWeekNumber(new Date(2017, 0, 1), 0)).toBe(1);
expect(DateUtils.getWeekNumber(new Date(2017, 0, 2), 0)).toBe(1);
expect(DateUtils.getWeekNumber(new Date(2017, 0, 8), 0)).toBe(2);
expect(DateUtils.getWeekNumber(new Date(2017, 0, 9), 0)).toBe(2);
expect(DateUtils.getWeekNumber(new Date(2020, 11, 28), 0)).toBe(53);
expect(DateUtils.getWeekNumber(new Date(2020, 11, 29), 0)).toBe(53);
expect(DateUtils.getWeekNumber(new Date(2020, 11, 30), 0)).toBe(53);
expect(DateUtils.getWeekNumber(new Date(2020, 11, 31), 0)).toBe(53);
expect(DateUtils.getWeekNumber(new Date(2022, 0, 3), 0)).toBe(1);
});
it('should be ok for monday 1 default', () => {
expect(DateUtils.getWeekNumber(new Date(2015, 0, 4), 1)).toBe(1);
expect(DateUtils.getWeekNumber(new Date(2017, 0, 1), 1)).toBe(52);
expect(DateUtils.getWeekNumber(new Date(2017, 0, 2), 1)).toBe(1);
expect(DateUtils.getWeekNumber(new Date(2017, 0, 8), 1)).toBe(1);
expect(DateUtils.getWeekNumber(new Date(2017, 0, 9), 1)).toBe(2);
expect(DateUtils.getWeekNumber(new Date(2020, 11, 28), 1)).toBe(53);
expect(DateUtils.getWeekNumber(new Date(2020, 11, 29), 1)).toBe(53);
expect(DateUtils.getWeekNumber(new Date(2020, 11, 30), 1)).toBe(53);
expect(DateUtils.getWeekNumber(new Date(2020, 11, 31), 1)).toBe(53);
expect(DateUtils.getWeekNumber(new Date(2022, 0, 3), 1)).toBe(1);
});
});
I tried a lot to get the shortest code to get the weeknumber ISO-conform.
Date.prototype.getWeek=function(){
var date=new Date(this);
date.setHours(0,0,0,0);
return Math.round(((date.setDate(this.getDate()+2-(this.getDay()||7))-date.setMonth(0,4))/8.64e7+3+(date.getDay()||7))/7)+"/"+date.getFullYear();}
The variable date is necessary to avoid to alter the original this. I used the return values of setDate() and setMonth() to dispense with getTime() to save code length and I used an expontial number for milliseconds of a day instead of a multiplication of single elements or a number with five zeros. this is Date or Number of milliseconds, return value is String e.g. "49/2017".
Another library-based option: use d3-time-format:
const formatter = d3.timeFormat('%U');
const weekNum = formatter(new Date());
Shortest workaround for Angular2+ DatePipe, adjusted for ISO-8601:
import {DatePipe} from "#angular/common";
public rightWeekNum: number = 0;
constructor(private datePipe: DatePipe) { }
calcWeekOfTheYear(dateInput: Date) {
let falseWeekNum = parseInt(this.datePipe.transform(dateInput, 'ww'));
this.rightWeekNum = (dateInput.getDay() == 0) ? falseWeekNumber-1 : falseWeekNumber;
}
Inspired from RobG's answer.
What I wanted is the day of the week of a given date. So my answer is simply based on the day of the week Sunday. But you can choose the other day (i.e. Monday, Tuesday...);
First I find the Sunday in a given date and then calculate the week.
function getStartWeekDate(d = null) {
const now = d || new Date();
now.setHours(0, 0, 0, 0);
const sunday = new Date(now);
sunday.setDate(sunday.getDate() - sunday.getDay());
return sunday;
}
function getWeek(date) {
const sunday = getStartWeekDate(date);
const yearStart = new Date(Date.UTC(2021, 0, 1));
const weekNo = Math.ceil((((sunday - yearStart) / 86400000) + 1) / 7);
return weekNo;
}
// tests
for (let i = 0; i < 7; i++) {
let m = 14 + i;
let x = getWeek(new Date(2021, 2, m));
console.log('week num: ' + x, x + ' == ' + 11, x == 11, m);
}
for (let i = 0; i < 7; i++) {
let m = 21 + i;
let x = getWeek(new Date(2021, 2, m));
console.log('week num: ' + x, x + ' == ' + 12, x == 12, 'date day: ' + m);
}
for (let i = 0; i < 4; i++) {
let m = 28 + i;
let x = getWeek(new Date(2021, 2, m));
console.log('week num: ' + x, x + ' == ' + 13, x == 13, 'date day: ' + m);
}
for (let i = 0; i < 3; i++) {
let m = 1 + i;
let x = getWeek(new Date(2021, 3, m));
console.log('week num: ' + x, x + ' == ' + 13, x == 13, 'date day: ' + m);
}
for (let i = 0; i < 7; i++) {
let m = 4 + i;
let x = getWeek(new Date(2021, 3, m));
console.log('week num: ' + x, x + ' == ' + 14, x == 14, 'date day: ' + m);
}
now = new Date();
today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
firstOfYear = new Date(now.getFullYear(), 0, 1);
numOfWeek = Math.ceil((((today - firstOfYear) / 86400000)-1)/7);
function getWeek(param) {
let onejan = new Date(param.getFullYear(), 0, 1);
return Math.ceil((((param.getTime() - onejan.getTime()) / 86400000) + onejan.getDay()) / 7);
}
Related
How can I calculate the date in JavaScript knowing the week number and the year? For week number 20 and year 2013 I want to obtain 2013-05-16.
I am trying it like this:
Date.prototype.dayofYear = function () {
var d = new Date(this.getFullYear(), 0, 0)
return Math.floor((/* enter code here */ this - d) / 8.64e + 7)
}
function getDateOfWeek(w, y) {
var d = (1 + (w - 1) * 7); // 1st of January + 7 days for each week
return new Date(y, 0, d);
}
This uses the simple week definition, meaning the 20th week of 2013 is May 14.
To calculate the date of the start of a given ISO8601 week (which will always be a Monday)
function getDateOfISOWeek(w, y) {
var simple = new Date(y, 0, 1 + (w - 1) * 7);
var dow = simple.getDay();
var ISOweekStart = simple;
if (dow <= 4)
ISOweekStart.setDate(simple.getDate() - simple.getDay() + 1);
else
ISOweekStart.setDate(simple.getDate() + 8 - simple.getDay());
return ISOweekStart;
}
Result: the 20th week of 2013 is May 13, which can be confirmed here.
Sorry if this is a little verbose but this solution will also return the Sunday after calculating the week number. It combines answers I've seen from a couple different places:
function getSundayFromWeekNum(weekNum, year) {
var sunday = new Date(year, 0, (1 + (weekNum - 1) * 7));
while (sunday.getDay() !== 0) {
sunday.setDate(sunday.getDate() - 1);
}
return sunday;
}
ISO Weeks
function weekDateToDate (year, week, day) {
const firstDayOfYear = new Date(year, 0, 1)
const days = 2 + day + (week - 1) * 7 - firstDayOfYear.getDay()
return new Date(year, 0, days)
}
2019 version (if anyone wants to calculate the date of week's start)
The answer of Elle is pretty much right, but there is one exception:
if you want to get a date of start of the week - it won't help you because Elle's algorithm doesn't mind the day, from which the week starts of, at all.
And here is why:
Elle's solution
function getDateOfWeek(w, y) {
var d = (1 + (w - 1) * 7); // 1st of January + 7 days for each week
return new Date(y, 0, d);
}
Here you basically just calculating the amount of days from the start of the year (1st January). This means that it doesn't matter from which day your year starts of: Monday, Sunday or Friday - it will not make any difference.
To set the day, from which your week will start of (let's say Monday, for example), you just need to:
function getDateOfWeek(w, y) {
let date = new Date(y, 0, (1 + (w - 1) * 7)); // Elle's method
date.setDate(date.getDate() + (1 - date.getDay())); // 0 - Sunday, 1 - Monday etc
return date
}
Get date range according to week number
Date.prototype.getWeek = function () {
var target = new Date(this.valueOf());
var dayNr = (this.getDay() + 6) % 7;
target.setDate(target.getDate() - dayNr + 3);
var firstThursday = target.valueOf();
target.setMonth(0, 1);
if (target.getDay() != 4) {
target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
}
return 1 + Math.ceil((firstThursday - target) / 604800000);
}
function getDateRangeOfWeek(weekNo){
var d1 = new Date();
numOfdaysPastSinceLastMonday = eval(d1.getDay()- 1);
d1.setDate(d1.getDate() - numOfdaysPastSinceLastMonday);
var weekNoToday = d1.getWeek();
var weeksInTheFuture = eval( weekNo - weekNoToday );
d1.setDate(d1.getDate() + eval( 7 * weeksInTheFuture ));
var rangeIsFrom = eval(d1.getMonth()+1) +"/" + d1.getDate() + "/" + d1.getFullYear();
d1.setDate(d1.getDate() + 6);
var rangeIsTo = eval(d1.getMonth()+1) +"/" + d1.getDate() + "/" + d1.getFullYear() ;
return rangeIsFrom + " to "+rangeIsTo;
};
getDateRangeOfWeek(10)
"3/6/2017 to 3/12/2017"
getDateRangeOfWeek(30)
"7/24/2017 to 7/30/2017"
function getDateOfWeek(weekNumber,year){
//Create a date object starting january first of chosen year, plus the number of days in a week multiplied by the week number to get the right date.
return new Date(year, 0, 1+((weekNumber-1)*7));
}
var myDate = getDateOfWeek(20,2013);
ISO week date (e.g. 2017-W32-3) to normal date:
const getZeroBasedIsoWeekDay = date => (date.getDay() + 6) % 7
const getIsoWeekDay = date => getZeroBasedIsoWeekDay(date) + 1
function weekDateToDate(year, week, weekDay) {
const zeroBasedWeek = week - 1
const zeroBasedWeekDay = weekDay - 1
let days = (zeroBasedWeek * 7) + zeroBasedWeekDay
// Dates start at 2017-01-01 and not 2017-01-00
days += 1
const firstDayOfYear = new Date(year, 0, 1)
const firstIsoWeekDay = getIsoWeekDay(firstDayOfYear)
const zeroBasedFirstIsoWeekDay = getZeroBasedIsoWeekDay(firstDayOfYear)
// If year begins with W52 or W53
if (firstIsoWeekDay > 4) days += 8 - firstIsoWeekDay
// Else begins with W01
else days -= zeroBasedFirstIsoWeekDay
return new Date(year, 0, days)
}
const expectedAndActual = [
[new Date('2007-01-01'), weekDateToDate(2007, 1, 1)],
[new Date('2015-11-24'), weekDateToDate(2015, 48, 2)],
[new Date('2015-12-31'), weekDateToDate(2015, 53, 4)],
[new Date('2016-01-03'), weekDateToDate(2015, 53, 7)],
[new Date('2017-01-01'), weekDateToDate(2016, 52, 7)],
[new Date('2017-01-02'), weekDateToDate(2017, 1, 1)],
[new Date('2017-05-07'), weekDateToDate(2017, 18, 7)],
[new Date('2018-12-31'), weekDateToDate(2019, 1, 1)],
]
expectedAndActual
.forEach(value => {
const expected = value[0].toISOString()
const actual = value[1].toISOString()
const isEqual = actual === expected
console.assert(isEqual, '%s !== %s', actual, expected)
console.log(actual, '===', expected)
})
#adius function worked for me but I made some improvements for people who are looking for a simple copy paste solution:
/**
* get date by week number
* #param {Number} year
* #param {Number} week
* #param {Number} day of week (optional; default = 0 (Sunday))
* #return {Date}
*/
function weekToDate(year, week, weekDay = 0) {
const getZeroBasedIsoWeekDay = date => (date.getDay() + 6) % 7;
const getIsoWeekDay = date => getZeroBasedIsoWeekDay(date) + 1;
const zeroBasedWeek = week - 1;
const zeroBasedWeekDay = weekDay - 1;
let days = (zeroBasedWeek * 7) + zeroBasedWeekDay;
// Dates start at 2017-01-01 and not 2017-01-00
days += 1;
const firstDayOfYear = new Date(year, 0, 1);
const firstIsoWeekDay = getIsoWeekDay(firstDayOfYear);
const zeroBasedFirstIsoWeekDay = getZeroBasedIsoWeekDay(firstDayOfYear);
// If year begins with W52 or W53
if (firstIsoWeekDay > 4) {
days += 8 - firstIsoWeekDay;
// Else begins with W01
} else {
days -= zeroBasedFirstIsoWeekDay;
}
return new Date(year, 0, days);
}
// test:
const x = [
{year: 2001, week: 10},
{year: 2019, week: 7},
{year: 2020, week: 5},
{year: 2020, week: 1},
{year: 2020, week: 12},
{year: 2020, week: 2},
{year: 2020, week: 40},
{year: 2021, week: 4},
{year: 2021, week: 3},
{year: 2021, week: 2},
{year: 2032, week: 1}
]
for (let i = 0; i < x.length; i++) {
let date = weekToDate(x[i].year, x[i].week, 0);
let d = new Date(date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})
console.log(d);
}
This is for getting the first monday of a week in the current year (ISO 8601):
function getFirstMondayOfWeek(weekNo) {
var firstMonday = new Date(new Date().getFullYear(), 0, 4, 0, 0, 0, 0);
while (firstMonday.getDay() != 1) {
firstMonday.setDate(firstMonday.getDate() - 1);
}
if (1 <= weekNo && weekNo <= 52)
return firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));
firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));
if (weekNo = 53 && firstMonday.getDate() >= 22 && firstMonday.getDate() <= 28)
return firstMonday;
return null;
}
I just created this one:
//Returns monday and saturday of the week
function getWeekRange(weekNo,YearNo) {
let firstDayofYear = new Date(yearNo, 0, 1);
if (firstDayofYear.getDay() > 4) {
let weekStart = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 8);
let weekEnd = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 8 + 5);
return { startDay: weekStart, endDay: weekEnd }
}
else {
let weekStart = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 1);
let weekEnd = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 1 + 5);
return { startDay: weekStart, endDay: weekEnd }
}
}
This is a short way
function addWeeks(numOfWeeks, date = new Date()) {
date.setDate(date.getDate() + numOfWeeks * 7);
return date;
}
Ex: Today is 2022-08-02
addWeeks(1)
the result will be today + 7
Tue Aug 09 2022 21:36:08 GMT+0100 (GMT+02:00)
but you may want only date without all info
addWeeks(1).toISOString().split('T')[0]
the result will be: 2022-08-09
ISO weeks (https://en.wikipedia.org/wiki/ISO_week_date):
const y = 2023;
const jan1 = new Date(y, 0, 1);
const jan1Day = jan1.getDay();
const daysToMonday = jan1Day === 1? 0 : jan1Day === 0? 1 : 8 - jan1Day
console.log('jan1', jan1)
console.log('jan1Day', jan1Day)
console.log('daysToMonday', daysToMonday)
// first Monday of the year
const firstMonday = daysToMonday === 0 ? jan1 : new Date(+jan1 + daysToMonday * 86400e3);
console.log('firstMonday', firstMonday)
// get monday of a specific week (20)
console.log('monday of week 20', new Date(+firstMonday + (20 - 1) * 7 * 86400e3))
// get sunday of a specific week (20)
console.log('sunday of week 20', new Date(+firstMonday + ((20 - 1) * 7 * 86400e3) + (86400e3 * 6) ))
Current accepted answer is close but not entirely correct. Here is the correct function:
function weekToDate(year, week) {
const days = 4 + 7 * (week - 1);
const date = new Date(year, 0, days);
return date;
}
This will yield a date that is guaranteed to be in the ISO week you asked for.
Then if you want a specific day in the week modify the date like so:
const dayOfWeek = 1 // monday
date.setDate(date.getDate() - date.getDay() + dayOfWeek)
Where dayOfWeek is the day of the week you want to get the date of. (1-7, 1 = monday)
Moment js has a function to get the number of days in a month : http://momentjs.com/docs/#/displaying/days-in-month/
However I could not find a function to find the number of iso weeks in a year (52 or 53).
Here's an answer that isn't dependent on a library. It uses a function to calculate the week in the year that 31 December falls in for the required year. If the week is 1 (i.e. 31 December is in the first week of the following year), it moves the day number lower until it gets a different value, which will be the last week of the required year.
function getWeekNumber(d) {
// Copy date so don't modify original
d = new Date(+d);
d.setHours(0, 0, 0, 0);
// Set to nearest Thursday: current date + 4 - current day number
// Make Sunday's day number 7
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
// Get first day of year
var yearStart = new Date(d.getFullYear(), 0, 1);
// Calculate full weeks to nearest Thursday
var weekNo = Math.ceil((((d - yearStart) / 86400000) + 1) / 7)
// Return array of year and week number
return [d.getFullYear(), weekNo];
}
function weeksInYear(year) {
var month = 11,
day = 31,
week;
// Find week that 31 Dec is in. If is first week, reduce date until
// get previous week.
do {
d = new Date(year, month, day--);
week = getWeekNumber(d)[1];
} while (week == 1);
return week;
}
[2015, 2016, 2029, new Date().getFullYear()].forEach(year =>
console.log(`${year} has ${weeksInYear(year)} weeks`)
);
The getWeekNumber code is from here: Get week of year in JavaScript like in PHP.
Edit
Alternatively, if 31 December is in week 1 of the following year, then the subject year has 52 weeks and otherwise has 53 weeks.
function getWeekNumber(d) {
d = new Date(+d);
d.setHours(0, 0, 0, 0);
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
var yearStart = new Date(d.getFullYear(), 0, 1);
var weekNo = Math.ceil((((d - yearStart) / 86400000) + 1) / 7)
return [d.getFullYear(), weekNo];
}
function weeksInYear(year) {
var d = new Date(year, 11, 31);
var week = getWeekNumber(d)[1];
return week == 1 ? 52 : week;
}
[2015, 2016, 2029, new Date().getFullYear()].forEach(year =>
console.log(`${year} has ${weeksInYear(year)} weeks`)
);
Use isoWeek on the last day of the year to get the number of weeks e.g. :
function weeksInYear(year) {
return Math.max(
moment(new Date(year, 11, 31)).isoWeek()
, moment(new Date(year, 11, 31-7)).isoWeek()
);
}
Feb. 4th 2014 the weeksInYear & isoWeeksInYear functions were added to moment.js
So today you can just use moment().isoWeeksInYear()or moment().weeksInYear()
For more into see the docs
Thought I would post a much simpler version that I derived from the wikipedia article.
https://en.wikipedia.org/wiki/ISO_week_date
The statement in the article is:
"The number of weeks in a given year is equal to the corresponding
week number of 28 December, because it is the only date that is always
in the last week of the year since it is a week before 4 January which
is always in the first week of the following year.
Using only the ordinal year number y, the number of weeks in that year
can be determined from a function, that
returns the day of the week of 31 December"
Therefore getWeekFor(new Date(2022, 11, 28) replacing the year with any year you want will always give you the number of weeks for that year.
// modified from https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php
const getWeekFor = (date) => {
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
const dayNum = d.getUTCDay() || 7;
const utc = new Date(d.setUTCDate(d.getUTCDate() + 4 - dayNum));
const yearStart = new Date(Date.UTC(utc.getUTCFullYear(), 0, 1)).getTime();
return Math.ceil(((d.getTime() - yearStart) / 86400000 + 1) / 7);
};
const weeks = getWeekFor(new Date(2020, 11, 28)) // 53.
console.log(weeks);
Get all weeks and periods of that week for a year, for whom it may interest
function getWeekPeriodsInYear(year) {
weeks = [];
// Get the first and last day of the year
currentDay = moment([year, 1]).startOf('year');
dayOfWeek = moment(currentDay).day();
lastDay = moment([year, 1]).endOf('year');
weeksInYear = moment(`${year}-01-01`).isoWeeksInYear();
daysToAdd = 7 - dayOfWeek;
for (let weekNumber = 1; weekNumber < weeksInYear + 1; weekNumber++) {
let endOfWeek = moment(currentDay).add(daysToAdd, 'days');
if (moment(endOfWeek).year() !== year) {
endOfWeek = lastDay;
}
weeks.push({ weekNumber, start: currentDay.toDate(), end: endOfWeek.toDate() });
currentDay = endOfWeek.add(1, 'day');
daysToAdd = 6;
}
return weeks;
}
getWeekPeriodsInYear(new Date().getFullYear()).forEach(period =>
document.write(`Week ${period.weekNumber} from ${moment(period.start).format('DD-MM-YYYY')} up to and including ${moment(period.end).format('DD-MM-YYYY')}<br/>`)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
How can I calculate the date in JavaScript knowing the week number and the year? For week number 20 and year 2013 I want to obtain 2013-05-16.
I am trying it like this:
Date.prototype.dayofYear = function () {
var d = new Date(this.getFullYear(), 0, 0)
return Math.floor((/* enter code here */ this - d) / 8.64e + 7)
}
function getDateOfWeek(w, y) {
var d = (1 + (w - 1) * 7); // 1st of January + 7 days for each week
return new Date(y, 0, d);
}
This uses the simple week definition, meaning the 20th week of 2013 is May 14.
To calculate the date of the start of a given ISO8601 week (which will always be a Monday)
function getDateOfISOWeek(w, y) {
var simple = new Date(y, 0, 1 + (w - 1) * 7);
var dow = simple.getDay();
var ISOweekStart = simple;
if (dow <= 4)
ISOweekStart.setDate(simple.getDate() - simple.getDay() + 1);
else
ISOweekStart.setDate(simple.getDate() + 8 - simple.getDay());
return ISOweekStart;
}
Result: the 20th week of 2013 is May 13, which can be confirmed here.
Sorry if this is a little verbose but this solution will also return the Sunday after calculating the week number. It combines answers I've seen from a couple different places:
function getSundayFromWeekNum(weekNum, year) {
var sunday = new Date(year, 0, (1 + (weekNum - 1) * 7));
while (sunday.getDay() !== 0) {
sunday.setDate(sunday.getDate() - 1);
}
return sunday;
}
ISO Weeks
function weekDateToDate (year, week, day) {
const firstDayOfYear = new Date(year, 0, 1)
const days = 2 + day + (week - 1) * 7 - firstDayOfYear.getDay()
return new Date(year, 0, days)
}
2019 version (if anyone wants to calculate the date of week's start)
The answer of Elle is pretty much right, but there is one exception:
if you want to get a date of start of the week - it won't help you because Elle's algorithm doesn't mind the day, from which the week starts of, at all.
And here is why:
Elle's solution
function getDateOfWeek(w, y) {
var d = (1 + (w - 1) * 7); // 1st of January + 7 days for each week
return new Date(y, 0, d);
}
Here you basically just calculating the amount of days from the start of the year (1st January). This means that it doesn't matter from which day your year starts of: Monday, Sunday or Friday - it will not make any difference.
To set the day, from which your week will start of (let's say Monday, for example), you just need to:
function getDateOfWeek(w, y) {
let date = new Date(y, 0, (1 + (w - 1) * 7)); // Elle's method
date.setDate(date.getDate() + (1 - date.getDay())); // 0 - Sunday, 1 - Monday etc
return date
}
Get date range according to week number
Date.prototype.getWeek = function () {
var target = new Date(this.valueOf());
var dayNr = (this.getDay() + 6) % 7;
target.setDate(target.getDate() - dayNr + 3);
var firstThursday = target.valueOf();
target.setMonth(0, 1);
if (target.getDay() != 4) {
target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
}
return 1 + Math.ceil((firstThursday - target) / 604800000);
}
function getDateRangeOfWeek(weekNo){
var d1 = new Date();
numOfdaysPastSinceLastMonday = eval(d1.getDay()- 1);
d1.setDate(d1.getDate() - numOfdaysPastSinceLastMonday);
var weekNoToday = d1.getWeek();
var weeksInTheFuture = eval( weekNo - weekNoToday );
d1.setDate(d1.getDate() + eval( 7 * weeksInTheFuture ));
var rangeIsFrom = eval(d1.getMonth()+1) +"/" + d1.getDate() + "/" + d1.getFullYear();
d1.setDate(d1.getDate() + 6);
var rangeIsTo = eval(d1.getMonth()+1) +"/" + d1.getDate() + "/" + d1.getFullYear() ;
return rangeIsFrom + " to "+rangeIsTo;
};
getDateRangeOfWeek(10)
"3/6/2017 to 3/12/2017"
getDateRangeOfWeek(30)
"7/24/2017 to 7/30/2017"
function getDateOfWeek(weekNumber,year){
//Create a date object starting january first of chosen year, plus the number of days in a week multiplied by the week number to get the right date.
return new Date(year, 0, 1+((weekNumber-1)*7));
}
var myDate = getDateOfWeek(20,2013);
ISO week date (e.g. 2017-W32-3) to normal date:
const getZeroBasedIsoWeekDay = date => (date.getDay() + 6) % 7
const getIsoWeekDay = date => getZeroBasedIsoWeekDay(date) + 1
function weekDateToDate(year, week, weekDay) {
const zeroBasedWeek = week - 1
const zeroBasedWeekDay = weekDay - 1
let days = (zeroBasedWeek * 7) + zeroBasedWeekDay
// Dates start at 2017-01-01 and not 2017-01-00
days += 1
const firstDayOfYear = new Date(year, 0, 1)
const firstIsoWeekDay = getIsoWeekDay(firstDayOfYear)
const zeroBasedFirstIsoWeekDay = getZeroBasedIsoWeekDay(firstDayOfYear)
// If year begins with W52 or W53
if (firstIsoWeekDay > 4) days += 8 - firstIsoWeekDay
// Else begins with W01
else days -= zeroBasedFirstIsoWeekDay
return new Date(year, 0, days)
}
const expectedAndActual = [
[new Date('2007-01-01'), weekDateToDate(2007, 1, 1)],
[new Date('2015-11-24'), weekDateToDate(2015, 48, 2)],
[new Date('2015-12-31'), weekDateToDate(2015, 53, 4)],
[new Date('2016-01-03'), weekDateToDate(2015, 53, 7)],
[new Date('2017-01-01'), weekDateToDate(2016, 52, 7)],
[new Date('2017-01-02'), weekDateToDate(2017, 1, 1)],
[new Date('2017-05-07'), weekDateToDate(2017, 18, 7)],
[new Date('2018-12-31'), weekDateToDate(2019, 1, 1)],
]
expectedAndActual
.forEach(value => {
const expected = value[0].toISOString()
const actual = value[1].toISOString()
const isEqual = actual === expected
console.assert(isEqual, '%s !== %s', actual, expected)
console.log(actual, '===', expected)
})
#adius function worked for me but I made some improvements for people who are looking for a simple copy paste solution:
/**
* get date by week number
* #param {Number} year
* #param {Number} week
* #param {Number} day of week (optional; default = 0 (Sunday))
* #return {Date}
*/
function weekToDate(year, week, weekDay = 0) {
const getZeroBasedIsoWeekDay = date => (date.getDay() + 6) % 7;
const getIsoWeekDay = date => getZeroBasedIsoWeekDay(date) + 1;
const zeroBasedWeek = week - 1;
const zeroBasedWeekDay = weekDay - 1;
let days = (zeroBasedWeek * 7) + zeroBasedWeekDay;
// Dates start at 2017-01-01 and not 2017-01-00
days += 1;
const firstDayOfYear = new Date(year, 0, 1);
const firstIsoWeekDay = getIsoWeekDay(firstDayOfYear);
const zeroBasedFirstIsoWeekDay = getZeroBasedIsoWeekDay(firstDayOfYear);
// If year begins with W52 or W53
if (firstIsoWeekDay > 4) {
days += 8 - firstIsoWeekDay;
// Else begins with W01
} else {
days -= zeroBasedFirstIsoWeekDay;
}
return new Date(year, 0, days);
}
// test:
const x = [
{year: 2001, week: 10},
{year: 2019, week: 7},
{year: 2020, week: 5},
{year: 2020, week: 1},
{year: 2020, week: 12},
{year: 2020, week: 2},
{year: 2020, week: 40},
{year: 2021, week: 4},
{year: 2021, week: 3},
{year: 2021, week: 2},
{year: 2032, week: 1}
]
for (let i = 0; i < x.length; i++) {
let date = weekToDate(x[i].year, x[i].week, 0);
let d = new Date(date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})
console.log(d);
}
This is for getting the first monday of a week in the current year (ISO 8601):
function getFirstMondayOfWeek(weekNo) {
var firstMonday = new Date(new Date().getFullYear(), 0, 4, 0, 0, 0, 0);
while (firstMonday.getDay() != 1) {
firstMonday.setDate(firstMonday.getDate() - 1);
}
if (1 <= weekNo && weekNo <= 52)
return firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));
firstMonday.setDate(firstMonday.getDate() + 7 * (weekNo - 1));
if (weekNo = 53 && firstMonday.getDate() >= 22 && firstMonday.getDate() <= 28)
return firstMonday;
return null;
}
I just created this one:
//Returns monday and saturday of the week
function getWeekRange(weekNo,YearNo) {
let firstDayofYear = new Date(yearNo, 0, 1);
if (firstDayofYear.getDay() > 4) {
let weekStart = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 8);
let weekEnd = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 8 + 5);
return { startDay: weekStart, endDay: weekEnd }
}
else {
let weekStart = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 1);
let weekEnd = new Date(yearNo, 0, 1 + (weekNo - 1) * 7 - firstDayofYear.getDay() + 1 + 5);
return { startDay: weekStart, endDay: weekEnd }
}
}
This is a short way
function addWeeks(numOfWeeks, date = new Date()) {
date.setDate(date.getDate() + numOfWeeks * 7);
return date;
}
Ex: Today is 2022-08-02
addWeeks(1)
the result will be today + 7
Tue Aug 09 2022 21:36:08 GMT+0100 (GMT+02:00)
but you may want only date without all info
addWeeks(1).toISOString().split('T')[0]
the result will be: 2022-08-09
ISO weeks (https://en.wikipedia.org/wiki/ISO_week_date):
const y = 2023;
const jan1 = new Date(y, 0, 1);
const jan1Day = jan1.getDay();
const daysToMonday = jan1Day === 1? 0 : jan1Day === 0? 1 : 8 - jan1Day
console.log('jan1', jan1)
console.log('jan1Day', jan1Day)
console.log('daysToMonday', daysToMonday)
// first Monday of the year
const firstMonday = daysToMonday === 0 ? jan1 : new Date(+jan1 + daysToMonday * 86400e3);
console.log('firstMonday', firstMonday)
// get monday of a specific week (20)
console.log('monday of week 20', new Date(+firstMonday + (20 - 1) * 7 * 86400e3))
// get sunday of a specific week (20)
console.log('sunday of week 20', new Date(+firstMonday + ((20 - 1) * 7 * 86400e3) + (86400e3 * 6) ))
Current accepted answer is close but not entirely correct. Here is the correct function:
function weekToDate(year, week) {
const days = 4 + 7 * (week - 1);
const date = new Date(year, 0, days);
return date;
}
This will yield a date that is guaranteed to be in the ISO week you asked for.
Then if you want a specific day in the week modify the date like so:
const dayOfWeek = 1 // monday
date.setDate(date.getDate() - date.getDay() + dayOfWeek)
Where dayOfWeek is the day of the week you want to get the date of. (1-7, 1 = monday)
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).
what would be a way in javascript to detect the last week of each (current) month. Or last monday of the month?
I would suggest to get the number of days in the month and then loop from the last day until getDay() gives back a Monday (1) or Sunday(0) .. based on when does your week start. Once you get your start date ... end date would be startDate + 7 so something along these lines
I found this helpful :
//Create a function that determines how many days in a month
//NOTE: iMonth is zero-based .. Jan is 0, Feb is 2 and so on ...
function daysInMonth(iMonth, iYear)
{
return 32 - new Date(iYear, iMonth, 32).getDate();
}
Then the loop:
//May - should return 31
var days_in_month = daysInMonth(4, 2010);
var weekStartDate = null;
var weekEndDate = null;
for(var i=days_in_month; i>0; i--)
{
var tmpDate = new Date(2010, 4, i);
//week starting on sunday
if(tmpDate.getDay() == 0)
{
weekStartDate = new Date(tmpDate);
weekEndDate = new Date(tmpDate.setDate(tmpDate.getDate() + 6));
//break out of the loop
break;
}
}
Playing with the date object and its methods you can do the following..
update
the complete calculations to get to last monday of the month could be compacted to
var d = new Date();
d.setMonth( d.getMonth() + 1 );
d.setDate(0);
lastmonday = d.getDate() - (d.getDay() - 1);
alert(lastmonday);
verbose example..
var now = new Date(); // get the current date
// calculate the last day of the month
if (now.getMonth() == 11 ) // if month is dec then go to next year and first month
{
nextmonth = 0;
nextyear = now.getFullYear() + 1;
}
else // otherwise go to next month of current year
{
nextmonth = now.getMonth() + 1;
nextyear = now.getFullYear();
}
var d = new Date( nextyear , nextmonth , 0); // setting day to 0 goes to last date of previous month
alert( d.getDay() ); // will alert the day of the week 0 being sunday .. you can calculate from there to get the first day of that week ..
Use getDay() to get the day of week of the last day in month and work from that (substracting the value from the number of days of the month should probably do the trick. +/- 1).
To determine whether it is a Monday, use .getDay() == 1. To determine if it is the last of the month, add seven days and compare months: nextMonday.setDate(monday.getDate()+7);
nextMonday.getMonth() == monday.getMonth();
The Javascript "Date" object is your friend.
function lastOfThisMonth(whichDay) {
var d= new Date(), month = d.getMonth();
d.setDate(1);
while (d.getDay() !== whichDay) d.setDate(d.getDate() + 1);
for (var n = 1; true; n++) {
var nd = new Date(d.getFullYear(), month, d.getDate() + n * 7);
if (nd.getMonth() !== month)
return new Date(d.getFullYear(), month, d.getDate() + (n - 1) * 7).getDate();
}
}
That'll give you the date (in the month, like 30) of the last day of the month that's the chosen day of the week (0 through 7).
Finding the last week of the month will depend on what you mean by that. If you mean the last complete week, then (if you mean Sunday - Saturday) find the last Saturday, and subtract 6. If you mean the last week that starts in the month, find the last Sunday.
You may also like to find the third Monday or the first Tuesday before or after a given date,
or flag every Wednesday between two dates.
Date.prototype.lastweek= function(wd, n){
n= n || 1;
return this.nextweek(wd, -n);
}
Date.prototype.nextweek= function(wd, n){
if(n== undefined) n= 1;
var incr= (n<0)? 1: -1,
D= new Date(this),
dd= D.getDay();
if(wd=== undefined) wd= dd;
if(dd!= wd) while(D.getDay()!= wd) D.setDate(D.getDate()+incr);
D.setDate(D.getDate()+7*n);
D.setHours(0, 0, 0, 0);
return D;
}
function lastMondayinmonth(month, year){
var day= new Date();
if(!month) month= day.getMonth()+1;
if(!year) year= day.getFullYear();
day.setFullYear(year, month, 0);
return day.lastweek(1);
}
alert(lastMondayinmonth())
i found such example that detects last monday of each week but it wont detect last monday of the month. maybe it will help to find better solution, that code looks short.
var dif, d = new Date(); // Today's date
dif = (d.getDay() + 6) % 7; // Number of days to subtract
d = new Date(d - dif * 24*60*60*1000); // Do the subtraction
alert(d); // Last monday.
OK, so far i came up with such solution making it a bit of my own way and getting a few things mentioned here. It works correct and always returns the last monday of current month.
//function that will help to check how many days in month
function daysInMonth(iMonth, iYear)
{
return 32 - new Date(iYear, iMonth, 32).getDate();
}
var dif = null;
d = new Date(); // Today's date
countDays = daysInMonth(d.getMonth(),d.getFullYear()); //Checking number of days in current month
d.setDate(countDays); //setting the date to last day of the month
dif = (d.getDay() + 6) % 7; // Number of days to subtract
d = new Date(d - dif * 24*60*60*1000); // Do the subtraction
alert(d.getDate()); //finally you get the last monday of the current month
Get the last day of the month:
/**
* Accepts either zero, one, or two parameters.
* If zero parameters: defaults to today's date
* If one parameter: Date object
* If two parameters: year, (zero-based) month
*/
function getLastDay() {
var year, month;
var lastDay = new Date();
if (arguments.length == 1) {
lastDay = arguments[0];
} else if (arguments.length > 0) {
lastDay.setYear(arguments[0]);
lastDay.setMonth(arguments[1]);
}
lastDay.setMonth(lastDay.getMonth() + 1);
lastDay.setDate(0);
return lastDay;
}
Get the last Monday:
/**
* Accepts same parameters as getLastDay()
*/
function getLastMonday() {
var lastMonday = getLastDay.apply(this, arguments);
lastMonday.setDate(lastMonday.getDate() - (lastMonday.getDay() == 0 ? 6 : (lastMonday.getDay() - 1)));
return lastMonday;
}
Get week of the year for a given day:
/**
* Accepts one parameter: Date object.
* Assumes start of week is Sunday.
*/
function getWeek(d) {
var jan1 = new Date(d.getFullYear(), 0, 1);
return Math.ceil((((d - jan1) / (24 * 60 * 60 * 1000)) + jan1.getDay() + 1) / 7);
}
Putting them together (assuming you're using Firebug):
// Get the last day of August 2006:
var august2006 = new Date(2006, 7);
var lastDayAugust2006 = getLastDay(august2006);
console.log("lastDayAugust2006: %s", lastDayAugust2006);
// ***** Testing getWeek() *****
console.group("***** Testing getWeek() *****");
// Get week of January 1, 2010 (Should be 1):
var january12010Week = getWeek(new Date(2010, 0, 1));
console.log("january12010Week: %s", january12010Week);
// Get week of January 2, 2010 (Should still be 1):
var january22010Week = getWeek(new Date(2010, 0, 2));
console.log("january22010Week: %s", january22010Week);
// Get week of January 3, 2010 (Should be 2):
var january32010Week = getWeek(new Date(2010, 0, 3));
console.log("january32010Week: %s", january32010Week);
console.groupEnd();
// *****************************
// Get the last week of this month:
var lastWeekThisMonth = getWeek(getLastDay());
console.log("lastWeekThisMonth: %s", lastWeekThisMonth);
// Get the last week of January 2007:
var lastWeekJan2007 = getWeek(getLastDay(2007, 0));
console.log("lastWeekJan2007: %s", lastWeekJan2007);
// Get the last Monday of this month:
var lastMondayThisMonth = getLastMonday();
console.log("lastMondayThisMonth: %s", lastMondayThisMonth);
// Get the week of the last Monday of this month:
var lastMondayThisMonthsWeek = getWeek(lastMondayThisMonth);
console.log("lastMondayThisMonthsWeek: %s", lastMondayThisMonthsWeek);