"is this date the third thursday of the month?" - Java Library?

710 views Asked by At

I've got a few dozen backlog requests in the pipeline like

'I need this functionality to run on the third Thursday of every month, and the first Wednesday of every other month...'

I've already got a function that runs every day, i just need the: isThirdSundayOfMonth(date) bit to append onto then end.

The less time I spend considering the nuances of the Gregorian calendar and timezones, the better my life is.

Anyone know a Java library that simplifies this sort of calculation? No xml config or frameworks or anything. Just a .Jar and a documented, readable API would be perfect.

Any help would be much appreciated.

2

There are 2 answers

0
Meno Hochschild On BEST ANSWER

Complete overview:

In Java-8 (new standard):

LocalDate input = LocalDate.now(); // using system timezone
int ordinal = 3;
DayOfWeek weekday = DayOfWeek.SUNDAY;

LocalDate adjusted = 
  input.with(TemporalAdjusters.dayOfWeekInMonth(ordinal, weekday));
boolean isThirdSundayInMonth = input.equals(adjusted);

In Joda-Time (popular 3rd-party-library):

LocalDate input = new LocalDate(); // using system timezone
int ordinal = 3;
int weekday = DateTimeConstants.SUNDAY;

LocalDate start = new LocalDate(input.getYear(), input.getMonthOfYear(), 1);
LocalDate date = start.withDayOfWeek(weekday);
LocalDate adjusted = (
  date.isBefore(start)) 
  ? date.plusWeeks(ordinal) 
  : date.plusWeeks(ordinal - 1);
boolean isThirdSundayInMonth = input.equals(adjusted);

Using java.util.GregorianCalendar (old standard):

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
GregorianCalendar input = new GregorianCalendar();
int ordinal = 3;
int weekday = Calendar.SUNDAY;

GregorianCalendar start =
    new GregorianCalendar(input.get(Calendar.YEAR), input.get(Calendar.MONTH), 1);
int dow = start.get(Calendar.DAY_OF_WEEK); // Sun=1, Mon=2, ...
int delta = (weekday - dow);
if (delta < 0) {
    delta += 7;
}
start.add(Calendar.DAY_OF_MONTH, delta + (ordinal - 1) * 7);
String comp1 = sdf.format(input.getTime());
String comp2 = sdf.format(start.getTime());
boolean isThirdSundayInMonth = comp1.equals(comp2);

Even with the ugliest library a solution is possible ;-) I have used a string comparison in order to get rid of any timezone effects or time-of-day-parts including milliseconds. A field-wise comparison based only on year, month and day-of-month is also a good idea.

Using Time4J (my own 3rd-party-library):

PlainDate input = 
  SystemClock.inLocalView().today(); // using system timezone
Weekday weekday = Weekday.SUNDAY;

PlainDate adjusted = 
  input.with(PlainDate.WEEKDAY_IN_MONTH.setToThird(weekday));
boolean isThirdSundayInMonth = input.equals(adjusted);
1
Daniel Martin On

The canonical library for all things date and time related is Joda Time. Adopt that and purge all the standard java classes like Date, Calendar, etc.

It will make your life much better.

As for "How do I use joda-time to find the third Thursday of the month", there's a stackoverflow answer for that already. I'd suggest using the code that the question asker posted and then the question "is it now the third Thursday of the month" is answered by:

LocalDate today = new LocalDate();
if (today.equals(calcDayOfWeekOfMonth(DateTimeConstants.THURSDAY, 3, today))) {
    // do special third-Thursday processing here
}