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

Предположим, следующий код выполняется 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 ]

12 голосов
/ 24 августа 2009

Он всегда должен оставаться неизменным 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 года как неделя предыдущий год.

7 голосов
/ 14 декабря 2009

следующая формула возвращает «текущий» день недели в диапазоне [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);
4 голосов
/ 21 сентября 2011

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

2 голосов
/ 27 марта 2017

Использование 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 (суббота)

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

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


О java.time

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

Проект Joda-Time , находящийся сейчас в режиме обслуживания , рекомендует перейти на классы 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 .
  • Android

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

1 голос
/ 24 августа 2009

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

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

0 голосов
/ 10 января 2017

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

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;
            }
        }
0 голосов
/ 02 сентября 2014

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

 /**
 * 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;
}
0 голосов
/ 09 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...