Ответ 1
Неделя месяца - это неделя в течение текущего месяца, начиная с воскресенья, сколько недель было.
День недели месяца - это день 5, будет четверг, 1 воскресенья и т.д.
Класс Java Calendar предоставляет два поля: WEEK_OF_MONTH и DAY_OF_WEEK_IN_MONTH. Может кто-нибудь объяснить мне разницу? Кажется, что оба они возвращают одинаковое значение при тестировании, используя следующий код:
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);
Неделя месяца - это неделя в течение текущего месяца, начиная с воскресенья, сколько недель было.
День недели месяца - это день 5, будет четверг, 1 воскресенья и т.д.
Calendar.WEEK_OF_MONTH
просто возвращает номер текущей недели в текущем месяцеCalendar.DAY_OF_WEEK
просто возвращает "Текущий номер дня на текущей неделе, начиная с последнего воскресенья" Calendar.DAY_OF_WEEK_IN_MONTH
возвращает "N, если текущий день - N-й день месяца. say " 3, если сегодня третья среда месяцаИтак, я пишу это 21-го декабря 2016 года:
И вот что я получаю:
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
Разница заключается в том, что DAY_OF_WEEK_IN_MONTH предоставляет количество раз, когда день недели произошел в течение месяца, а WEEK_OF_MONTH просто возвращает номер недели в текущем месяце. Подумайте об этом таким образом, если месяц начнется в среду, первый понедельник будет происходить в течение второй недели месяца. Значение для DAY_OF_WEEK_IN_MONTH для этого понедельника будет равно 1, но WEEK_OF_MONTH будет равно 2.
Я обнаружил, что все другие документы запутаны, поэтому для любых разработчиков Microsoft, таких как я, это может быть ясно для вас, как и для меня:
http://msdn.microsoft.com/en-us/library/aa986432(v=vs.80).aspx
Константа, представляющая значение для того, сколько раз в данный день произошло в течение месяца.
Вы также должны учитывать, что Calendar.getInstance зависит от локали. Поэтому иногда может потребоваться указать конкретную локаль вместо локали по умолчанию, например: Calendar.getInstance (новая локаль ("es", "PE").
Например, avobe, Calendar.getInstance (новая локаль ("es", "PE") календарь будет считать первые дни недели понедельниками, в других локалях могут быть другие дни.
Calendar.WEEK_OF_MONTH
Calendar
.Locale
и результатом getFirstDayOfWeek()
.LocalDate::get( ChronoField.ALIGNED_WEEK_OF_MONTH )
Calendar.DAY_OF_WEEK_IN_MONTH
Calendar
.LocalDate::get( ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH )
Calendar
Помните, что класс Calendar
, использованный в этом вопросе, ужасен и был вытеснен несколько лет назад современными классами java.time, определенными в JSR 310. Не используйте ни Calendar
, ни GregorianCalendar
. Они были разработаны людьми, которые не понимали обработку даты и времени.
LocalDate
Класс LocalDate
представляет значение только для даты без времени суток и без часового пояса или смещения от UTC.
LocalDate ld = LocalDate.of( 2020 , Month.JANUARY , 23 ) ; // 2020-01-23.
Если дан объект Calendar
, который действительно является GregorianCalendar
, вы можете легко преобразовать его в современный объект ZonedDateTime
.
GregorianCalendar gc = ( GregorianCalendar ) myCalendar ; // Cast from more general class to the concrete class underlying.
ZonedDateTime zdt = gc.toZonedDateTime() ;
Извлечь часть только для даты.
LocalDate ld = zdt.toLocalDate() ; // Extract the date, omitting the time-of-day and the context of a time zone.
ChronoField
Вы можете опросить объект LocalDate
с помощью метода get
с различными объектами перечисления ChronoField
.
Это требует недели месяца. Но как вы определяете неделю месяца? К сожалению, определение класса Calendar
варьируется в зависимости от Locale
. Таким образом, ваши результаты могут отличаться во время выполнения.
Если вы определили, что неделя № 1 имеет первый день календарного месяца, вы можете опросить LocalDate
, используя ChronoField.ALIGNED_WEEK_OF_MONTH
.
int weekOfMonth = ld.get( ChronoField.ALIGNED_WEEK_OF_MONTH ) ;
Это означает n-й день недели, найденный в месяце, например, 2-вторник или 3-й четверг. В отличие от Calendar.WEEK_OF_MONTH
, это определение не зависит от Locale
. Неделя № 1 - это неделя, содержащая день месяца 1. Этот унаследованный класс Calendar
действительно ужасный беспорядок, запутанный и противоречивый. Хорошее избавление.
Теперь в java.time используйте вместо этого 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 ) ;