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.
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.
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.
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()); 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> d.setMilliseconds(0) as well - it kept showing different week numbers for the same date depending on whether I used new Date() or new Date("1/4/2016"). Just a heads up for others who might experience the same.You can use momentjs library also:
moment().week()Luxon or Day.js. Here is the topic from moment.js: momentjs.com/docs/#/-project-status/recommendationsNot 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); } 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 +6 ) % 7 part does. Thanks from a scrub!javascript date = date instanceof Date ? new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) : new Date() 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.
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)); } 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 need the week to begin on a Sunday; I think the only needed change is in function weekday()'s .getDay()+1 to be changed to .getDay()I found useful the Java SE's SimpleDateFormat class described on Oracle's specification. 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); }; new Date(Date.UTC(2018,11, 31)).getWeek(1)+1 (Monday is the 1st day of week in Germany).this code fixes a bug in answer by nvd
function getWeek(param) { let onejan = new Date(param.getFullYear(), 0, 1); return Math.ceil((((param.getTime() - onejan.getTime()) / 86400000) + onejan.getDay()) / 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'); 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.
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; fromJSDate() is just one of many. Luxon was created by one of the maintainers of MomentJS, and is expected to be maintained indefinitely. At this point in time, either this or Moment are really the best ways to accomplish this task.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); } According to https://en.wikipedia.org/wiki/ISO_week_date
Weeks start with Monday and end on Sunday. Each week's year is the Gregorian year in which the Thursday falls. The first week of the year, hence, always contains 4 January.
date-fns getWeek does this.
It can be tested according to wiki's "Examples of contemporary dates around New Year's Day" table as following:
in jsfiddle
// html <script src="https://cdn.jsdelivr.net/npm/[email protected]/cdn.min.js"></script> result1: <span id="result1"></span><br> result2: <span id="result2"></span><br> result3: <span id="result3"></span><br> result4: <span id="result4"></span><br> result5: <span id="result5"></span><br> result6: <span id="result6"></span><br> result7: <span id="result7"></span><br> result8: <span id="result8"></span><br> // js function getWeek (date) { return dateFns.getWeek(date, { weekStartsOn: 1, firstWeekContainsDate: 4 }) } document.getElementById('result1').innerHTML = getWeek('1977-01-01') document.getElementById('result2').innerHTML = getWeek('1977-01-02') document.getElementById('result3').innerHTML = getWeek('1978-01-01') document.getElementById('result4').innerHTML = getWeek('1978-01-02') document.getElementById('result5').innerHTML = getWeek('1979-01-01') document.getElementById('result6').innerHTML = getWeek('1979-01-02') document.getElementById('result7').innerHTML = getWeek('1980-12-28') document.getElementById('result8').innerHTML = getWeek('1980-12-29') results:
As of April 2025, The TC39 Temporal Proposal is in stage 3, and currently being worked on by being worked on the JS engine implementers. BUT it can be accessed now by using a polyfill.
It has a built-in function to get ISO 8601 weekOfYear
const date = Temporal.PlainDate.from("2019-12-31"); console.log(date4.weekOfYear); // 1 Based on the explanation on Wikipedia, I made a simpler implementation that's easy to understand.
/** * Returns the ISO 8601 week number * @param {Date} target */ function getWeek(target) { const targetYear = target.getFullYear(); const Dec31 = new Date(targetYear, 11, 31); const dec31WeekDay = getISOWeekDay(Dec31.getDay()); // if Dec 31 is Monday(1), Tuesday(2) or Wednesday(3), last few days would be in week 1 of next year if ( dec31WeekDay < 4 && target.getMonth() === 11 && target.getDate() > 31 - dec31WeekDay ) { return 1; } const Jan1 = new Date(targetYear, 0, 1); const jan1WeekDay = getISOWeekDay(Jan1.getDay()); // If Jan 1 is on a Monday(1), Tuesday(2), Wednesday(3) or Thursday(4), it is in W01. // If it is on a Friday(5), it is part of W53 of the previous year. // If it is on a Saturday(6), it is part of the last week of the previous year, // which is numbered W52 in a common year and W53 in a leap year. // If it is on a Sunday(7), it is part of W52 of the previous year. if ( jan1WeekDay > 4 && target.getMonth() === 0 && target.getDate() <= 7 - jan1WeekDay + 1 ) { return jan1WeekDay === 5 || (jan1WeekDay === 6 && isLeapYear(targetYear - 1)) ? 53 : 52; } // 1-based days into the year (1-366) const dayOfYear = Math.floor((target.getTime() - Jan1.getTime()) / (1000 * 60 * 60 * 24)) + 1; // The offset is the number of days till the *second* Monday when Jan 1 is in W01, // and, number of days till the *first* Monday otherwise, i.e. when Jan 1 lies in the last week of previous year // Both happen to have the same formula. const offset = 7 - jan1WeekDay + 1; return Math.ceil((dayOfYear - offset) / 7) + (jan1WeekDay > 4 ? 0 : 1); } /** @param {number} year 4-digit year */ function isLeapYear(year) { return year % 4 === 0 && !(year % 100 === 0 && year % 400 !== 0); } /** * Converts JS week day to ISO 8601 week year day. * - JS Week: starts on Sunday, 0-6 * - ISO 8601 Week: Starts on Monday (1-7) * * @param {number} day Week Day from Date object method */ function getISOWeekDay(day) { return ((6 + day) % 7) + 1; }