I am somewhat struggling with this.
I want to setup my Calendar to let\'s say: Third Monday in February 2012. And I didn\'t find any way of doing th
To do date arithmetic in Java (and in general, to do anything with datetimes, except for the most trivial things) Joda-Time is the answer:
public static LocalDate getNDayOfMonth(int dayweek,int nthweek,int month,int year) {
LocalDate d = new LocalDate(year, month, 1).withDayOfWeek(dayweek);
if(d.getMonthOfYear() != month) d = d.plusWeeks(1);
return d.plusWeeks(nthweek-1);
}
public static LocalDate getLastWeekdayOfMonth(int dayweek,int month,int year) {
LocalDate d = new LocalDate(year, month, 1).plusMonths(1).withDayOfWeek(dayweek);
if(d.getMonthOfYear() != month) d = d.minusWeeks(1);
return d;
}
public static void main(String[] args) {
// second wednesday of oct-2011
LocalDate d = getNDayOfMonth( DateTimeConstants.WEDNESDAY, 2, 10, 2011);
System.out.println(d);
// last wednesday of oct-2011
LocalDate dlast = getLastWeekdayOfMonth( DateTimeConstants.WEDNESDAY, 10, 2011);
System.out.println(dlast);
}
Edit: Since Java 8 (2014) the new Date API (package java.time
), which is inspired by/similar to Jodatime, should be preferred.
Any chances you are using Quartz scheduler?
public Date date(String cronExpression) {
return new org.quartz.CronExpression(cronExpression).
getNextValidTimeAfter(new Date(0));
}
System.out.println(date("0 0 0 ? May Thu#3 2015"));
System.out.println(date("0 0 0 ? Jun Mon#1 2050"));
System.out.println(date("0 0 0 ? Dec Tue#4 2012"));
System.out.println(date("0 0 0 ? Jul Wed#2 2000"));
This simple code prints correct (?) results:
Thu May 21 00:00:00 CEST 2015
Mon Jun 06 00:00:00 CEST 2050
Tue Dec 25 00:00:00 CET 2012
Wed Jul 12 00:00:00 CEST 2000
The required CronExpression doesn't have any dependencies on the rest of Quartz, so you might consider copying it to your project (watch out for license!)
Side note: the internal implementation of getNextValidTimeAfter()
is 400 lines of code...
All you need is a loop:
public class CalculateDate {
public static void main( String ... args ) {
Calendar c = Calendar.getInstance();
c.set( Calendar.YEAR, 2012 );
c.set( Calendar.MONTH , Calendar.MAY);
c.set( Calendar.DAY_OF_MONTH, 0 );
c.add( Calendar.DAY_OF_MONTH, -1 );
System.out.println( c.getTime() );
int mondaysCount = 0;
while ( mondaysCount != 4 ) {
c.add( Calendar.DAY_OF_MONTH, 1 );
if ( c.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY ) {
mondaysCount++;
}
}
System.out.printf( "The fourth monday of may is %s", c.getTime() );
}
}
Here is an alternative. What it does is: Get which week you want (n), and the other parameters, and return the date of the day in that week. Since Calendar gives the date of the previous month (for example 29th of February instead of 7th of March, since the 1st week of March collides with last week of Feb), the function computes the 2nd week if the date goes beyond 7 or multiples of it for each week thereof. Hope that helps.
public static int getNthWeekDay (int n, int day, int month, int year) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, day);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.WEEK_OF_MONTH,n);
calendar.set(Calendar.YEAR, year);
if (calendar.get(Calendar.DATE) > n * 7) {
calendar.set(Calendar.DAY_OF_WEEK,day);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.WEEK_OF_MONTH,day+1);
}
return calendar.get(Calendar.DATE);
}
The following code was successfully tested for all holidays in 2013 and 2014. I realize that this doesn't really answer the original question, but I think it might be useful for people who come across this post in hopes of figuring out how to work with holidays using Calendar.
public static boolean isMajorHoliday(java.util.Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// check if New Year's Day
if (cal.get(Calendar.MONTH) == Calendar.JANUARY
&& cal.get(Calendar.DAY_OF_MONTH) == 1) {
return true;
}
// check if Christmas
if (cal.get(Calendar.MONTH) == Calendar.DECEMBER
&& cal.get(Calendar.DAY_OF_MONTH) == 25) {
return true;
}
// check if 4th of July
if (cal.get(Calendar.MONTH) == Calendar.JULY
&& cal.get(Calendar.DAY_OF_MONTH) == 4) {
return true;
}
// check Thanksgiving (4th Thursday of November)
if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER
&& cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 4
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) {
return true;
}
// check Memorial Day (last Monday of May)
if (cal.get(Calendar.MONTH) == Calendar.MAY
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY
&& cal.get(Calendar.DAY_OF_MONTH) > (31 - 7) ) {
return true;
}
// check Labor Day (1st Monday of September)
if (cal.get(Calendar.MONTH) == Calendar.SEPTEMBER
&& cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 1
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
return true;
}
// check President's Day (3rd Monday of February)
if (cal.get(Calendar.MONTH) == Calendar.FEBRUARY
&& cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
return true;
}
// check Veterans Day (November 11)
if (cal.get(Calendar.MONTH) == Calendar.NOVEMBER
&& cal.get(Calendar.DAY_OF_MONTH) == 11) {
return true;
}
// check MLK Day (3rd Monday of January)
if (cal.get(Calendar.MONTH) == Calendar.JANUARY
&& cal.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 3
&& cal.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
return true;
}
return false;
}
I do not know the "easy" way but I can suggest you the following.