Show week number with Javascript?
Asked Answered
B

16

38

I have the following code that is used to show the name of the current day, followed by a set phrase.

<script type="text/javascript"> 
    <!-- 
    // Array of day names
    var dayNames = new Array(
    "It's Sunday, the weekend is nearly over",
    "Yay! Another Monday",
     "Hello Tuesday, at least you're not Monday",
     "It's Wednesday. Halfway through the week already",
     "It's Thursday.",
     "It's Friday - Hurray for the weekend",
    "Saturday Night Fever");
    var now = new Date();
    document.write(dayNames[now.getDay()] + ".");
     // -->
</script>

What I would like to do is have the current week number in brackets after the phrase. I have found the following code:

Date.prototype.getWeek = function() {
    var onejan = new Date(this.getFullYear(),0,1);
    return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
} 

Which was taken from http://javascript.about.com/library/blweekyear.htm but I have no idea how to add it to existing javascript code.

Bread answered 14/10, 2011 at 9:38 Comment(1)
note that week numbering can be locale-specific (or otherwise culturally arbitrary) < en.wikipedia.org/wiki/Seven-day_week#Week_numbering >. do you want ISO 8601 week numbers? < en.wikipedia.org/wiki/ISO_8601#Week_dates >Alonzoaloof
S
61

Simply add it to your current code, then call (new Date()).getWeek()

<script>
    Date.prototype.getWeek = function() {
        var onejan = new Date(this.getFullYear(), 0, 1);
        return Math.ceil((((this - onejan) / 86400000) + onejan.getDay() + 1) / 7);
    }

    var weekNumber = (new Date()).getWeek();

    var dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
    var now = new Date();
    document.write(dayNames[now.getDay()] + " (" + weekNumber + ").");
</script>
Sedition answered 14/10, 2011 at 9:42 Comment(8)
Thanks! That works but for some reason it's showing the current week number as 42 but all online resources say week 41. I have checked the time/date on the server and the computer but they are both correct. Any ideas?Bread
If I alter the fourth line to 'var onejan = new Date(this.getFullYear(),0,2);' it's correct. Is that the right way to do it?Bread
If your week doesn't start on Sunday, probably you would like to use this: #6118314Springhouse
@Bread "It works, but it shows the wrong week number"?Venezuela
It should be Math.floor() instead of Math.ceil(). With Math.floor() it's work fine for me!Epigastrium
Also if your week does not start on Sunday, you can change the + 1 into a - 1 at the line 4Epigastrium
First, you have to ask yourself if you want the equivalent of strftime %U, %V, or %W. I think people generally use the ISO 8601 week number (%V), where week 1 is the week that has the first Thursday of that year.Detention
This is the mistake: var onejan = new Date(this.getFullYear(), 0, 1) That's because, according to ISO, the first week of the year is the one that has the first Thursday. Or, in other words, the week that has Jan 4th in it. This solves the problem: var onejan = new Date(this.getFullYear(), 0, 4) That also means onejan is not the right name for that variable.Tatman
O
20

In case you already use jQuery-UI (specifically datepicker):

Date.prototype.getWeek = function () { return $.datepicker.iso8601Week(this); }

Usage:

var myDate = new Date();
myDate.getWeek();

More here: UI/Datepicker/iso8601Week

I realize this isn't a general solution as it incurs a dependency. However, considering the popularity of jQuery-UI this might just be a simple fit for someone - as it was for me.


If you don't use jQuery-UI and have no intention of adding the dependency. You could just copy their iso8601Week() implementation since it is written in pure JavaScript without complex dependencies:

// Determine the week of the year (local timezone) based on the ISO 8601 definition.
Date.prototype.iso8601Week = function () {
  // Create a copy of the current date, we don't want to mutate the original
  const date = new Date(this.getTime());

  // Find Thursday of this week starting on Monday
  date.setDate(date.getDate() + 4 - (date.getDay() || 7));
  const thursday = date.getTime();

  // Find January 1st
  date.setMonth(0); // January
  date.setDate(1);  // 1st
  const jan1st = date.getTime();

  // Round the amount of days to compensate for daylight saving time
  const days = Math.round((thursday - jan1st) / 86400000); // 1 day = 86400000 ms
  return Math.floor(days / 7) + 1;
};

console.log(new Date().iso8601Week());
console.log(new Date("2020-01-01T00:00").iso8601Week());
console.log(new Date("2021-01-01T00:00").iso8601Week());
console.log(new Date("2022-01-01T00:00").iso8601Week());
console.log(new Date("2023-12-31T00:00").iso8601Week());
console.log(new Date("2024-12-31T00:00").iso8601Week());
Orjonikidze answered 2/1, 2013 at 18:55 Comment(0)
J
14

Consider using my implementation of "Date.prototype.getWeek", think is more accurate than the others i have seen here :)

Date.prototype.getWeek = function(){
    // We have to compare against the first monday of the year not the 01/01
    // 60*60*24*1000 = 86400000
    // 'onejan_next_monday_time' reffers to the miliseconds of the next monday after 01/01

    var day_miliseconds = 86400000,
        onejan = new Date(this.getFullYear(),0,1,0,0,0),
        onejan_day = (onejan.getDay()==0) ? 7 : onejan.getDay(),
        days_for_next_monday = (8-onejan_day),
        onejan_next_monday_time = onejan.getTime() + (days_for_next_monday * day_miliseconds),
        // If one jan is not a monday, get the first monday of the year
        first_monday_year_time = (onejan_day>1) ? onejan_next_monday_time : onejan.getTime(),
        this_date = new Date(this.getFullYear(), this.getMonth(),this.getDate(),0,0,0),// This at 00:00:00
        this_time = this_date.getTime(),
        days_from_first_monday = Math.round(((this_time - first_monday_year_time) / day_miliseconds));

    var first_monday_year = new Date(first_monday_year_time);

    // We add 1 to "days_from_first_monday" because if "days_from_first_monday" is *7,
    // then 7/7 = 1, and as we are 7 days from first monday,
    // we should be in week number 2 instead of week number 1 (7/7=1)
    // We consider week number as 52 when "days_from_first_monday" is lower than 0,
    // that means the actual week started before the first monday so that means we are on the firsts
    // days of the year (ex: we are on Friday 01/01, then "days_from_first_monday"=-3,
    // so friday 01/01 is part of week number 52 from past year)
    // "days_from_first_monday<=364" because (364+1)/7 == 52, if we are on day 365, then (365+1)/7 >= 52 (Math.ceil(366/7)=53) and thats wrong

    return (days_from_first_monday>=0 && days_from_first_monday<364) ? Math.ceil((days_from_first_monday+1)/7) : 52;
}

You can check my public repo here https://bitbucket.org/agustinhaller/date.getweek (Tests included)

Judgeship answered 20/3, 2012 at 4:40 Comment(4)
Right now it says it's week 40, which is wrong (it's week 41 now). Not really "more accurate than the others"...Gamekeeper
Right, this function is not working. It shows week 18 now while it's actually week 19.Sedition
basteln and this.lau_, that is because this code calculates American week numbers, not ISO Standard week numbers.Poteet
first_monday_year is unusedVenezuela
S
13

If you want something that works and is future-proof, use a library like MomentJS.

moment(date).week();
moment(date).isoWeek()

http://momentjs.com/docs/#/get-set/week/

Selfexecuting answered 20/4, 2016 at 6:40 Comment(2)
This should be the top answer. Modifying the prototype of Date, like suggested above, is a really bad practice.Coacervate
The project status of MomentJS itself recommends against using MomentJS in new projects. Consider other alternatives.Daniels
P
10

It looks like this function I found at weeknumber.net is pretty accurate and easy to use.

// This script is released to the public domain and may be used, modified and
// distributed without restrictions. Attribution not necessary but appreciated.
// Source: http://weeknumber.net/how-to/javascript 

// Returns the ISO week of the date.
Date.prototype.getWeek = function() {
  let date = new Date(this.getTime());
  date.setHours(0, 0, 0, 0);
  // Thursday in current week decides the year.
  date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
  // January 4 is always in week 1.
  let week1 = new Date(date.getFullYear(), 0, 4);
  // Adjust to Thursday in week 1 and count number of weeks from date to week1.
  return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
}

If you're lucky like me and need to find the week number of the month a little adjust will do it:

// Returns the week in the month of the date.
Date.prototype.getWeekOfMonth = function() {
  let date = new Date(this.getTime());
  date.setHours(0, 0, 0, 0);
  // Thursday in current week decides the year.
  date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
  // January 4 is always in week 1.
  let week1 = new Date(date.getFullYear(), date.getMonth(), 4);
  // Adjust to Thursday in week 1 and count number of weeks from date to week1.
  return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
}
Poff answered 16/12, 2015 at 23:13 Comment(0)
N
4

If you already use Angular, then you could profit $filter('date').

For example:

var myDate = new Date();
var myWeek = $filter('date')(myDate, 'ww');
Navarrette answered 7/4, 2016 at 6:23 Comment(0)
M
3

I was coding in the dark (a challenge) and couldn't lookup, bring in any dependencies or test my code.

I forgot what round up was called (Math.celi) So I wanted to be extra sure i got it right and came up with this code instead.

var elm = document.createElement('input')
elm.type = 'week'
elm.valueAsDate = new Date()
var week = elm.value.split('W').pop()

console.log(week)
Just a proof of concept of how you can get the week in any other way

But still i recommend any other solution that isn't required by the DOM.

Member answered 30/8, 2017 at 9:16 Comment(0)
S
2

By adding the snippet you extend the Date object.

Date.prototype.getWeek = function() {
    var onejan = new Date(this.getFullYear(),0,1);
    return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
}

If you want to use this in multiple pages you can add this to a seperate js file which must be loaded first before your other scripts executes. With other scripts I mean the scripts which uses the getWeek() method.

Snaggy answered 14/10, 2011 at 9:49 Comment(1)
This function is not always accurate, because January 4 is the day that matters for ISO weeknumber count.Poff
H
2

All the proposed approaches may give wrong results because they don’t take into account summer/winter time changes. Rather than calculating the number of days between two dates using the constant of 86’400’000 milliseconds, it is better to use an approach like the following one:

getDaysDiff = function (dateObject0, dateObject1) {
    if (dateObject0 >= dateObject1) return 0;
    var d = new Date(dateObject0.getTime());
    var nd = 0;
    while (d <= dateObject1) {
        d.setDate(d.getDate() + 1);
        nd++;
    }
    return nd-1;
};
Hiram answered 9/5, 2012 at 9:44 Comment(1)
"All the proposed approaches may give wrong results" such claims are useless. Answers are added as time goes by, and there are several that are 100% correct.Histogen
R
1

In browsers that support the week input type, the following function should work:

function isoWeek(date) {
  const input = document.createElement('input');
  input.type = 'week';
  input.valueAsDate = date;
  return input.value;
};

Cf.

>>> isoWeek(new Date("2022-01-01"))
'2021-W52'
>>> isoWeek(new Date("2022-01-03"))
'2022-W01'
>>> isoWeek(new Date("2023-12-14"))
'2023-W50'
>>> isoWeek(new Date("2024-01-01"))
'2024-W01'
Rheingold answered 14/12, 2023 at 12:51 Comment(0)
U
0

With that code you can simply;

document.write(dayNames[now.getDay()] + " (" + now.getWeek() + ").");

(You will need to paste the getWeek function above your current script)

Unaccountedfor answered 14/10, 2011 at 9:43 Comment(0)
B
0

You could find this fiddle useful. Just finished. https://jsfiddle.net/dnviti/ogpt920w/ Code below also:

/** 
 * 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 first  
  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 weeknumber is the number of weeks between the   
  // first thursday of the year and the thursday in the target week  
  return 1 + Math.ceil((firstThursday - target) / 604800000); // 604800000 = 7 * 24 * 3600 * 1000  
}  

/** 
* Get the ISO week date year number 
*/  
Date.prototype.getWeekYear = function ()   
{  
  // Create a new date object for the thursday of this week  
  var target  = new Date(this.valueOf());  
  target.setDate(target.getDate() - ((this.getDay() + 6) % 7) + 3);  

  return target.getFullYear();  
}

/** 
 * Convert ISO week number and year into date (first day of week)
 */ 
var getDateFromISOWeek = function(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;
}

var printDate = function(){
  /*var dateString = document.getElementById("date").value;
	var dateArray = dateString.split("/");*/ // use this if you have year-week in the same field

  var dateInput = document.getElementById("date").value;
  if (dateInput == ""){
    var date = new Date(); // get today date object
  }
  else{
    var date = new Date(dateInput); // get date from field
  }

  var day = ("0" + date.getDate()).slice(-2); // get today day
  var month = ("0" + (date.getMonth() + 1)).slice(-2); // get today month
  var fullDate = date.getFullYear()+"-"+(month)+"-"+(day) ; // get full date
  var year = date.getFullYear();
  var week = ("0" + (date.getWeek())).slice(-2);
  var locale= "it-it";
  
  document.getElementById("date").value = fullDate; // set input field

  document.getElementById("year").value = year;
  document.getElementById("week").value = week; // this prototype has been written above

  var fromISODate = getDateFromISOWeek(week, year);
  
	var fromISODay = ("0" + fromISODate.getDate()).slice(-2);
  var fromISOMonth = ("0" + (fromISODate.getMonth() + 1)).slice(-2);
  var fromISOYear = date.getFullYear();
  
  // Use long to return month like "December" or short for "Dec"
  //var monthComplete = fullDate.toLocaleString(locale, { month: "long" }); 

  var formattedDate = fromISODay + "-" + fromISOMonth + "-" + fromISOYear;

  var element = document.getElementById("fullDate");

  element.value = formattedDate;
}

printDate();
document.getElementById("convertToDate").addEventListener("click", printDate);
*{
  font-family: consolas
}
<label for="date">Date</label>
<input type="date" name="date" id="date" style="width:130px;text-align:center" value="" />
<br /><br />
<label for="year">Year</label>
<input type="year" name="year" id="year" style="width:40px;text-align:center" value="" />
-
<label for="week">Week</label>
<input type="text" id="week" style="width:25px;text-align:center" value="" />
<br /><br />
<label for="fullDate">Full Date</label>
<input type="text" id="fullDate" name="fullDate" style="width:80px;text-align:center" value="" />
<br /><br />
<button id="convertToDate">
Convert Date
</button>

It's pure JS. There are a bunch of date functions inside that allow you to convert date into week number and viceversa :)

Battleship answered 7/12, 2016 at 17:22 Comment(0)
H
0

Luxon is an other alternative. Luxon date objects have a weekNumber property:

let week = luxon.DateTime.fromString("2022-04-01", "yyyy-MM-dd").weekNumber;
console.log(week);
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/3.0.1/luxon.min.js"></script>
Histogen answered 11/7, 2022 at 21:52 Comment(0)
O
0

I've tried using code from all of the answers above, and all return week #52 for the first of January. So I decided to write my own, which calculates the week number correctly. Week numeration starts from 0

Maybe it's a bad taste to use a loop, or the result can be cached somewhere to prevent repeating the same calculations if the function is called often enough. Well, I have made this for myself, and it does what I need it to do.

    Date.prototype.getWeek = function() {
       // debugger
        let msWeek = 604800000;                                     // Week in milliseconds
        let msDay = 86400000;                                       // Day in milliseconds
        let year = this.getFullYear();                              // Get the year
        //let month = this.getMonth();                                // Month
        let oneDate = new Date(year, 0, 1);                         // Create a new date based on THIS year
        let temp = oneDate.getDay();                                // Ordinal of the first day
        let getFirstDay = (temp === 0) ? 6 : temp - 1;              // Ordinal of the first day of the current month (0-MO, 6-SU)
        let countWeek  = 0;
        // Test to confirm week
        oneDate = new Date(oneDate.getTime() + msDay*(7 - getFirstDay));
        if(oneDate.getTime() > this.getTime()){
            return  countWeek;
        }
        // Increment loop
        while(true){
            oneDate = new Date(oneDate.getTime() + msWeek);                 // Add a week and check
            if(oneDate.getTime() > this.getTime()) break;
            countWeek++;
        }
        return countWeek + 1;
    }

    let s1 = new Date('2022-01-01'); console.log(s1.getWeek());
    let s2 = new Date('2023-01-01'); console.log(s2.getWeek());
    let s22 = new Date('2023-01-02'); console.log(s22.getWeek());
    let s3 = new Date('2024-01-01'); console.log(s3.getWeek());
    let s4 = new Date('2025-01-01'); console.log(s4.getWeek());
    let s5 = new Date('2022-02-28'); console.log(s5.getWeek());
    let s6 = new Date('2022-12-31'); console.log(s6.getWeek());
    let s7 = new Date('2024-12-31'); console.log(s7.getWeek());
Overcareful answered 11/11, 2022 at 19:48 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Rascally
V
-1

Some of the code I see in here fails with years like 2016, in which week 53 jumps to week 2.

Here is a revised and working version:

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;  

  // Set the target to the thursday of this week so the  
  // target date is in the right year  
  target.setDate(target.getDate() - dayNr + 3);  

  // ISO 8601 states that week 1 is the week with january 4th in it  
  var jan4    = new Date(target.getFullYear(), 0, 4);  

  // Number of days between target date and january 4th  
  var dayDiff = (target - jan4) / 86400000;    

  if(new Date(target.getFullYear(), 0, 1).getDay() < 5) {
    // Calculate week number: Week 1 (january 4th) plus the    
    // number of weeks between target date and january 4th    
    return 1 + Math.ceil(dayDiff / 7);    
  }
  else {  // jan 4th is on the next week (so next week is week 1)
    return Math.ceil(dayDiff / 7); 
  }
}; 
Volatilize answered 21/1, 2016 at 1:51 Comment(1)
This code fails in 2017: It jumps from week 52 on 1-jan to week 2 on 2->8 jan. For the rest of the year it's always 1 week ahead of what it should be, and ends with week 53Ulotrichous
J
-1

Martin Schillinger's version seems to be the strictly correct one.

Since I knew I only needed it to work correctly on business week days, I went with this simpler form, based on something I found online, don't remember where:

ISOWeekday = (0 == InputDate.getDay()) ? 7 : InputDate.getDay();
ISOCalendarWeek = Math.floor( ( ((InputDate.getTime() - (new Date(InputDate.getFullYear(),0,1)).getTime()) / 86400000) - ISOWeekday + 10) / 7 );

It fails in early January on days that belong to the previous year's last week (it produces CW = 0 in those cases) but is correct for everything else.

Jemima answered 18/5, 2017 at 12:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.