What is the difference between Calendar.WEEK_OF_MONTH and Calendar.DAY_OF_WEEK_IN_MONTH in Java's Calendar class?
Java's Calendar class provides for two fields: WEEK_开发者_C百科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);
Calendar.WEEK_OF_MONTH
simply returns "Current week number in current month"Calendar.DAY_OF_WEEK
simply returns "Current day number in current week starting on last Sunday"Calendar.DAY_OF_WEEK_IN_MONTH
returns "N if current day is Nth day of month" say "3 if today is 3rd Wednesday in month"
So I am writing this on 21st December 2016:
And this is what I am getting:
Calendar today = Calendar.getInstance();
System.out.println(today.get(Calendar.DAY_OF_WEEK)); //outputs 4, as today is 4th day in this week which started on 18
System.out.println(today.get(Calendar.DAY_OF_WEEK_IN_MONTH)); //outputs 3, as today is "3rd Wednesday of this month". Earlier two wednesday were on 7th and 14th
System.out.println(today.get(Calendar.WEEK_OF_MONTH)); //outputs 4, as currently 4th week of a month is running
The difference is that DAY_OF_WEEK_IN_MONTH provides the number of times the weekday has occurred during the month and WEEK_OF_MONTH just returns the week number within the current month. Think of it this way, if the month starts on a Wednesday, the first Monday will occur during the second week of the month. The value for DAY_OF_WEEK_IN_MONTH for that Monday would be 1, but the WEEK_OF_MONTH would be 2.
I found all of the other docs confusing, so for any Microsoft developers like myself this one might be clear for you, as it was for me:
http://msdn.microsoft.com/en-us/library/aa986432(v=vs.80).aspx
A constant representing a value for how many times a given day has occurred in the month.
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 ofgetFirstDayOfWeek()
. - 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 )
- Obsolete, never use
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 )
- Obsolete, never use
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 ) ;
Week of Month is the week within the current month starting from sundays how many weeks have there been.
Day of week of month is the day 5 would be Thursday, 1 sunday ect.
精彩评论