Search code examples
javascriptjquerydatedatepicker

Find all the days in a month with Date object?


is there a way to have all the days of a month or of a year? I am looking for this in order to disable some specific days in a datepicker, i would have a page in the back-office to select these days to disable.

So i would need to show all the days in a month, and add a "activate or deactive" button below each day. Is there a way to find these days with the Date object? I found this link for example : Displaying all the days of a month but i don't really understand it, plus it is Java, i am trying to find a solution in javascript.

Thank you for your help


Solution

  • To get a list of all days in a month, you can start with a Date on the first day of a month, increase the day until the month changes.

    /**
     * @param {int} The month number, 0 based
     * @param {int} The year, not zero based, required to account for leap years
     * @return {Date[]} List with date objects for each day of the month
     */
    function getDaysInMonth(month, year) {
      var date = new Date(year, month, 1);
      var days = [];
      while (date.getMonth() === month) {
        days.push(new Date(date));
        date.setDate(date.getDate() + 1);
      }
      return days;
    }
    

    UTC Version

    In response to some comments, I've created a version that uses UTC methods in case you want to call UTC methods instead of the standard methods that return the localized time zone.

    I suspect this is the culprit of the comments saying this didn't work. You typically want to make sure you call getUTCMonth/Day/Hours methods if you instantiated it with Date.UTC, and vice-versa, unless you are trying to convert time zones and show differences.

    function getDaysInMonthUTC(month, year) {
      var date = new Date(Date.UTC(year, month, 1));
      var days = [];
      while (date.getUTCMonth() === month) {
        days.push(new Date(date));
        date.setUTCDate(date.getUTCDate() + 1);
      }
      return days;
    }
    

    Editing This Answer

    If you think there's a problem with this script, please feel free to:

    • First see existing unit tests below
    • Write a test case that proves it's broken.
    • Fix the code, making sure existing tests pass.

    Unit Tests

    /**
     * @param {int} The month number, 0 based
     * @param {int} The year, not zero based, required to account for leap years
     * @return {Date[]} List with date objects for each day of the month
     */
    function getDaysInMonthUTC(month, year) {
      var date = new Date(Date.UTC(year, month, 1));
      var days = [];
      while (date.getUTCMonth() === month) {
        days.push(new Date(date));
        date.setUTCDate(date.getUTCDate() + 1);
      }
      return days;
    }
    
    function getDaysInMonth(month, year) {
      var date = new Date(year, month, 1);
      var days = [];
      while (date.getMonth() === month) {
        days.push(new Date(date));
        date.setDate(date.getDate() + 1);
      }
      return days;
    }
    
    const days2020 = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    const days2021 = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    
    describe("getDaysInMonthUTC", function() {
      it("gets day counts for leap years", function() {
        const actual = days2020.map(
          (day, index) => getDaysInMonthUTC(index, 2020).length
        );
        expect(actual).toEqual(days2020);
      });
    
      it("gets day counts for non-leap years", function() {
        const actual = days2021.map(
          (day, index) => getDaysInMonthUTC(index, 2021).length
        );
        expect(actual).toEqual(days2021);
      });
    });
    
    
    describe("getDaysInMonth", function() {
      it("gets day counts for leap years", function() {
        const actual = days2020.map(
          (day, index) => getDaysInMonth(index, 2020).length
        );
        expect(actual).toEqual(days2020);
      });
    
      it("gets day counts for non-leap years", function() {
        const actual = days2021.map(
          (day, index) => getDaysInMonth(index, 2021).length
        );
        expect(actual).toEqual(days2021);
      });
    });
    
    // load jasmine htmlReporter
    (function() {
      var env = jasmine.getEnv();
      env.addReporter(new jasmine.HtmlReporter());
      env.execute();
    }());
    <script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
    <script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
    <link href="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" rel="stylesheet"/>