Get week of year in JavaScript like in PHP

后端 未结 19 1308
南方客
南方客 2020-11-22 02:38

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

相关标签:
19条回答
  • 2020-11-22 02:56

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 02:58

    This week number thing has been a real pain in the a**. Most of scripts around the net didn't work for me. They worked most of time but all of them broke in 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 1st week of next year, angular gave week 53).

    Note: 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);
    
        // Get 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.

    0 讨论(0)
  • 2020-11-22 02:59

    With Luxon (https://github.com/moment/luxon) :

    import { DateTime } from 'luxon';
    const week: number = DateTime.fromJSDate(new Date()).weekNumber;
    
    0 讨论(0)
  • 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);
    }
    
    0 讨论(0)
  • 2020-11-22 03:01

    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);
                }
            }
        }
    });
    
    0 讨论(0)
  • 2020-11-22 03:04

    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
    
    0 讨论(0)
提交回复
热议问题