/*
* (c) Rob Gordon 2005
*/
package org.oddjob.schedules;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.oddjob.schedules.units.DayOfMonth;
import org.oddjob.schedules.units.DayOfWeek;
import org.oddjob.schedules.units.WeekOfMonth;
public class CalendarUtils {
private final Calendar baseCalendar;
/**
* Constructor.
*
* @param inDate The date to base functionality on.
* @param timeZone The timezone for the calendar
*/
public CalendarUtils(Date inDate, TimeZone timeZone) {
baseCalendar = Calendar.getInstance(timeZone);
baseCalendar.setTime(inDate);
}
/**
* Constructor base on an existing calendar.
*
* @param baseCalendar
*/
public CalendarUtils(Calendar baseCalendar) {
this(baseCalendar.getTime(), baseCalendar.getTimeZone());
}
/**
* Return a new calendar with the base calendar time zone
* but a different date.
*
* @param date The date.
* @return The new calendar.
*/
public Calendar forDate(Date date) {
Calendar c2 = Calendar.getInstance(baseCalendar.getTimeZone());
c2.setTime(date);
return c2;
}
/**
* Calculate the start of day date time (i.e. at 00:00) for a given date.
*
* @return The Calendar at the start of the day.
*/
public Calendar startOfDay() {
Calendar c2 = Calendar.getInstance(baseCalendar.getTimeZone());
c2.clear();
c2.set(baseCalendar.get(Calendar.YEAR),
baseCalendar.get(Calendar.MONTH),
baseCalendar.get(Calendar.DATE));
return c2;
}
/**
* Calculate start of the day after.
*
* @return The Calendar at the start of the next day.
*/
public Calendar endOfDay() {
Calendar c2 = Calendar.getInstance(baseCalendar.getTimeZone());
c2.clear();
c2.set(baseCalendar.get(Calendar.YEAR),
baseCalendar.get(Calendar.MONTH),
baseCalendar.get(Calendar.DATE) + 1);
return c2;
}
/**
* Set the calendar to the end of day.
*
* @param calendar The calendar that will be set.
*/
public static void setEndOfDay(Calendar calendar) {
calendar.add(Calendar.DATE, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
/**
* Set the calendar to the end of the month.
*
* @param calendar The calendar that will be set.
*/
public static void setEndOfMonth(Calendar calendar) {
calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
/**
* Calculate the date at the start of the month for the given date.
*
* @return The date at the start of the month.
*/
public Calendar startOfMonth() {
Calendar c2 = Calendar.getInstance(baseCalendar.getTimeZone());
c2.clear();
c2.set(baseCalendar.get(Calendar.YEAR),
baseCalendar.get(Calendar.MONTH), 1);
return c2;
}
/**
* Calculate the date at the end of the month for the given date.
*
* @return The calendar at the end of the month.
*/
public Calendar endOfMonth() {
// get the date at the beginning of next month
Calendar c2 = Calendar.getInstance(baseCalendar.getTimeZone());
c2.clear();
c2.set(baseCalendar.get(Calendar.YEAR),
baseCalendar.get(Calendar.MONTH) + 1, 1);
return c2;
}
/**
* Utility function to get a calendar which
* represents the day of the month in which the reference date is.
*
* @param day The day.
* @return The Calendar.
*/
public Calendar dayOfMonth(DayOfMonth dayOfMonth) {
int day = dayOfMonth.getDayNumber();
int month = day > 0 ?
baseCalendar.get(Calendar.MONTH) :
baseCalendar.get(Calendar.MONTH) + 1;
Calendar c2 = Calendar.getInstance(
baseCalendar.getTimeZone());
c2.clear();
c2.set(baseCalendar.get(Calendar.YEAR), month, day);
return c2;
}
public Calendar startOfWeekOfMonth(WeekOfMonth week) {
int weekNumber = week.getWeekNumber();
Calendar result = Calendar.getInstance(baseCalendar.getTimeZone());
result.clear();
result.setFirstDayOfWeek(Calendar.MONDAY);
result.setMinimalDaysInFirstWeek(7);
result.set(Calendar.YEAR, baseCalendar.get(Calendar.YEAR));
if (weekNumber < 0) {
result.set(Calendar.MONTH, baseCalendar.get(Calendar.MONTH) + 1);
}
else {
result.set(Calendar.MONTH, baseCalendar.get(Calendar.MONTH));
}
result.set(Calendar.WEEK_OF_MONTH, weekNumber);
return result;
}
public Calendar endOfWeekOfMonth(WeekOfMonth week) {
Calendar result = startOfWeekOfMonth(week);
result.add(Calendar.DATE, 7);
return result;
}
public Calendar dayOfWeekInMonth(DayOfWeek dayOfWeek, WeekOfMonth week) {
int weekNumber = week.getWeekNumber();
int javaDay = javaDayOfWeek(dayOfWeek);
Calendar result = Calendar.getInstance(baseCalendar.getTimeZone());
result.clear();
result.set(Calendar.YEAR, baseCalendar.get(Calendar.YEAR));
result.set(Calendar.MONTH, baseCalendar.get(Calendar.MONTH));
result.set(Calendar.DAY_OF_WEEK_IN_MONTH, weekNumber);
result.set(Calendar.DAY_OF_WEEK, javaDay);
return result;
}
/**
* Calculate the start of the week for the given date.
*
* @param inDate The given date.
*
* @return The date at the start of the month.
*/
public static Calendar startOfWeek(Date inDate, TimeZone timeZone) {
Calendar c1 = Calendar.getInstance(timeZone);
c1.setTime(inDate);
Calendar c2 = Calendar.getInstance(timeZone);
c2.clear();
int daysBefore = isoDayOfWeek(c1.get(Calendar.DAY_OF_WEEK)) - 1;
c2.set(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH),
c1.get(Calendar.DAY_OF_MONTH) - daysBefore);
return c2;
}
/**
* Calculate the start of the week for the given date.
*
* @param inDate The given date.
*
* @return The date at the start of the month.
*/
public static Calendar endOfWeek(Date inDate, TimeZone timeZone) {
Calendar c1 = Calendar.getInstance(timeZone);
c1.setTime(inDate);
Calendar c2 = Calendar.getInstance(timeZone);
c2.clear();
int daysToAdd = 8 - isoDayOfWeek(c1.get(Calendar.DAY_OF_WEEK));
c2.set(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH),
c1.get(Calendar.DAY_OF_MONTH) + daysToAdd);
return c2;
}
private static int isoDayOfWeek(int javaDayOfWeek) {
switch (javaDayOfWeek) {
case Calendar.MONDAY:
return 1;
case Calendar.TUESDAY:
return 2;
case Calendar.WEDNESDAY:
return 3;
case Calendar.THURSDAY:
return 4;
case Calendar.FRIDAY:
return 5;
case Calendar.SATURDAY:
return 6;
case Calendar.SUNDAY:
return 7;
default:
throw new IllegalArgumentException("Invalid day of week " +
javaDayOfWeek);
}
}
private static int javaDayOfWeek(DayOfWeek isoDayOfWeek) {
switch (isoDayOfWeek.getDayNumber()) {
case 1:
return Calendar.MONDAY;
case 2:
return Calendar.TUESDAY;
case 3:
return Calendar.WEDNESDAY;
case 4:
return Calendar.THURSDAY;
case 5:
return Calendar.FRIDAY;
case 6:
return Calendar.SATURDAY;
case 7:
return Calendar.SUNDAY;
default:
throw new IllegalArgumentException("Invalid day of week " +
isoDayOfWeek);
}
}
/**
* Utility function to get a calendar which
* represents the day of the week from the reference date.
* @param day The day.
*/
public Calendar dayOfWeek(
DayOfWeek dayOfWeek) {
int day = dayOfWeek.getDayNumber();
Calendar c2 = Calendar.getInstance(
baseCalendar.getTimeZone());
c2.clear();
c2.set(baseCalendar.get(Calendar.YEAR),
baseCalendar.get(Calendar.MONTH),
baseCalendar.get(Calendar.DAY_OF_MONTH));
int offset = day - isoDayOfWeek(baseCalendar.get(Calendar.DAY_OF_WEEK));
c2.add(Calendar.DATE, offset);
return c2;
}
/**
* Calculate the date at the start of the year for the given date.
*
* @param referenceDate The given date.
* @return The calendar at the start of the year.
*/
public static Calendar startOfYear(Date referenceDate, TimeZone timeZone) {
Calendar c1 = Calendar.getInstance(timeZone);
c1.setTime(referenceDate);
Calendar c2 = Calendar.getInstance(timeZone);
c2.clear();
c2.set(c1.get(Calendar.YEAR), 0, 1);
return c2;
}
/**
* Calcuate the date at the end of the year from the
* given date.
*
* @param referenceDate The given date.
* @return The calendar at the end of the year.
*/
public static Calendar endOfYear(Date referenceDate, TimeZone timeZone) {
Calendar c1 = Calendar.getInstance(timeZone);
c1.setTime(referenceDate);
Calendar c2 = Calendar.getInstance();
c2.clear();
c2.set(c1.get(Calendar.YEAR) + 1, 0, 1);
c2.setTimeZone(timeZone);
return c2;
}
/**
* Calendar for the day of year.
*
* @param referenceDate The date to take year from.
* @param dayOfYear The day of the year.
* @return The calendar.
*/
public Calendar dayOfYear(int dayOfMonth, int month) {
Calendar c2 = Calendar.getInstance(baseCalendar.getTimeZone());
c2.clear();
c2.set(Calendar.YEAR, baseCalendar.get(Calendar.YEAR));
c2.set(Calendar.DATE, dayOfMonth);
c2.set(Calendar.MONTH, month - 1);
return c2;
}
/**
* Utility function to get the start of the month as a Calendar.
*
* @param referenceDate The whole date.
* @param month The month to calculate the start of. 1 is January,
* 12 is December.
*
* @return The start of the month.
*/
public static Calendar monthOfYear(Date referenceDate, int month, TimeZone timeZone) {
Calendar c1 = Calendar.getInstance(timeZone);
c1.setTime(referenceDate);
Calendar c2 = Calendar.getInstance(timeZone);
c2.clear();
// Adjust for Java 0 based months.
c2.set(c1.get(Calendar.YEAR), month - 1, 1);
return c2;
}
}