get week number from date in whole week base in javascript - javascript

I have searched the web and found the script to get the week number in year. However my counting is difference. The below image is the week number I want to get. When I tested using '1/5/2015', my code got week number is 2, but the week number should be 1 in my requirement. Would someone can help me. Thanks in advance.
I found the javascript at IamSilviu/Get week number
There is my code:
function myWeekNumber(thisDate) {
var dt = new Date(thisDate)
var onejan=new Date(dt.getFullYear(), 0, 2);
return Math.ceil((((dt - onejan) / 86400000) + onejan.getDay() + 1) / 7); }

The algorithm you're trying to implement seems to be that:
Weeks start on Sunday
The first week of the year is the one that has any days in the year, e.g. 1 Jan 2016 was a Friday, so the first week of 2016 started on Sunday 27 December 2015
In this case, it's best to use UTC methods to avoid daylight saving issues:
function getWeekNumberNonISO(d) {
// Create UTC equivalent for 23:59:59.999 on the passed in date
var sat = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(),23,59,59,999));
// Set to Saturday at end of week
sat.setUTCDate(sat.getUTCDate() + 6 - sat.getUTCDay());
// Get first day of year
var firstDay = new Date(Date.UTC(sat.getUTCFullYear(), 0, 1));
// Set to Sunday on or before, i.e. first day of first week in year
firstDay = firstDay.setUTCDate(firstDay.getUTCDate() - firstDay.getUTCDay());
// Week number is difference in dates divided by ms/week rounded
return Math.round((sat - firstDay)/(6.048e8));
}
// Get week number for Mon 5 Jan 2015
console.log(getWeekNumberNonISO(new Date(2015,0,5))); // 2
// Get week number for Sat 31 Dec 2011
console.log(getWeekNumberNonISO(new Date(2011,11,31))); //53
// Get week number for Sat 1 Jan 2011
console.log(getWeekNumberNonISO(new Date(2011,0,1))); // 1
// Get week number for Sun 2 Jan 2011
console.log(getWeekNumberNonISO(new Date(2011,0,2))); // 2

Js has function inbulid function which can be used to fetch the date from the given date of the week getweek().
var week=date.getWeek()

Related

Get days from specific isoWeek in dayjs

In order to create a weekly calendar that shows me the days of a given week, I am looking for a solution that will do this. The output should show me the days from given data, starting from Monday to Sunday. To achieve this I'm using dayjs in nuxt. I wrote a method and thought I was done so far. However, this is not the case after I have tested out different years.
As seen here ISO week date, I thought I would be well served with .isoWeek().
An ISO week-numbering year (also called ISO year informally) has 52 or 53 full weeks. That is 364 or 371 days instead of the usual 365 or 366 days. These 53 week years occur on all years that have Thursday as the 1st of January and on leap years that start on Wednesday the 1st. The extra week is sometimes referred to as a leap week, although ISO 8601 does not use this term.
Let's see what I did and where the problem is
const year = 2022
const calendarWeek = 1 //1 to 53
const dayjs = this.$dayjs
const isoWeek = require('dayjs/plugin/isoWeek')
dayjs.extend(isoWeek)
const week = dayjs().year(year).isoWeek(calendarWeek)
const startOfWeek = dayjs(week).day(1)
const weekdays = new Array(7).fill(startOfWeek).map(
(day, idx) => day.add(idx, 'day').format('dddd, DD MMM YYYY'))
This will output me the expected result with the dates between Monday, 03 Jan 2022 and Sunday, 09 Jan 2022. Great, that's exactly how it should be.
The discovered problem: If I insert the first calendar week of 2023, I get the following output:
const year = 2023
const calendarWeek = 1
Output: Dates between Monday, 09 Jan 2023 and Sunday, 15 Jan 2023
It should be 02. Jan - 08. Jan. This is the result I would get if I specified 0 as calendarWeek. Why does 1 work for 2022 and not for 2023? Thus the correct functionality of my calendar is no longer possible.
In short, you want to get the first week which includes the first monday of the year...
But what you actually get is the second week of the year (isoWeek is zero-based).
The first week of the year is the one that contains at least one date of that year (January 1st).
For 2022, that monday is December 27th, 2021.
In this case, just compare the year and add 7 days if necessary.
I have made it a function with just the year and week as argument:
function getWeekOfYear(year, week) {
// The first monday of the first week includes at least one day of the year
let firstMondayOfYear = dayjs().year(year).isoWeek(week).day(1);
console.log("Monday 1:", firstMondayOfYear.format("dddd, DD MMM YYYY"));
// Now make sure it really is the first monday of the year
if (firstMondayOfYear.year() !== year) {
firstMondayOfYear = firstMondayOfYear.add(7, "days");
}
console.log("Monday 2:", firstMondayOfYear.format("dddd, DD MMM YYYY"));
// return the week for that "real" first monday of the year
return new Array(7)
.fill(firstMondayOfYear)
.map((day, idx) => day.add(idx, "day").format("dddd, DD MMM YYYY"));
}
console.log("result for 2022 - week 0", getWeekOfYear(2022, 0))
console.log("result for 2023 - week 0", getWeekOfYear(2023, 0))
console.log("result for 2022 - week 52", getWeekOfYear(2022, 52))
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.6/dayjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.6/plugin/isoWeek.min.js"></script>
<script>
dayjs.extend(window.dayjs_plugin_isoWeek)
</script>

How to use moment to find first monday 18 month ago

I am writing some javascript and came across moment library.I would like to use the moment to get the first Monday of 18 Month ago. How would I do it?
I know 18 months ago it is
moment().subtract(18, 'months');
But how would I know the first Monday of that time.
Thanks ahead of time!
You can do this in one line.
moment().subtract(18,'months').startOf('month').add(6 - moment().day("Monday").day() ,'days').startOf('week').day(1);
Find the moment 18 months ago, get the start date of that month, add 6 days since in worst case the first of that month is a tuesday(results in a date which is in the week that includes the first monday) and then get the start of that week.
Voila, all in one line.
1st edit: corrected the calculation to be locale independent and always return a Monday and not beginning of week since that is locale dependent.
2nd edit: locales makes it a bit more complicated. Adding 6 days to a Monday with a locale where the week ends on Saturday will move into another week thus we need to adapt the algorithm to take the Monday week number into consideration, i.e. subtract moment().day("Monday").day() which gives the locale dependent week day number of a Monday(0 or 1). Changed in the code above.
cleaner and more reusable IMHO ;)
var monday = moment().day('Monday').weekday();
var searchFirstMonday = moment().subtract(18, 'months').startOf('month');
while (searchFirstMonday.weekday() !== monday){
searchFirstMonday.add(1, 'day');
}
If you go back 18 months, get the first day of that month, then the Monday of that week, you'll get close:
moment().subtract(18, 'months').startOf('month').day(1)
To make sure the Monday is in the right month, you need to break that down a bit:
var month = moment().subtract(18, 'months');
var firstMonday = month.startOf('month').day(1);
if (firstMonday.month() != month.month()) {
firstMonday = firstMonday.add(7, 'days');
}
If anyone wants to do the same without any libraries.
Not sure if this is the best way to do it :P
var now = new Date();
//Get year and month
var month = now.getMonth();
var year = now.getFullYear();
//Months to go back
var monthsIntoPast = 18;
//Day of week we're looking for
var firstWeekDay= 2;
//Loop for one week
for(var x = 0; x < 7; x++) {
//Go back 18 months to first day + x of the month
var past = new Date(year, month - monthsIntoPast, 2 + x);
//First monday
if(past.getDay() == firstWeekDay) {
//First monday 18 months ago
alert(past.toUTCString())
break;
}
}
You use the following code to get what you need:
// Subtract 18 months from the current date, then get the first day of the month
var date = moment().subtract(18, 'months').startOf('month');
// Get current month
var month = date.month();
// Get monday of the first week of the month
var firstMonday = moment(date).weekday(0);
// Check if the first day of the month is not Monday
// and first monday of first week is in the desired month
if( date.weekday() != 0 && firstMonday.month() != month ){
// Add 1 week if needed
firstMonday.add(1, 'weeks');
}
The example above consideres Monday as the first day of the week. If Monday is not the first day of the week (day with index 0), you can get the correct index using moment.weekdays()
var moment = require('moment');
date = moment().subtract(18, 'months').startOf('month');
First we get the the current date and subtract 18 months. Then we find the start of the month, which as of today is
_d: Tue Jul 01 2014 00:00:00 GMT-0800 (AKDT),
So now we need to adjust for the next Monday. We get the current day of the week with date.day() which will give us a number between 0-7 with 0 being last Sunday and 7 being next Sunday. In this case, the first is on a Tuesday.
>date.day();
2
So we take the offset of the day of the week and subtract it from 8. Why 8 you say? Because if you count every number including 0 and 7 there are 8 numbers. (Think arrays)
//since it's not monday we add the offset
date = date.add(8-date.day(), 'days');
In your code you'd want to check if the First day returned actually IS a Monday so as to not get the second Monday of the month. So the whole thing might look like
date = moment().subtract(18, 'months').startOf('month');
if(date.day() > 1){ //check if it's Monday
//since it's not monday we add the offset
date = date.add(8-date.day(), 'days');
}
returns
_d: Mon Jul 07 2014 00:00:00 GMT-0800 (AKDT),

moment.js thinks that 2013-12-31 is week 1, not week 53

The moment.js library is awesome, and I use it almost all the time, but I recently ran into something interesting. I'm trying to plot data by week of the year, and one of the data points was 2013-12-31, moment.js tells me this is week 1? Is there a better way to handle this? either with 53, null, -1, or something?
moment('2013-12-31').week()
(returns) 1
I thought maybe using isoWeek or format would get around this, but they all return the same value of 1, despite the documentation saying it goes to 53.
moment('2013-12-31').isoWeek()
(returns) 1
+moment('2013-12-31').format('w')
(returns) 1
Anyone have any ideas on this? (short of making a test whether the week computed has a min/max date that covers the date value I passed it)
It is because the week from the 30th december 2013 is considered to be the 1st week of 2014 as you may see on this page epoch converter
And according to momentjs documentation:
The week with January 1st in it is the first week of the year.
I had a problem at my work where we used .format('YYYY WW') for some comparison logic.
That doesn't really make sense, as you should probably use .format('gggg WW') in such cases.
moment('2013-12-31').format('YYYY w'); // Returns 2013 1
moment('2013-12-31').format('gggg w'); // Returns 2014 1
https://momentjs.com/docs/#/displaying/format/
This is expected behavior. According to the ISO 8601 standard, 2013 is not a year with 53 weeks.
The long years, with 53 weeks in them, can be described by any of the following equivalent definitions:
any year starting on Thursday (dominical letter D or DC) and any leap year starting on Wednesday (ED)
any year ending on Thursday (D, ED) and any leap year ending on Friday (DC)
years in which 1 January and 31 December (in common years) or either (in leap years) are Thursdays
(source)
2013 started and ended on a Tuesday so therefore it is not a "long year" and 2013-12-31 is considered part of the first week of 2014.
If you want that week to be the 53rd, you'll have to write custom code for it as the ISO standard won't agree with you!
Moment.js docs aren't that straightforward with this I had to move from WW-YYYY to WW-GGGG
moment(2019-12-30T00:20:53.380Z).format(WW-YYYY) // Gave me 01-2019 incorrectly
moment(2019-12-30T00:20:53.380Z).format(WW-GGGG) // Gave me 01-2020 correctly
Findings
If your doing locale weeks, use ww & gggg
If your doing ISO weeks, use WW & GGGG
A mix of w/W & Y is incorrect usage
I had the same problem with the calculation of the week number, starting from the date of Sunday.
Finally I was able to solve the problem by calculating the week number starting not from Sunday but from Monday.
moment(date).isoWeekday(1).week()
Better right a custom method which will convert date into week and that can be customized easily.
//value : (MMM DD YYYY format)
function getEpiWeek(value) {
Date.prototype.getWeek = function () {
var target = new Date(this.valueOf());
// ISO week date weeks start on monday, so correct the day number
var dayNr = (this.getDay() + 7) % 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() < 4) {
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);
}
};
var weekNumber = new Date(value).getWeek()
var year = getYear(value, weekNumber);
return weekNumber + ' ' + year;
}
function getYear(value, weekNumber) {
var year = parseInt(value.split(' ')[2]);
if (value.split(' ')[0] == 'Jan') {
if (weekNumber > 40) {
year = year - 1;
}
}
if (value.split(' ')[0] == 'Dec') {
if (weekNumber < 2) {
year = year + 1;
}
}
return year.toString();
}
Personally solved my ordering issue using :
if(d.month()==0) {
week = d.week();
}else{
week=d.isoWeek();
}

JavaScript Dateobject Increment goes wrong

I want to increment the year-value of a given date, but this goes wrong.
this is my code:
var endDate = entry.start;
endDate.setDate(endDate.getFullYear() + 5);
and for comparison the output (console.log) is:
Date {Thu Jun 30 2011 11:30:10 GMT+0200}
Date {Tue Dec 06 2016 11:30:10 GMT+0100}
as you can see, it also incremented the month and Day.
What am I missing?
thanks in advance
You have to set the year only, using the setYear method:
endDate.setYear(endDate.getFullYear() + 5);
Using setDate(getFullYear()+5) you add 5 + (year of the date) days to the date value of endDate
You're adding 2016 days to it, not modifying the year, which is 5 and a half year.

Problem in adding days / month / year to a given date using javascript?

I trying to add days / months / year to a given date and map it to an input field
var d = new Date();
d.setDate(15);
d.setMonth(06);
d.setYear(2011);
document.getElementById("test").innerHTML=d;
d.setDate(d.getDate()+20);
document.getElementById("test").innerHTML+=""+d.getDate()+"/"+d.getMonth()+"/"+d.getYear("YY");
this actually prints out
Fri Jul 15 2011 12:45:48 GMT+0530 (India Standard Time)
4/7/111
actually this is wrong.. it should print out 5/7/2011.. i think by default the system takes as "30" days for a month and adds the +20 days.. but actually Jun has 30 days so that result should be 5/7/2011..
any suggestion about what goes wrong in here.. any alternative for this?
At the first, you have better to use getFullYear to get year as 2011. You did get number from getDate() and add 20. This break Date. You should get long value from getTime(), and add milli-seconds.
<div id="test"></div>
<script>
var d = new Date();
d.setDate(15);
d.setMonth(06);
d.setFullYear(2011);
document.getElementById("test").innerHTML+=" "+d.getDate()+"/"+d.getMonth()+"/"+d.getFullYear();
d.setTime(d.getTime()+1000*60*60*24*20);
document.getElementById("test").innerHTML+=" "+d.getDate()+"/"+d.getMonth()+"/"+d.getFullYear();
</script>
> var d = new Date();
> d.setDate(15);
> d.setMonth(06);
> d.setYear(2011);
is equivalent to:
var d = new Date(2011,6,15); // 15 Jul 2011
Months are zero based (January = 0, December = 11).
Date.prototype.getYear is specified in ECMA-262 ed5 as Return YearFromTime(LocalTime(t)) − 1900. so:
alert(d.getYear()); // 111
whereas:
alert(d.getFullYear()); // 2011
i think by default the system takes as "30" days for a month and adds the +20 days.. but actually May has 31 days so that result should be 5/7/2011.
You are interpreting it a wrong way, Month in a date starts with 0 - Jan..
So as per the date entered by you it comes Jul 15 2011 on the month number 6.
When you add 20 to date it will be Aug 04 2011 and you are directly getting month number which is 7 - i.e. Aug which misleads your calculation. And for the year, yes it is you should getFullYear
Read this to get your basics correct..

Categories

Resources