Java Calendar.set (Calendar.DAY_OF_WEEK, Calendar.SUNDAY), будет ли он откатываться назад, вперед или неизвестно?

Предположим, что следующий код выполняется 22 августа 2009 года (суббота)

   Calendar c = Calendar.getInstance();
   c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);

c.get(Calendar.DAY_OF_MONTH) вернусь 23. Я 'Интересующие меня условия будут возвращаться 14 (в прошлое воскресенье, а не в следующее воскресенье).

Есть ли какие-либо правила, связанные с направлением?DAY_OF_MONTH/YEAR когдаDAY_OF_WEEK установлен? Если так, то кто они?

Ответы на вопрос(8)

Зависит от первого дня недели:

 /**
 * Gets what the first day of the week is; e.g., <code>SUNDAY</code> in the U.S.,
 * <code>MONDAY</code> in France.
 *
 * @return the first day of the week.
 * @see #setFirstDayOfWeek(int)
 * @see #getMinimalDaysInFirstWeek()
 */
public int getFirstDayOfWeek()
{
    return firstDayOfWeek;
}
Решение Вопроса

Всегда должно быть одинаковым (WEEK_OF_MONTHhttp://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#WEEK_OF_MONTH). Из документации:

При установке или получении полей WEEK_OF_MONTH или WEEK_OF_YEAR Календарь должен определить первую неделю месяца или года в качестве ориентира. Первая неделя месяца или года определяется как самый ранний семидневный период, начинающийся с getFirstDayOfWeek () и содержащий как минимум getMinimalDaysInFirstWeek () дни этого месяца или года. Недели пронумерованы ..., -1, 0 предшествуют первой неделе; недели, пронумерованные 2, 3, ... следуйте за этим. Обратите внимание, что нормализованная нумерация, возвращаемая get (), может отличаться. Например, определенный подкласс Calendar может обозначать неделю до недели 1 года как неделю n предыдущего года.

следующая формула возвращает "ток" день недели в диапазоне [0; 6]

(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek

или добавьте 1, если вы хотите диапазон [1; 7]

(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek + 1

d это чтоCalendar.get(Calendar.DAY_OF_WEEK) возвращается

чтобы получить первый день недели, вычтите формулурезультат с текущей даты. Следующий код делает это:

final int currentDayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 7 - cal.getFirstDayOfWeek()) % 7;
cal.add(Calendar.DAY_OF_YEAR, -currentDayOfWeek);

Вы можете использовать как этот метод.

public Integer whichDayOfWeek(Calendar calendar) {
            if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
                return 1;
            } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY) {
                return 2;
            } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
                return 3;
            } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) {
                return 4;
            } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
                return 5;
            } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
                return 6;
            } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
                return 7;
            } else {
                return null;
            }
        }
 Todd21 авг. 2018 г., 16:49
это нене обращаться к афишевопрос вообще

Это зависит, на самом деле. Рассмотрим следующий код Java. Это на самом деле довольно просто, и я ожидаю, что он напечатает понедельник, предшествующий 2011-09-18, то есть 2011-09-12:

Calendar calendar = Calendar.getInstance(Locale.GERMANY);
System.out.printf("First day of week: %d%n%n", calendar.getFirstDayOfWeek());

calendar.set(2011, Calendar.SEPTEMBER, 18);
System.out.printf("Starting day: %tF%n", calendar);
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.printf("Last monday: %tF%n%n", calendar);

calendar.set(2011, Calendar.SEPTEMBER, 18);
System.out.printf("Starting day: %tF (week %d)%n",
        calendar, calendar.get(Calendar.WEEK_OF_YEAR));
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.printf("Last monday: %tF (week %d)%n", calendar,
        calendar.get(Calendar.WEEK_OF_YEAR));

Но на самом деле результат немного другой:

First day of week: 2

Starting day: 2011-09-18
Last monday: 2011-09-19

Starting day: 2011-09-18 (week 37)
Last monday: 2011-09-12 (week 37)

Другими словами, результат зависит от того, знает ли мой календарь, что я могу быть заинтересован в неделе. Результат действительно меняется, если я сделаю запрос!WEEK_OF_YEAR

ОтJavadoc:

Если есть какой-либо конфликт в значениях полей календаря, Календарь отдает приоритет полям календаря, которые были установлены более недавно. Ниже приведены комбинации полей календаря по умолчанию. Будет использоваться самая последняя комбинация, определенная самым последним установленным одиночным полем.

Для полей даты:

 YEAR + MONTH + DAY_OF_MONTH
 YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
 YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
 YEAR + DAY_OF_YEAR
 YEAR + DAY_OF_WEEK + WEEK_OF_YEAR

Я понимаю, что это означает, что, учитывая, что выЕсли установить день недели, он будет объединен с неделей месяца или недели года для получения фактической даты и времени.

Вы также должны проверить, какой первый день недели. Я также думал, что это всегда воскресенье, но это зависит от местных настроек, и в моем случае понедельник - первый день недели. Установка воскресенья в качестве первого дня недели устранила мою проблему.

Использование java.time

Современный подход с классами java.time, которые вытесняют проблемные старые классы даты и времени.

С классами java.time работать намного проще. В частности, они устраняют неоднозначность, поднятую в Вопросе. Вы можете явно попросить либоранее Воскресенье или дляпотом Воскресенье.

LocalDate класс представляет значение только для даты без времени суток и без часового пояса.

Month enum предоставляет дюжину предопределенных объектов, по одному на каждый месяц года. Эти перечисляемые объекты безопаснее использовать, но вместо этого вы можете использовать простое число для месяца. В отличие от предыдущих классов, эти месяцы имеют нормальную нумерацию, 1–12 за январь-декабрь.

LocalDate localDate = LocalDate.of( 2009 , Month.AUGUST, 22 );

TemporalAdjuster Интерфейс обеспечивает манипулирование значениями даты и времени.TemporalAdjusters класс (обратите внимание на множественное числоs) предоставляет несколько удобных реализаций.

previous & next Настройщики исключают саму дату из рассмотрения.previousOrSame & nextOrSame методы возвращают указанную дату, если это действительно желаемый день недели.

DayOfWeek enum предоставляет семь предопределенных объектов, по одному на каждый день недели.

LocalDate previousSunday = localDate.with( TemporalAdjusters.previous ( DayOfWeek.SUNDAY ));
LocalDate previousOrSameSunday = localDate.with( TemporalAdjusters.previousOrSame ( DayOfWeek.SUNDAY ));

LocalDate nextSunday = localDate.with( TemporalAdjusters.next ( DayOfWeek.SUNDAY ));
LocalDate nextOrSameSunday = localDate.with( TemporalAdjusters.nextOrSame ( DayOfWeek.SUNDAY ));

Дамп на консоль.

System.out.println ("localDate: " + localDate + " ( " + localDate.getDayOfWeek ().getDisplayName ( TextStyle.FULL, Locale.US )  + " )");
System.out.println ("previousSunday: " + previousSunday );
System.out.println ("nextSunday: " + nextSunday );

localDate: 2009-08-22 (суббота)

предыдущее воскресенье: 2009-08-16

следующее воскресенье: 2009-08-23

О java.time

java.time фреймворк встроен в Java 8 и выше. Эти классы вытесняют хлопотное староенаследие классы даты и времени, такие как, &java.util.DateCalendar ,SimpleDateFormat

Joda времени проект, сейчас вРежим технического обслуживанияПосоветует миграцию наjava.time классы.

Чтобы узнать больше, см.Oracle Tutorial, И поиск переполнения стека для многих примеров и объяснений. СпецификацияJSR 310.

Где взять классы java.time?

Java SE 8 а такжеSE 9 и позжеВстроенный.Часть стандартного Java API с комплексной реализацией.Java 9 добавляет некоторые незначительные функции и исправления.Java SE 6 а такжеSE 7Большая часть функциональности java.time перенесена на Java 6 & 7 вThreeTen-Backport.AndroidThreeTenABP проект адаптируетсяThreeTen-Backport (упомянуто выше) специально для Android.УвидетьКак использовать ThreeTenABP ....

ThreeTen-Extra Проект расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Вы можете найти некоторые полезные классы здесь, такие как,IntervalYearWeekYearQuarter, а такжеБольше.

Ваш ответ на вопрос