1

I'm currently trying to make a date / week counter, where you can increase or decrease the week number alongside the date of the week's first and last day. This is what I've got so far thanks to @ishegg

<script>
   
    var curr = new Date(new Date().getTime() + 60 * 60 * 24 * 7);
    curr.setHours(0,0,0,0);

    function week() {
        curr = new Date(new Date().getTime() + 60 * 60 * 24 * 7);

        // First day of the week
        var first = curr.getDate() - curr.getDay();

        // Last day of the week
        var last = first + 6;

        var startDate = new Date(curr.setDate(first));
        var endDate = new Date(curr.setDate(last));

        document.getElementById("start").innerHTML = startDate;
        document.getElementById("end").innerHTML = endDate;

        // 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.getElementById("week").innerHTML = ("Week " + curr.getWeekNumber());
    }

    function startOfWeek(date) {
        date.setDate(date.getDate() - date.getDay());
        return date;
    }

    function endOfWeek(date) {
        date = startOfWeek(date);
        date.setDate(date.getDate() + 6);
        return date; 
    }

    function weekPlus() {
    
        var startDate = new Date(startOfWeek(curr));
        startDate.setDate(startDate.getDate() + 7);
        var endDate = endOfWeek(curr);
        endDate.setDate(endDate.getDate() + 7);
        curr = startDate;

        document.getElementById("start").innerHTML = startDate;
        document.getElementById("end").innerHTML = endDate;

        // 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 + 1);
        };
        document.getElementById("week").innerHTML = ("Week " + curr.getWeekNumber());
    }

    function weekMinus() {

        var startDate = new Date(startOfWeek(curr));
        startDate.setDate(startDate.getDate() - 7);
        var endDate = endOfWeek(curr);
        endDate.setDate(endDate.getDate() - 7);
        curr = startDate;

        document.getElementById("start").innerHTML = startDate;
        document.getElementById("end").innerHTML = endDate;

        // 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 - 1);
        };
        document.getElementById("week").innerHTML = ("Week " + curr.getWeekNumber());
    }    
</script>


<div id="start">start</div>
<div id="end">end</div>
<div id="week">week</div>
<button onclick="week()">current</button>
<button onclick="weekPlus()">add</button>
<button onclick="weekMinus()">substract</button>

So after you press the current -button, you'll get the last and first day of the week including the week number.

You can add or substract by 1 week with each button press.

Problems with the code:

  • After adding or substracting the weeks -> pressing the current -button to reset the weeks to the current date, adding or substracting doesn't start from the current week, but from before you press the current button.

  • After pressing the add -button couple of times and then pressing substract, the week number instantly goes down by 3, instead of 1. (Same thing reversed, going up by 3, instead of 1)

  • Whenever the year changes, sometimes the week jumps straight to week 2.

Any idea's how to solve these problems with the code?

Any help is appreciated.

IlariM
  • 376
  • 1
  • 3
  • 16
  • 2
    I think it's because you're using a *local variable* `curr` within your week function, and you probably meant to update the *global variable* curr instead. Solution - within week() don't use `var` in front of `curr` – James Aug 26 '17 at 18:33
  • @James Thank you, got it fixed. Any idea's about why the week number jumps by 3 instead of 1 after adding couple of times and then substracting? – IlariM Aug 26 '17 at 18:50

1 Answers1

2

The problem is that the Date#set**** functions mutate the argument. This affects also curr at times you don't really want that to happen.

Solve this by making sure that the functions startOfWeek and endOfWeek do not modify their arguments, but return new Date instances. And then stick to calling those functions where possible, avoiding code duplication. There are only a few places where curr should be modified, and that is in the week (I renamed it to weekReset) and the weekPlus function (and weekMin, but see next point).

I would remove weekMin, as it has the same logic as weekPlus. You can settle the difference by providing weekPlus a parameter.

Don't redefine Date.prototype.getWeekNumber over and over again: just do this once.

Finally, split the rendering logic from the date calculations, again to avoid code duplication. I would create a separate display function for generating the output. Note that you don't need document.getElementById since current browsers create global variables for elements that have an id. This was also the reason I renamed the week function so it would not coincide with the variable for the element with that id.

Here is the revised code:

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);
};

var curr;
weekReset();

function display() {
    start.textContent = curr;
    end.textContent = endOfWeek(curr);
    week.textContent = ("Week " + curr.getWeekNumber());
}

function weekReset() {
    curr = startOfWeek(new Date());
    display();
}

function startOfWeek(date) {
    var start = new Date(date);
    start.setHours(0,0,0,0);
    start.setDate(start.getDate() - start.getDay());
    return start;
}

function endOfWeek(date) {
    date = startOfWeek(date);
    date.setDate(date.getDate() + 6);
    return date; 
}

function weekPlus(weeks) {
    curr.setDate(curr.getDate() + 7 * weeks);
    display();
}
<div id="start">start</div>
<div id="end">end</div>
<div id="week">week</div>
<button onclick="weekReset()">current</button>
<button onclick="weekPlus(1)">add</button>
<button onclick="weekPlus(-1)">substract</button>
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thank you works great. If the `weekReset()` , `weekPlus()` and `weekMinus()` functions we're on different pages, do I need to call `Date.prototype.getWeekNumber` on each of the pages or can I just call it inside the `week()` function page and use it on the other pages? – IlariM Aug 27 '17 at 18:53
  • That's because I gather alot more different data other than week number and dates from these functions, so they have to be on different pages. – IlariM Aug 27 '17 at 18:55
  • You need to *define* Date.prototype.getWeekNumber` on each page that references it. It is no different as other functions: you need to define them where you use them. – trincot Aug 27 '17 at 19:32
  • 1
    But I would put all the functions (including the `Date.prototype.getWeekNumer` function ) in a `.js` file, and include that script with a `script` tag in all the pages that need (some of) it. – trincot Aug 27 '17 at 19:33
  • Thank you for the help. Any idea how I could change the `getWeekNumber` -function to get the week number for my time zone? It says Week 34, but it should be week 35. – IlariM Aug 27 '17 at 22:27
  • There are different systems of week numbering. The code you have used calculates the [ISO week number](https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php), but maybe you have another system in mind. If you can't find the answer by a search, then I would suggest asking a new question just about that, explaining the logic with which you determine which week should get number 1, for all 7 possible ways a year can start. – trincot Aug 27 '17 at 23:09