Moment.js how to get week of month? (google calendar style) - javascript

I am using Moment.js and it is great. The problem I have now is that I can't figure out how to get the week of the month a certain date is. I can only find "week of year" in the Moment js docs. For example, if I choose today's date (2/12/2014), I would like to know that this date is in the second week of this month of february and consequently, it is the second wednesday of the month. Any ideas?
EDIT:
I guess some clarification is necessary. What I need most is the nth number of a certain day in a month. For example, (from the comments) Feb 1, 2014 would be the first Saturday of the month. Feb 3, 2014 would be the first Monday of the month even though it is "technically" the second week of the month. Basically, exactly how google calendar's repeat function classifies days.

It seems that moment.js does not have the method that implements the functionality that you are looking for.
However, you can find the nth number of a certain day of the week in a month is using the Math.ceil of the date / 7
For example:
var firstFeb2014 = moment("2014-02-01"); //saturday
var day = firstFeb2014.day(); //6 = saturday
var nthOfMoth = Math.ceil(firstFeb2014.date() / 7); //1
var eightFeb2014 = moment("2014-02-08"); //saturday, the next one
console.log( Math.ceil(eightFeb2014.date() / 7) ); //prints 2, as expected
It looks like this is the number you are looking for, as demonstrated by the following test
function test(mJsDate){
var str = mJsDate.toLocaleString().substring(0, 3) +
" number " + Math.ceil(mJsDate.date() / 7) +
" of the month";
return str;
}
for(var i = 1; i <= 31; i++) {
var dayStr = "2014-01-"+ i;
console.log(dayStr + " " + test(moment(dayStr)) );
}
//examples from the console:
//2014-01-8 Wed number 2 of the month
//2014-01-13 Mon number 2 of the month
//2014-01-20 Mon number 3 of the month
//2014-01-27 Mon number 4 of the month
//2014-01-29 Wed number 5 of the month

When calculating the week of the month based on a given date, you have to take the offset into account. Not all months start on the first day of the week.
If you want to take this offset into account, you can use something something like the following if you are using moment.
function weekOfMonth (input = moment()) {
const firstDayOfMonth = input.clone().startOf('month');
const firstDayOfWeek = firstDayOfMonth.clone().startOf('week');
const offset = firstDayOfMonth.diff(firstDayOfWeek, 'days');
return Math.ceil((input.date() + offset) / 7);
}

Simple using moment.js
function week_of_month(date) {
prefixes = [1,2,3,4,5];
return prefixes[0 | moment(date).date() / 7]
}

This library adds the function moment.weekMonth()
https://github.com/c-trimm/moment-recur

I made some modifications based on feedback.
let weeks = moment().weeks() - moment().startOf('month').weeks() + 1;
weeks = (weeks + 52) % 52;
On days passing through the next year, the week value will be negative so I had to add 52.

What about something like:
weekOfCurrentMonth = (moment().week() - (moment().month()*4));
This takes the current week of the year, and subtracts it by the 4 times the number of previous months. Which should give you the week of the current month

I think the answer to this question will be helpful, even though it doesn't use moment.js as requested:
Get week of the month

function countWeekdayOccurrencesInMonth(date) {
var m = moment(date),
weekDay = m.day(),
yearDay = m.dayOfYear(),
count = 0;
m.startOf('month');
while (m.dayOfYear() <= yearDay) {
if (m.day() == weekDay) {
count++;
}
m.add('days', 1);
}
return count;
}

There is a problem with #Daniel Earwicker answer.
I was using his function in my application and the while loop was infinite because of the following situation:
I was trying to figure out which week of december (2016) was the day 31.
the first day of december was day 336 of the year. The last day of december was day 366 of the year.
Problem here: When it was day 366 (31 of december, last day of the year) the code added another day to this date. But with another day added it would be day 1 of january of 2017. Therefore the loop never ended.
while (m.dayOfYear() <= yearDay) {
if (m.day() == weekDay) {
count++;
}
m.add('days', 1);
}
I added the following lines to the code so the problem would be fixed:
function countWeekdayOccurrencesInMonth(date) {
var m = moment(date),
weekDay = m.day(),
yearDay = m.dayOfYear(),
year = m.year(),
count = 0;
m.startOf('month');
while (m.dayOfYear() <= yearDay && m.year() == year) {
if (m.day() == weekDay) {
count++;
}
m.add('days', 1);
}
return count;
}
It verifies if it is still in the same year of the date being veryfied

Here's Robin Malfait's solution implemented with the lightweight library date-fns
import {
differenceInDays,
startOfMonth,
startOfWeek,
getDate
} from 'date-fns'
const weekOfMonth = function (date) {
const firstDayOfMonth = startOfMonth(date)
const firstDayOfWeek = startOfWeek(firstDayOfMonth)
const offset = differenceInDays(firstDayOfMonth, firstDayOfWeek)
return Math.ceil((getDate(date) + offset) / 7)
}
export default weekOfMonth

I'd do the following:
let todaysDate = moment(moment.now());
let endOfLastMonth = moment(get(this, 'todaysDate')).startOf('month').subtract(1, 'week');
let weekOfMonth = todaysDate.diff(endOfLastMonth, 'weeks');
That gets todaysDate and the endOfLastMonth and then uses Moment's built-in diff() method to compute the current month's week number.

It's not built-in, but basically you can subtract the week number of the start of the month from the week number of the date in question.
function weekOfMonth(m) {
return m.week() - moment(m).startOf('month').week() + 1;
}
Credit goes to code by original author, give him a star if it helped you.

How about this?
const moment = require("moment");
// Generate Week Number of The Month From Moment Date
function getWeekOfMonth(input = moment()) {
let dayOfInput = input.clone().day(); // Saunday is 0 and Saturday is 6
let diffToNextWeek = 7 - dayOfInput;
let nextWeekStartDate = input.date() + diffToNextWeek;
return Math.ceil((nextWeekStartDate) / 7);
}

Simple code, but has been working for me.
const weekOfTheMonth = (myMomentDate) => {
const startDay = moment(myMomentDate).startOf('week');
const day = parseInt(startDay.format('DD'),10);
if(day > 28){
return 5;
}
if((day > 21) && (day <= 28) ){
return 4;
}
if((day > 14) && (day <= 21) ){
return 3;
}
if((day > 7) && (day <= 14) ){
return 2;
}
return 1;
}

Related

Subtracting 3 days from date

I want to calculate a reminderDate by subtracting 3 days from it. However, if the resulting date
falls on a Saturday or Sunday, it should give the date of the Friday
falls on a Friday, it should give the date of Thursday
For example
Exchange Date ReminderDate
18.06.2020 -3 days = 15.06.2020 --> OK, because Monday
17.06.2020 -3 days = 14.06.2020 --> Sunday, must be changed to 12.06.2020
16.06.2020 -3 days = 13.06.2020 --> Saturday, must be changed to 12.06.2020
15.06.2020 -3 days = 11.06.2020 --> Friday, must be changed to 11.06.2020
I tried something like this, but neither .getDay() nor .day() seem to work. And dt seems to give the date of today, and not the date of exchange.
var exchange = NWF$("#" + varAustauschtermin).val(); // date like 18.06.2020
console.log("Exchange: " + exchange);
var reminderDate = moment(exchange, "DD.MM.YYYY").format("DD.MM.YYYY");
var dt = new Date(reminderDate);
// var reminderDate = moment(exchange, "DD.MM.YYYY").subtract(3, 'days').format("DD.MM.YYYY");
// console.log("reminderDate.day(): " + reminderDate.day());
// console.log("reminderDate.getDay(): " + reminderDate.getDay());
if(dt.getDay() == 6) { // Saturday
console.log("Saturday");
reminderDate = moment(exchange, "DD.MM.YYYY").subtract(1, 'days').format("DD.MM.YYYY");
} else if (dt.getDay() == 0) { // Sunday
console.log("Sunday");
reminderDate = moment(exchange, "DD.MM.YYYY").subtract(2, 'days').format("DD.MM.YYYY");
} else if (dt.getDay() == 5) { // Friday
console.log("Friday");
reminderDate = moment(exchange, "DD.MM.YYYY").subtract(1, 'days').format("DD.MM.YYYY");
} else {
console.log("Weekday");
reminderDate = moment(exchange, "DD.MM.YYYY").subtract(3, 'days').format("DD.MM.YYYY");
}
console.log("Reminder Date: " + reminderDate);
Any help is appreciated!
If you are using momentjs then there is no need to switch to native Date object because everything you can do with momentjs and with much simplicity
Use momentjs day() to help you get the oridinal for a day of week
0 - Sunday
1 - Monday
...
..
.
6 - Saturday
To find what date will say "Saturday" come in this week you can do like moment().day("Saturday").
Then there is subtract which you are already using to rewind dates by given days.
Building on these above ideas you can try this helper function
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.0/moment.min.js"></script>
<script type="text/javascript">
function dateShift(d) {
//days numbering are 0(Sunday) to 6(Saturday)
d.subtract(3, 'days')
//Is SUNDAY?
if (d.day() == 0) {
//adjust it to friday
var upComingFri = d.day('Friday'); // date of friday in which THIS sunday is
return upComingFri.subtract(7, 'days');
//but we want to rewind as you want to stay in same week as the original date provided
}
//Is SATURDAY?
if (d.day() == 6) {
//adjust it to friday
var friday = d.day('Friday'); //sat is in same week
return friday;
}
//Is FRIDAY?
if (d.day() == 5) {
//adjust it to thursday
var thursday = d.day('Thursday');
return thursday;
}
return d;
}
t1 = moment('18.06.2020', "DD.MM.YYYY");
r1 = dateShift(t1);
console.log(r1.format("DD.MM.YYYY"))
t2 = moment('17.06.2020', "DD.MM.YYYY");
r2 = dateShift(t2);
console.log(r2.format("DD.MM.YYYY"))
t3 = moment('16.06.2020', "DD.MM.YYYY");
r3 = dateShift(t3);
console.log(r3.format("DD.MM.YYYY"))
t4 = moment('15.06.2020', "DD.MM.YYYY");
r4 = dateShift(t4);
console.log(r4.format("DD.MM.YYYY"))
</script>
It's not too hard to do this with plain javascript. Instead of subtracting 3 days, seeing what the day is, then subtracting again, you can work out the days to subtract given the initial day and do one subtraction, e.g.
// Parse string in format d.m.y to Date
function parseDMY(s) {
let [d, m, y] = s.split(/\D/);
return new Date(y, --m, d);
}
// s is date in format d.m.y
function adjustDate(s) {
let d = parseDMY(s);
// Subtract 4 days from Mon and Tue, 5 from Wed, 3 otherwise
d.setDate(d.getDate() - ([,4,4,5][d.getDay()] || 3));
return d;
}
['29.03.2020','28.03.2020','27.03.2020','26.03.2020',
'01.04.2020','31.03.2020','30.03.2020'
].forEach(s => console.log(parseDMY(s).toDateString() + ' -> ' +
adjustDate(s).toDateString()));

Get all days of the week given a day

I'm trying to make a function to get all the days of the week given the current day. I had a function that i thought was working until i noticed that if the day of the week is near the end of the month, like for example February, i get weird data. Anyone know whats going on and how to fix it?
function days(current) {
var week = new Array();
// Starting Monday not Sunday
var first = ((current.getDate() - current.getDay()) + 1);
for (var i = 0; i < 7; i++) {
week.push(
new Date(current.setDate(first++))
);
}
return week;
}
var input = new Date(2017, 1, 27);
console.log('input: %s', input);
var result = days(input);
console.log(result.map(d => d.toString()));
.as-console-wrapper{min-height:100%}
If you don't want to use some kind of other library like Moment.js you can also change your function a little and then it will work. Try this:
function dates(current) {
var week= new Array();
// Starting Monday not Sunday
current.setDate((current.getDate() - current.getDay() +1));
for (var i = 0; i < 7; i++) {
week.push(
new Date(current)
);
current.setDate(current.getDate() +1);
}
return week;
}
console.log(dates(new Date(2017, 1, 27)));
You can use Moment.js library - utility library for dates/time operations
Here's examplary code to get current week's dates starting from monday:
function getThisWeekDates() {
var weekDates= [];
for (var i = 1; i <= 7; i++) {
weekDates.push(moment().day(i));
}
return weekDates;
}
var thisWeekDates = getThisWeekDates();
thisWeekDates.forEach(function(date){ console.log(date.format());});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.js"></script>
The code above prints following results to the console:
2017-03-20T21:26:27+01:00
2017-03-21T21:26:27+01:00
2017-03-22T21:26:27+01:00
2017-03-23T21:26:27+01:00
2017-03-24T21:26:27+01:00
2017-03-25T21:26:27+01:00
2017-03-26T21:26:27+02:00
I will trace your code using your example of Feb 27, 2017:
first = 27 - 1 + 1 = 27
loop:
Feb.setDate(27) = 27 feb
Feb.setDate(28) = 28 feb
Feb.setDate(29) = Not 29 days in Feb. So it sets current to 29-28 = 1st day of March
March.setDate(30) = March 30
March.setDate(31) = March 31
March.setDate(32) = Not 32 days in March. So it sets current to 31-32 = 1st of April..
April.setDate(33) = Not 33 days in April. So it sets current day 33-30 = 3rd day of May.
Please note that I used the shorthand of Month.setDate() to show the month of the current Date object when it was being called.
So the issue is with your understanding of setDate that is being used on current. It changes the month and if the value you use isn't a day in the month it adjusts the month and day appropriately. I hope this cleared things up for you.
For how to add one to a date, see Add +1 to current date. Adapted to your code, you can set current to the first day of the week then just keep adding 1 day and pushing copies to the array:
function days(current) {
var week = [];
// Starting Monday not Sunday
var first = current.getDate() - current.getDay() + 1;
current.setDate(first);
for (var i = 0; i < 7; i++) {
week.push(new Date(+current));
current.setDate(current.getDate()+1);
}
return week;
}
var input = new Date(2017, 1, 27);
console.log('input: %s', input);
var result = days(input);
console.log(result.map(d => d.toString()));
Note that this changes the date passed in (per the original code), you may want to make current a copy to avoid that.
Suppose monday starts the week, you can calculate monday and go to sunday. getDategives you the day of the week, and Sunday starts at 0. With momnday, we get just offset forward to 6 days to get sunday
mondayThisWeek(date: Date): Date {
const d = new Date(date)
const day = d.getDay()
const diff = d.getDate() - day + (day === 0 ? -6 : 1)
return new Date(d.setDate(diff))
}
const offsetDate = (base: Date, count: number): Date => {
const date = new Date(base)
date.setDate(base.getDate() + count)
return date
}
thisWeek(today: Date): TimeRange {
const monday = mondayThisWeek(today)
return {
startDate: monday,
endDate: offsetDate(monday, 6)
}
}
This can be achieved easly using moment
const getWeekDates = () => {
let weekDates = [];
for (let i = 0; i < 7; i++)
weekDates.push(moment().add(i, 'd'));
return weekDates;
};
console.log(getWeekDates());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.js"></script>

How to check if date is in this week in javascript?

I have this date "2016-04-23T11:45:00Z" and I want to check this date in this week or not ?
Thanks,
Dates are hard, I would always suggest using a library dedicated to date handling as it reduces the chances of errors in your code.
MomentJS is a good one.
var now = moment();
var input = moment("2016-04-17T11:45:00Z");
var isThisWeek = (now.isoWeek() == input.isoWeek())
Edit: Please note as of 2020 moment may not be a good choice for new projects
This seems to be working for me.
function isDateInThisWeek(date) {
const todayObj = new Date();
const todayDate = todayObj.getDate();
const todayDay = todayObj.getDay();
// get first date of week
const firstDayOfWeek = new Date(todayObj.setDate(todayDate - todayDay));
// get last date of week
const lastDayOfWeek = new Date(firstDayOfWeek);
lastDayOfWeek.setDate(lastDayOfWeek.getDate() + 6);
// if date is equal or within the first and last dates of the week
return date >= firstDayOfWeek && date <= lastDayOfWeek;
}
const date = new Date();
const isInWeek = isDateInThisWeek(date);
<div ng-app="myApp">
<div class="container" ng-controller="Ctrl_List">
<h1>{{currentDate}}</h1>
<h1>{{numberCurrentDateWeeks}}</h1>
<h1>{{yourDate}}</h1>
<h1>{{numberYourDateWeeks}}</h1>
</div>
</div>
......
angular.module('myApp', [])
.controller("Ctrl_List", ["$scope", "$filter", function(s, $filter) {
s.yourDate = '2016-04-23T11:45:00Z'
s.currentDate = new Date();
s.numberCurrentDateWeeks = $filter('date')(s.currentDate, "w");
s.numberYourDateWeeks = $filter('date')(s.yourDate, "w");
}]);
then you got the Week numbers just compare or do whatever you like
cheers !
You can do that without any libraries by checking if the date.getTime() (milliseconds since epoch) is between last monday and next monday:
const WEEK_LENGTH = 604800000;
function onCurrentWeek(date) {
var lastMonday = new Date(); // Creating new date object for today
lastMonday.setDate(lastMonday.getDate() - (lastMonday.getDay()-1)); // Setting date to last monday
lastMonday.setHours(0,0,0,0); // Setting Hour to 00:00:00:00
const res = lastMonday.getTime() <= date.getTime() &&
date.getTime() < ( lastMonday.getTime() + WEEK_LENGTH);
return res; // true / false
}
(one week in ms = 24 * 60 * 60 * 1000 * 7 = 604,800,000)
May not be the most optimal solution, but I think it's quite readable:
function isThisWeek (date) {
const now = new Date();
const weekDay = (now.getDay() + 6) % 7; // Make sure Sunday is 6, not 0
const monthDay = now.getDate();
const mondayThisWeek = monthDay - weekDay;
const startOfThisWeek = new Date(+now);
startOfThisWeek.setDate(mondayThisWeek);
startOfThisWeek.setHours(0, 0, 0, 0);
const startOfNextWeek = new Date(+startOfThisWeek);
startOfNextWeek.setDate(mondayThisWeek + 7);
return date >= startOfThisWeek && date < startOfNextWeek;
}
This link explaines, how to do this without using any js libraries. https://gist.github.com/dblock/1081513
Code against link death:
function( d ) {
// Create a copy of this date object
var target = new Date(d.valueOf());
// ISO week date weeks start on monday
// so correct the day number
var dayNr = (d.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;
// Calculate week number: Week 1 (january 4th) plus the
// number of weeks between target date and january 4th
var weekNr = 1 + Math.ceil(dayDiff / 7);
return weekNr;
}
I managed to do it with this simple trick and without any external library.
Considering monday as the first day of the week, the function takes as parameter a date string and do the validation before checking if the day indeed is in the current week.
function isInThisWeek(livr){
const WEEK = new Date()
// convert delivery date to Date instance
const DATEREF = new Date(livr)
// Check if date instance is in valid format (depends on the function arg)
if(DATEREF instanceof Date && isNaN(DATEREF)){
console.log("invalid date format")
return false}
// Deconstruct to get separated date infos
const [dayR, monthR, yearR] = [DATEREF.getDate(), DATEREF.getMonth(), DATEREF.getFullYear()]
// get Monday date
const monday = (WEEK.getDate() - WEEK.getDay()) + 1
// get Saturday date
const sunday = monday + 6
// Start verification
if (yearR !== WEEK.getFullYear()) { console.log("WRONG YEAR"); return false }
if (monthR !== WEEK.getMonth()) { console.log("WRONG MONTH"); return false }
if(dayR >= monday && dayR <= sunday) { return true }
else {console.log("WRONG DAY"); return false}
}
In the comments I saw that you stated that your week starts on Monday.
In that case, I guess it'd be a good idea to calculate the ISO week number of the 2 dates and see if you get the same week number for both of them.
To calculate the ISO week number, check this answer:
In case anyone else's week starts on Sunday instead, you can use this answer to calculate the week number accordingly.
then you can do something like this:
function isSameWeek(date1, date2) {
return date1.getWeekNumber() === date2.getWeekNumber();
}
const isDateInThisWeek = (date) => {
const today = new Date();
//Get the first day of the current week (Sunday)
const firstDayOfWeek = new Date(
today.setDate(today.getDate() - today.getDay())
);
//Get the last day of the current week (Saturday)
const lastDayOfWeek = new Date(
today.setDate(today.getDate() - today.getDay() + 6)
);
//check if my value is between a minimum date and a maximum date
if (date >= firstDayOfWeek && date <= lastDayOfWeek) {
return true;
} else {
return false;
}
};

Going through weeks is automatically changing on wednesday rather than sunday/monday

I'm looking for some help with my coursework as I've spent the last 8 hours trying to find a way to do what i'm trying to accomplish.
Now I have to use JavaScript, cannot use plugins but i can use the jQuery Library.
I'm basically trying to assign weeks to the semesters of the university year, so we say 29th September 2014 (Monday) to 26th January which is around 15 weeks.
Now I'm using something like this:
Date.prototype.getWeek = function() {
var firstJan = new Date(2014,0,1);
var today = new Date(2014, 9, 14);
var firstMonSem1 = new Date(2014, 8, 29);
var firstMonSem2 = new Date(this.getFullYear(), 1, 1);
var dayOfYear = ((today - firstJan + 86400000)/86400000);
var startWeekSem1 = ((firstMonSem1 - firstJan + 86400000)/86400000);
var startWeekSem2 = ((firstMonSem2 - firstJan + 86400000)/86400000);
var currentWeekNumber = Math.ceil(dayOfYear/7);
var startWeekNumberSem1 = Math.ceil(startWeekSem1/7);
var startWeekNumberSem2 = Math.ceil(startWeekSem2/7);
var output = {current: currentWeekNumber, sem1: startWeekNumberSem1, sem2: startWeekNumberSem2};
return output;
};
So i'm returning the current week of the year, semester start date for semester 1 and 2.
But for this example let's only focus on the first is 29th September (Monday) until 26th January which is around 15 weeks.
Now i've worked out based on the values i get when the semester starts and finishes including a 4 week holiday over the christmas period. And then I have an array for the index of which week of the semester we are in, in comparison to the week of the year (this way it could be week 41 in the year and based on the index array I would know that this is week 2).
Here's the code (note: it works!)
var today = new Date();
var info = today.getWeek();
if (info['current'] >= info['sem1'] && info['current'] <= (info['sem1'] + 18)) {
// Semester 1
var index = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var yearWeeks = [];
var count = 1;
for (var i = info['sem1']; i < (info['sem1'] + 18); i++) {
if (count !== 12 && count !== 13 && count !== 14) {
yearWeeks.push(i);
}
count++;
}
var rightIndex = $.inArray(info['current'], yearWeeks);
var x = 1;
while (x <= 15) {
if (x >= rightIndex) {
var weekOption = $("<option/>", {
"value" : x,
html : "Week "+x
}).appendTo(week);
}
x++;
}
}
So what I do here is append to a select all the weeks that are greater than the current week, so if we are in week 5 then there won't be a week 1,2,3,4 for the sake of this example (it's because in the project we are selecting a week to make a booking on but that's irrelevant).
Now, the problem.
This all works fantastically but there is a major catch, the week changes on Wednesday for example:
Week 1 is commencing 29th of September (Monday)
Week 2 starts 8th October (Wednesday)
Week 3 starts 15th October (Wednesday)
So every time the week changes on the Wednesday, now as the idea is that this system is being implemented so you can book room for that given week aka Monday - Friday, I need the weeks to update every Monday rather than Wednesday.
I really need help with this, and I know it might be a lot to grasp. However, I appreciate all the help I can get.
Thank you.
I think you need to replace this line:
var currentWeekNumber = Math.ceil(dayOfYear/7);
To be:
var currentWeekNumber = Math.ceil((dayOfYear + 5)/7);
To make a week start from Wednesday. In such case, the week of Day 2 (Tuesday) is Math.ceil((2+5)/7)=1, while Day 3 (Wednesday) is Math.ceil((3+5)/7)=2.
I worked it out some and hope it helps. This is not just for 2014 that you use, but for the current year. With some adaptation you can adjust.
You get the first of the year and get the offset of the day-number. Then you calculate the current day and subtract. The result will help you get the weeknr.
The week starts on Monday (where in other regions it may be on Sunday).
I created a fiddle, so you can play with it:
http://jsfiddle.net/djwave28/r0m4sokv/
This is an abstract from that fiddle:
// set an offset
var offset = 0;
var now = new Date();
var testday = new Date(now.getTime() + offset * 24 * 60 * 60 * 1000);
var firstofyear = new Date(testday.getFullYear(), 0, 1);
var firstdayoffset = firstofyear.getDay();
var daynr = Math.ceil((testday - firstofyear) / 86400000);
var weeknr = (daynr - firstdayoffset) / 7;

Is there an easy way to find the last date a day of week occurs in the current month

I am trying to display the date of the last Wednesday in the current month... so that it will automatically change to the correct date when the next month occurs. (So instead of having to say: "Performing the last wednesday of every month", I can dymanmically give the actual date.)
For example, I would want the date to show on the webpage as Wednesday, Sept 25th for this month, and then appear as Wednesday, Oct 30th next month.
A bonus additional solution would be if I could get the next month's date to display after the previous date has past. In my above example, when the current date is Sept 26-30 (any date after that last wednesday, but still in the same month).. the date would show the next performance date of Oct 30th.
It would be great if the solution was through html, javascript/jquery or asp.
Thanks,
SunnyOz
It depends on your criteria for "easy". Here's a simple function to do as required, it's 5 lines of working code that can be reduced to 4, but will lose a bit of clarity if that's done:
function lastDayInMonth(dayName, month, year) {
// Day index map - modify to suit whatever you want to pass to the function
var dayNums = {Sunday: 0, Monday:1, Tuesday:2, Wednesday:3,
Thursday:4, Friday:5, Saturday:6};
// Create a date object for last day of month
var d = new Date(year, month, 0);
// Get day index, make Sunday 7 (could be combined with following line)
var day = d.getDay() || 7;
// Adjust to required day
d.setDate(d.getDate() - (7 - dayNums[dayName] + day) % 7);
return d;
}
You can change the map to whatever, just determine what you want to pass to the function (day name, abbreviation, index, whatever) that can be mapped to an ECMAScript day number.
Edit
So in the case of always wanting to show the last Wednesday of the month or next month if it's passed:
function showLastWed() {
var now = new Date();
var lastWedOfThisMonth = lastDayInMonth('Wednesday', now.getMonth()+1, now.getFullYear());
if (now.getDate() > lastWedOfThisMonth().getDate()) {
return lastDayInMonth('Wednesday', now.getMonth()+2, now.getFullYear());
} else {
return lastWedOfThisMonth;
}
}
Note that the function expects the calendar month number (Jan = 1, Feb = 2, etc.) whereas the getMonth method returns the ECMAScript month index (Jan = 0, Feb = 1, etc.) hence the +1 and +2 to get the calendar month number.
You could use a javascript library such as moment.js:
http://momentjs.com/
and then get it with this:
moment().add('months', 1).date(1).subtract('days', 1).day(-4)
Here is an approach in JS:
var monthLengths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
function getLastWednesday() {
var d = new Date();
var month = d.getMonth();
var lastDay = monthLengths[month];
// mind leap years
if (month == 1) {
var year = d.getFullYear();
var isLeapYear = ((year % 4 == 0 && year % 100 > 0) || year % 400 == 0);
if (isLeapYear) lastDay++;
}
// get the weekday of last day in the curent mont
d.setDate(lastDay);
var weekday = d.getDay();
// calculate return value (wednesday is day 3)
if (weekday == 3) {
return lastDay;
}
else {
var offset = weekday - 3;
if (offset < 0) offset += 7;
return lastDay - offset;
}
}
I prefer to use an abstraction like moment.js as #Aralo suggested. To do it in raw JavaScript, however, you can use some code like this... create a function that gets all the days in a month. Then reverse-traverse the list to find the last day number. Wednesday is 3.
function getDaysInMonth(date) {
var dayCursor = new Date(today.getFullYear(), today.getMonth()); // first day of month
var daysInMonth = [];
while(dayCursor.getMonth() == date.getMonth()) {
daysInMonth.push(new Date(dayCursor));
dayCursor.setDate(dayCursor.getDate() + 1);
}
return daysInMonth;
}
function findLastDay(date, dayNumber) {
var daysInMonth = getDaysInMonth(date);
for(var i = daysInMonth.length - 1; i >= 0; i--) {
var day = daysInMonth[i];
if(day.getDay() === dayNumber) return day;
}
}
Then, to get the last Wednesday in the current month:
var today = new Date();
var lastWednesday = findLastDay(today, 3);

Categories

Resources