Why does does removing a line effect the next one? - javascript

I'm attempting to return different days based on a given date, such as the first Monday of the week, the Friday of the week, as well as days in previous and following weeks so that I can figure out the start and end of my pay periods (for my two jobs, each are different) as well as the pay date for that period.
When I remove the Logger.log("Prev Monday > " + addDays(pMonday, -7));
the next line's value changes. What is removed line doing to mess up the following one?
I'm using this in Google App Scripts so I can pull data from a Google Calendar to a Google Sheet easily. It also means no extra libraries.
function test_monday(){
var theDate = new Date();
theDate.setDate(16);
theDate.setMonth(5);
theDate.setFullYear(2016);
theDate.setHours(12,0,0,0)
Logger.log(theDate);
var pMonday = new Date();
pMonday = getMonday( theDate ) ;
Logger.log("pMonday: " + pMonday)
Logger.log("Prev Monday > " + addDays(pMonday, -7));
Logger.log("Following Friday > " + addDays(pMonday, 4));
}
function getMonday( date ) {
var day = date.getDay() || 7;
if( day !== 1 )
date.setHours(-24 * (day - 1));
return date;
}
function addDays(d, n){
var date = new Date();
date = d;
var offset = n;
date.setHours(24 * ( offset ));
return date;
}

date = d;
This line right here completely undoes the work you did in the previous line. It says that date is the exact same instance as d. That means that whenever you modify date (date.setHours(24 * offset)) you're also modifying d. You might as well be writing d.setHours(24 * offset) because they mean the same thing.
If you want to create a new Date object equal to another one, just pass the original into the Date constructor. So you could rewrite your function as:
function addDays(d, n) {
var date = new Date(d);
date.setHours(24 * n);
return date;
}

Related

Javascript: Tabbed time period charts

I'm trying to produce a graph like the following:
From an array of events as follows:
var events = {
"0": {"guid": "78926349827546", "created": "2017-07-07 14:14:21" },
"1": {"guid": "78926349827546", "created": "2017-07-08 15:44:10" },
"2": {"guid": "20936752065745", "created": "2017-07-09 12:09:24" },
"3": {"guid": "20936752065745", "created": "2017-07-11 06:55:42" },
"4": {"guid": "20936752065745", "created": "2017-07-11 22:10:29" },
...
};
I'm currently using the Google Line Chart. Although I'm happy with the aesthetic, I still need to find a way to produce a tabbed display of several timescales, e.g. Today, Last 7 Days, Last Month and Total.
Programmatically, this is proving to be a sisyphean task, as I have to count occurrences across (in one instance) every hour in the last day, and then (in another instance) every day in the last week etc.
And there's a lot of date conversion, counting backwards from today and so on.
Is there a way of taking my array and producing a new array of human-readable dates relative from today, across several timescales?
This is really a duplicate of a couple of questions like Where can I find documentation on formatting a date in JavaScript?, How to add months to a date in JavaScript? and Add days to JavaScript Date. So there are plenty of existing examples to work from.
Also, Google Charts has its own date formatter.
Anyway, you might use a function that takes a start date, end date and increment and returns an array of timestamps in a particular format. Formatting the strings can use a second function or the Google Charts formatter.
A bare bones version is very little code, to add some logic for forward or backward series takes a few more lines.
// Return date string in YYYY-MM-DD HH:mm:ss format
function formatDate(date) {
function z(n){return (n<10? '0':'') + n}
return date.getFullYear() + '-' +
z(date.getMonth() + 1) + '-' +
z(date.getDate()) + ' ' +
z(date.getHours()) + ':' +
z(date.getMinutes()) + ':' +
z(date.getSeconds());
}
// Return date strings from start date to end date
// with increment inc in hours
function getDateSeries(start, end, inc) {
var d = new Date(+start);
inc = +inc;
var dates = [];
// Deal with backwards sequences
var reverse = false, t;
if (start > end) {
t = start;
start = end;
end = t;
reverse = true;
}
if (inc < 0) {
reverse = true;
inc *= -1;
}
while (start <= end) {
dates.push(formatDate(start));
start.setHours(start.getHours() + inc);
}
return reverse? dates.reverse() : dates;
}
// Hourly intervals over 2 days forwards
console.log(getDateSeries(new Date(2017,7,18), new Date(2017,7,19), 1));
// 6 hourly intervals over 10 days backwards
console.log(getDateSeries(new Date(2017,7,28), new Date(2017,7,18), -6));
// Hourly intervals from now going back 24 hours
var now = new Date();
var end = new Date(+now);
end.setDate(end.getDate() - 1);
console.log(getDateSeries(now, end, -1))
// Daily intervals from today going back 30 days
var now = new Date();
now.setHours(0,0,0,0);
var end = new Date(+now);
end.setDate(end.getDate() - 30);
console.log(getDateSeries(now, end, -24))
There are plenty of libraries around to help with formatting, incrementing and decrementing dates but if this is all you want to do, it doesn't take much to write.
This could be modified so the start is always "now" or "today" and use an interval in days rather than a start and end date with hours.
Where a library would come in handy is if you want say monthly intervals on the last day of the month or similar (since months aren't of equal length). So using moment.js you could do:
function getMonthlySequenceStart(months) {
var format = 'YYYY-MM-DD HH:mm:ss'
var now = moment().startOf('month');
var count = Math.abs(months);
var direction = months < 0? -1 : 1;
var result = [];
while (count--) {
result.push(now.format(format));
now.add(direction, 'months');
}
return result;
}
console.log(getMonthlySequenceStart(-12));
function getMonthlySequenceEnd(months) {
var format = 'YYYY-MM-DD HH:mm:ss'
var now = moment().endOf('month').startOf('day');
var count = Math.abs(months);
var direction = months < 0? -1 : 1;
var result = [];
while (count--) {
result.push(now.format(format));
now.add(direction, 'months');
now.endOf('month').startOf('day');
}
return result;
}
console.log(getMonthlySequenceEnd(-12));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
Not using a library isn't too hard either. The following sets the date to the first of the month as then it's easy to decrement by 1 month, then get the day before (the last day of the previous month) for the string:
// Sequence of end of months from current month
// back for num months
function getMonthlySequenceEnd(num) {
var now = new Date();
now.setHours(0,0,0,0);
var t, result = [];
// Set to first day of next month
now.setMonth(now.getMonth() + 1, 1)
while (num--) {
t = new Date(+now);
t.setDate(t.getDate() - 1);
result.push(formatDate(t));
now.setMonth(now.getMonth() - 1);
}
return result;
}
function formatDate(date) {
function z(n) {return (n < 10 ? '0' : '') + n}
return date.getFullYear() + '-' + z(date.getMonth() + 1) + '-' + z(date.getDate()) + ' ' +
z(date.getHours()) + ':' + z(date.getMinutes()) + ':' + z(date.getSeconds());
}
console.log(getMonthlySequenceEnd(24));
So I think you now have enough to do whatever is required.

take a date string, add a class to span if expiration date is less than 2 weeks from now

i've been stuck on this problem for a while now and I am ready to pull my hair out :). I have to add a class to a span if a campaign date is expiring in 2 weeks or less. The date retrieved is a string in the following format
07/26/2017
when I run this function, I am passing the datestring as an argument since the method will be attached to the var which holds the string. But for whatever reason this logic isn't working. Am I totally screwing this up? It's failing silently somewhere. Thank you. I know it should be easy but I am caught in a loop.
campMethods.EndDateAlert = function (dateString) {
var currentDate = new Date ();
var twoWeeks = new Date ();
twoWeeks.setDate(currentDate.getDate() + 14)
var $EndDateSpan = $('.campaign-end-date');
if (dateString <= twoWeeks) {
$EndDateSpan.addClass('red');
}
return dateString;
};
You can do that with some Math. The key is, 2 weeks = 14 days.
Here is Pure Javascript example for you:
var date = "07/26/2017".split("/");
var formatedDate = (date[2] + '' + date[0] + '' + date[1]);
var currentDate = new Date();
var today = currentDate.getFullYear() +''+ ("0" + (currentDate.getMonth() + 1)).slice(-2)+''+("0" + currentDate.getDate()).slice(-2);
var compareDay = formatedDate - today;
if(compareDay < 14){// 14 day = 2 week
// do something for less than 2 weeks
console.log('Less than 2 weeks will be expired');
} else {
// also can do something
console.log('more than 2 weeks will be expired.');
}
Javascript Date Reference
Try comparing milliseconds of the dates.
We know that there are 1000 * 60 * 60 * 24 * 14 = 1209600000 milliseconds in two weeks, knowing this we can add 1209600000ms to the current date and compare this to the milliseconds of the due date.
let dueDate = new Date('07/26/2017');
if(Date.now() + 1209600000 > dueDate.getMilliseconds()){
//do stuff
}

TypeError: *.getMonth is not a function

I'm trying to build a javascript function that will auto-fill 14 days of a calendar with dates leading up to the last date, which is picked by a datepicker. So far my code is:
function filldates() {
datepicked = document.getElementById("period-ending").value;
s = datepicked.split('/');
enddate = new Date(s[2], s[0], s[1]);
date1 = enddate.setDate(enddate.getDate()-14);
day1 = date1.getMonth() + 1;
month1 = date1.getDate();
var firstday = day1 + '/' + month1;
document.getElementById("date-1").value = firstday;
}
However the developer's console keeps telling me that date1.getMonth is not a function. I'm confused because all of the tutorials and examples I've been looking at are based around something like: "var today = new Date(); var month = today.getMonth() + 1;"
Is this an implementation problem?
The setDate() function mutates its context date. It does not return a new Date instance.
If you want to create a new date instance that's some number of days ahead of another one:
function daysAfter(d, days) {
var nd = new Date(d.getTime());
nd.setDate(d.getDate() + days);
return nd;
}
Then if you've got a date, you can create a date 14 days after it like this:
var someDate = ... whatever ... ;
var fourteenDaysAfter = daysAfter(someDate, 14);
You can then use the .getMonth() and .getDate() accessors to do whatever formatting you want. Keep in mind that months are numbered from zero in JavaScript.
edit for dates before a date just pass a negative number.

Get next date and day

I have a table to which i dynamically add rows. The number of days is equal to the date difference of the dates inserted by user. On the dynamic rows i want to add three fields. The first two are date and day filed. For that I need to know the next date and the corresponding day. For example user enters 10-2-2012. I need to insert The next dates like 17-2-2012,18-2-2012... and corresponding days like Wednesday, Thursday..etc
I have used the following function to get next date
function getTomorrow(d,offset)
{
if (!offset)
{
offset = 1
}
return new Date(new Date().setDate(d.getDate() + offset));
}
But it shows error 16-2-2012 has no getDate() function. Am not able to find next date and the corresponding day. Is there any way to get it?
You have to convert the string d into a Date object:
function getTomorrow(d,offset){
if (!offset){
offset = 1;
}
if(typeof(d) === "string"){
var t = d.split("-"); /* splits dd-mm-year */
d = new Date(t[2],t[1] - 1, t[0]);
// d = new Date(t[2],t[1] - 1, t[0] + 2000); /* for dd-mm-yy */
}
return new Date(d.setDate(d.getDate() + offset));
}
document.write(getTomorrow('16-02-2012',20) + ' test');
var k = getTomorrow('16-02-2012',1);
var myTime = k.getDate()+'-'+(k.getMonth()+1)+'-'+k.getFullYear();
alert(myTime);
JSFiddle Demo. See also http://www.w3schools.com/jsref/jsref_obj_date.asp.
var d=new Date();
d.setTime((d.getTime() + 86400 * 1000*1));
document.write(d);
document.write(d.getDay()+"-"+parseInt(d.getMonth()+1)+"-"+d.getFullYear());
if you need to know the date of day after tommorow , just change 1000*1 to 1000*2.
i giving a example
var year = 2010, month = 9, day = 14;
// The value of `meses`
var offset = 1; // Tomorow
var future_date = new Date(year, month , day+offset);
console.log(future_date);

Show week number with Javascript?

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.
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>
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());
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)
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/
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() {
var 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.
var 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() {
var 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.
var 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);
}
If you already use Angular, then you could profit $filter('date').
For example:
var myDate = new Date();
var myWeek = $filter('date')(myDate, 'ww');
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.
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;
};
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.
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)
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 :)
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>
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());
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);
}
};
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.

Categories

Resources