Подтвердить что ты не робот

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

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

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

c.get(Calendar.DAY_OF_MONTH) вернется 23. Меня интересуют условия, которые вернутся 14 (в прошлое воскресенье, а не в следующее воскресенье).

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

4b9b3361

Ответ 1

Он должен всегда сохранять те же WEEK_OF_MONTH (http://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() могут быть разными. Например, конкретный календарь подкласс может указывать за неделю до неделю 1 года в качестве недели n в прошлом году.

Ответ 2

следующая формула возвращает "текущий" день в неделю в диапазоне [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);

Ответ 3

На самом деле это зависит. Рассмотрим следующий код 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!

Ответ 4

Из 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

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

Ответ 5

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

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

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

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

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

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

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

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

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

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 (суббота)

previousSunday: 2009-08-16

nextSunday: 2009-08-23


О java.time

Структура java.time встроена в Java 8 и более поздних версий. Эти классы вытесняют неприятный старый legacy классы даты-времени, такие как java.util.Date, Calendar и SimpleDateFormat.

Проект Joda-Time, теперь режим обслуживания, советуем перейти к классам java.time.

Чтобы узнать больше, см. Учебник Oracle. И поиск Qaru для многих примеров и объяснений. Спецификация 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.
  • Android

Проект ThreeTen-Extra расширяет java.time с помощью дополнительных классов. Этот проект является доказательством возможных будущих дополнений к java.time. Здесь вы можете найти полезные классы, такие как Interval, YearWeek, YearQuarter и больше.

Ответ 6

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

Ответ 7

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

 /**
 * 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;
}

Ответ 8

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

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