Given a weekday and the day of the month it occurs, can I get its ordinal position in constant time?
Say I'm given a date, from which I can get its day of the month and day of the week. For example (in Javascript):
var d = new Date(1316038581772); // Wed Sep 14 2011 12:16:21 GMT-1000
var dayOfWeek = d.getDay(); // 3 - Wednesday
var dayOfMonth = d.getDate(); // 14 - Day of month
I'm looking for a value n
such that this date is the n
th day of the week in the month. In this case, I'm looking for n=2
, for the 2nd Wednesday in September 2011.
The naive algorithm would be to find the first occurrence of that weekday in the month, take the difference in days, and divide by 7, but this isn't in constant time. For example, I would need to iterate over each day from the first day in September 7 times to reach the first Wednesday.
Is there a constant-time solution to this problem?
(For anyone interested, I'm trying to generate ordinal values for iCalendar recurrence rules; given a date, generate the monthly recurrence for the n
th day of each month. The rule 开发者_如何转开发for this case would be something like
RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=WE;BYSETPOS=2
or
RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=2WE
)
Divide by 7 and round up.
The 14th is always the 2nd [weekday] of the month, the 15th is always the 3rd [weekday] of the month, etc.
Take the day of the month, add 6, and divide by 7, throwing away the remainder.
You need two functions- one to get the day info, the other for the nth.
Number.prototype.nth= function(){
var n= Math.round(this), t= Math.abs(n%100), i= t%10;
if(i<4 && (t<4 || t> 20)){
switch(i){
case 1:return n+'st';
case 2:return n+'nd';
case 3:return n+'rd';
}
}
return n+'th';
}
Date.prototype.nthofMonth= function(){
var today= this.getDate(),m=this.getMonth(),
day= ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday'][this.getDay()],
month= ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'][m];
return [(m+1)+'-'+today,'the ', (Math.ceil((today)/7)).nth(), day, 'of', month, 'in', this.getFullYear()].join(' ');
}
精彩评论