java.time
Java 8 и более поздние версии поставляются с новым пакетом java.time. Вдохновлен Joda-Time , определенным JSR 310 , расширенным проектом ThreeTen-Extra . Эти новые классы заменяют общеизвестно хлопотные java.util.Date/.Calendar & java.text.SimpleDateFormat и тому подобное.
Обратите внимание, что мы указываем часовой пояс, важный для определения даты. Например, в Париже новый день наступает раньше, чем в Монреале.
ZoneId zoneId = ZoneId.of( "America/Montreal" ); // Time zone is crucial in determining the date. A new day dawns earlier in Paris than In Montréal, for example.
Вы написали бы этот код, чтобы использовать только LocalDate
без какого-либо времени суток. Но в бизнесе полная дата-время часто более полезна. Так что мой пример здесь использует ZonedDateTime
.
Чтобы быть аккуратным, я хочу установить время дня в первый момент дня. Можно предположить, что это означает 00:00:00.0
, но не всегда из-за таких аномалий, как Летнее время . Чтобы софт-кодировать этот первый момент, мы хотим вызвать метод atStartOfDay
, найденный в LocalDate. Итак, мы начинаем с LocalDate
, затем используем этот метод для получения ZonedDateTime
объекта.
Опять же, обратите внимание, что мы указываем часовой пояс при получении сегодняшней даты. Очень распространенная ошибка - пропуск часового пояса. Если не указан, текущий часовой пояс JVM по умолчанию будет применяться неявно. Это означает, что ваши результаты могут отличаться в зависимости от машины или настроек администратора. Хуже того, любой код в любом потоке любого приложения в этой JVM может вызвать изменение часового пояса по умолчанию в любой момент во время выполнения , пока ваше приложение выполняет ! Поэтому всегда указывайте, а не полагайтесь неявно на текущее значение по умолчанию.
LocalDate today = LocalDate.now( zoneId ); // We want a ZonedDateTime, but starting with a LocalDate in order to get first moment of the day (see next line).
ZonedDateTime todayStart = today.atStartOfDay( zoneId ); // Set time-of-day to first moment of this date, just to be neat. Usually that time is '00:00:00.0' but not always.
Среда java.time включает несколько удобных TemporalAdjustors для получения первого дня года, а оттуда - первого воскресенья этого месяца.
ZonedDateTime firstOfThisYear = todayStart.with( TemporalAdjusters.firstDayOfYear( ) );
ZonedDateTime zdtFirstOfNextYear = firstOfThisYear.with( TemporalAdjusters.firstDayOfNextYear( ) );
ZonedDateTime firstSundayOfThisYear = firstOfThisYear.with( TemporalAdjusters.dayOfWeekInMonth( 1, DayOfWeek.SUNDAY ) );
Теперь мы настроены на цикл по всем неделям года. Мы увеличиваем неделю, пока не окажемся в следующем году. Мы собираем каждое воскресенье в List
.
ZonedDateTime zdt = firstSundayOfThisYear; // Var changing throughout loop.
List< ZonedDateTime > sundays = new ArrayList<>( 53 ); // Set initial capacity to maximum number of values.
while ( zdt.isBefore( zdtFirstOfNextYear ) ) {
// Handle this iteration.
sundays.add( zdt );
System.out.println( "Sunday # " + sundays.size( ) + " : " + zdt );
// Prepare next iteration.
zdt = zdt.plusWeeks( 1 );
}
При запуске.
Sunday # 1 : 2015-01-04T00:00-05:00[America/Montreal]
Sunday # 2 : 2015-01-11T00:00-05:00[America/Montreal]
…
Sunday # 51 : 2015-12-20T00:00-05:00[America/Montreal]
Sunday # 52 : 2015-12-27T00:00-05:00[America/Montreal]