Get days from specific isoWeek in dayjs - javascript

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>

Related

How to get last month day 15 and current month day 16 in moment

I am trying to get last month of day 15 and current month of day 16 in moment but I am failed could someone please help me how to resolve this issue.
Expected result => 15 oct, 15 Nov 2020
To get last month with date 15 you need this:
moment().subtract(1, 'month').date(15);
You subtract one month and set date to 15. This returns 15 october.
To get current date 15, just remove the subtract part.
To get exactly the result you asked for then:
const currentMonthDate15 = moment().date(15);
const lastMonthDate15 = moment().date(15).subtract(1, 'month');
const string = lastMonthDate15.format('DD MMM') + ', ' + currentMonthDate15.format('DD MMM YYYY');
Where string is 15 Oct, 15 Nov 2020

Problem while modifying a date (modification is wrong)

I'm trying to make a calendar in Angular. For this I have implement a drag & drop functionnality to be able to move one appointment from a day to another one.
But I have something strange, when I try to move an appointment it seems working, but when I try to move it from the 1st april to the 31 march then the date is modified to the 1st march.
When I drop my appointment I emit a change with my appointment data and the new day:
drop(evt) {
let schedule: Schedule;
schedule = evt.data.schedule;
// Emit change
this.scheduleChange.emit({schedule, day: this.day});
}
Then I edit my appointment:
scheduleChanged(evt) {
const schedule = this.createScheduleFromObject(evt.schedule);
const day = evt.day;
console.log(day);
if (this.isSameDate(schedule.start, schedule.end)) {
schedule.start.setDate(day.getDate());
schedule.start.setMonth(day.getMonth())
schedule.start.setFullYear(day.getFullYear());
schedule.end.setDate(day.getDate());
schedule.end.setMonth(day.getMonth());
schedule.end.setFullYear(day.getFullYear());
console.log(schedule);
}
}
I think the problem is when I transform my object to a Schedule class:
createScheduleFromObject(obj: any) {
const schedule: Schedule = Object.assign(new Schedule(null, '', '', '', new Date(), new Date()), obj);
console.log(obj.start);
schedule.start = new Date(obj.start);
schedule.end = new Date(obj.end);
console.log(schedule.start);
return schedule;
}
This function return the good date here is the output of the console log:
2020-04-01T21:31:49.640Z
Wed Apr 01 2020 23:31:49 GMT+0200
But when I modify it in the scheduleChanged function even if the day is the 31st march as I have in the console log:
Tue Mar 31 2020 00:00:00 GMT+0200
The start date of my schedule is set to :
Sun Mar 01 2020 23:33:19 GMT+0100
Why ?
I suspect this is a duplicate of Javascript setMonth shows improper date. What is likely happening in your case is that moving a date for April to 31 March, you are setting the day in April to a non–existent date, so it rolls over to the next month.
When setting the values of a date one at a time, you may have issues where the date of the starting Date doesn't exist in the month being set. So when setting the values of a date to new values, do it all in one go, so instead of:
schedule.start.setDate(day.getDate());
schedule.start.setMonth(day.getMonth())
schedule.start.setFullYear(day.getFullYear());
do:
schedule.start.setFullYear(day.getFullYear(), day.getMonth(), day.getDate());
So in your case, moving a date from 1 April to 31 March:
The April date is set to 31, which doesn't exist so rolls over to 1 May
The month is set to March
Year is set to whatever
So you end up with a Date for 1 March. Setting the values in one go fixes that so:
(2020-04-01).setFullYear(2020, 2, 31) -> 2020-03-31
When setting the year, you can also set the month and day, when setting month you can set the month and day. Similarly for time, setting hours can set hours, minutes, seconds and milliseconds. Setting minutes can set minutes, seconds and milliseconds, etc.

get week number from date in whole week base in 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()

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),

MomentJS returns obscure date for 1st of month

I'm having a small problem with MomentJS returning a nonsense date. I am attempting to set the date to the first of a given month and year. I have tried the following:-
var _year = 2015;
var _month = 10;
var _dateString = _year.toString() + '-' + _month.toString() + '-1';
var _date = moment(_dateString, 'YYYY-MM-D');
console.log('_date', _date.format('dddd, do MMMM YYYY'));
This gives Thursday, 4th October 2015 as the _date. Which doesn't exist. I tried using .set() and .date(), both give the same result:-
var _date = moment(_dateString, 'YYYY-MM-D').set('date', 1);
> Thursday, 4th October 2015
var _date = moment(_dateString, 'YYYY-MM-D').date(1);
> Thursday, 4th October 2015
So, I can't see what I'm doing wrong now, can anyone offer any suggestions or help?
Many thanks.
Your code is correct except you should use capital D not small d in do:
console.log('_date', _date.format('dddd, Do MMMM YYYY'));
Difference between Do and do is:
do is the index of the day in the week, for example if you check the calender you will find 1st October is Thursday which is the 4th day of the week as the index start from 0 and if you changed to 2 October which is Friday it will give you 5th and same for 3 Oct => 6th and then the new week start from Sunday then 4 Oct => 0th and start over again.
Do is the index of the day in the month and that what you expected the result to be, 1th Oct is 1th, 2nd Oct => 2nd and so on.
Check the docs here for more info

Categories

Resources