What is the difference between Calendar.WEEK_OF_MONTH and Calendar.DAY_OF_WEEK_IN_MONTH in Java's Calendar class?

Viewed 21224

Java's Calendar class provides for two fields: WEEK_OF_MONTH and DAY_OF_WEEK_IN_MONTH. Can someone explain the difference to me? It seems that they both return the same value when tested using the code below:

Calendar date = Calendar.getInstance();
date.set(2011,5,29);
int weekNo1 = date.get(Calendar.WEEK_OF_MONTH);
int weekNo2 = date.get(Calendar.DAY_OF_WEEK_IN_MONTH);
6 Answers

You must also take in count that Calendar.getInstance depends on Locale. So, you sometimes could have to specify a concrete Locale instead of the default Locale, for instance: Calendar.getInstance(new Locale("es","PE").

For the example, avobe, Calendar.getInstance(new Locale("es","PE") the calendar will consider first days of the week the Mondays, in other Locales could be other days

tl;dr

  • Calendar.WEEK_OF_MONTH
    • Obsolete, never use Calendar.
    • Means the nth week within a month, with definition varying by Locale and the result of getFirstDayOfWeek().
    • If you want to define a week as week-of-month # 1 is the week containing day-of-month 1, then use: LocalDate::get( ChronoField.ALIGNED_WEEK_OF_MONTH )
  • Calendar.DAY_OF_WEEK_IN_MONTH
    • Obsolete, never use Calendar.
    • Means the nth day-of-week within that month, such 2nd Tuesday, where weeks are defined as week # 1 containing day 1 of that month.
    • Replaced by LocalDate::get( ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH )

Avoid Calendar legacy class

Be aware that the Calendar class used in the question is terrible, and was supplanted years ago by the modern java.time classes defined in JSR 310. Do not use Calendar nor GregorianCalendar. They were designed by people who did not understand date-time handling.

java.time

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.

LocalDate ld = LocalDate.of( 2020 , Month.JANUARY , 23 ) ;  // 2020-01-23.

Convert

If given a Calendar object that is really a GregorianCalendar, you can easily convert to a modern ZonedDateTime object.

GregorianCalendar gc = ( GregorianCalendar ) myCalendar ;  // Cast from more general class to the concrete class underlying.
ZonedDateTime zdt = gc.toZonedDateTime() ;

Extract the date-only portion.

LocalDate ld = zdt.toLocalDate() ;  // Extract the date, omitting the time-of-day and the context of a time zone.

ChronoField

You can interrogate a LocalDate object via the get method with various ChronoField enum objects.

Calendar.WEEK_OF_MONTH

This asks for the week of the month. But how do you define a week of the month? Unfortunately, the Calendar class’ definition varies by Locale. So your results may vary at runtime.

If your definition is that week # 1 has the first day of the calendar month, you can interrogate a LocalDate using ChronoField.ALIGNED_WEEK_OF_MONTH.

int weekOfMonth = ld.get( ChronoField.ALIGNED_WEEK_OF_MONTH ) ;

Calendar.DAY_OF_WEEK_IN_MONTH

This means the nth day-of-week found in the month, such as 2nd-Tuesday or third-Thursday. Unlike Calendar.WEEK_OF_MONTH, this definition does not vary by Locale. Week # 1 is the week containing day-of-month 1. This legacy Calendar class really is an awful mess, confusing and inconsistent. Good riddance.

Now in java.time, use instead ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH.

DayOfWeek dow = ld.getDayOfMonth() ;  // Get enum object representing day of week such as `DayOfWeek.MONDAY`. 
int nthDayOfWeekOfMonth = ld.get( ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH ) ;
Related