开发者

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:

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

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 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 ) ;


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜