Интересно, почему учителя все еще преподают старый API (Date
, Calendar
и SimpleDateFormat
), потому что у них есть множество проблем и проблемы дизайна, и они заменяются новыми API. (Кстати, Java 8 была выпущена в 2014 году).
В любом случае, если у вас есть GregorianCalendar
, вы можете преобразовать его в новые классы java.time
и сделать с ними все остальное.
Во-первых, вы можете использовать календарь для создания Instant
:
Instant instant = Instant.ofEpochMilli(calendar.getTimeInMillis());
Единственная проблема заключается в том, что если вы создадите Calendar
и установите день, месяц и год, оно будет иметь текущее время (часы/минуты/секунды), поэтому Instant
выше будет иметь текущее время в формате UTC. Если это нормально, вы можете преобразовать этот момент в свой часовой пояс:
ZoneId zone = ZoneId.of("America/Sao_Paulo");
ZonedDateTime start = instant.atZone(zone);
Я использовал America/Sao_Paulo
, но вы можете изменить его на часовой пояс, подходящий для вашей системы. API использует названия часовых поясов IANA (всегда в формате Region/City
, например America/Sao_Paulo
или Europe/Berlin
). Избегайте использования трехбуквенных сокращений (например, CST
или PST
), поскольку они двусмысленный и нестандартный.
Вы можете получить список доступных часовых поясов (и выбрать тот, который лучше всего подходит для вашей системы), позвонив по номеру ZoneId.getAvailableZoneIds()
. Вы также можете использовать системное значение по умолчанию, если хотите (ZoneId.systemDefault()
), но обратите внимание, что его можно изменить без предварительного уведомления, даже во время выполнения, поэтому всегда лучше указывать, какой часовой пояс вы используете. Если вы хотите работать с датами в формате UTC, вы можете использовать встроенную константу ZoneOffset.UTC
.
Приведенный выше код создаст ZonedDateTime
с датой и временем календаря, скорректированными в соответствии с указанным часовым поясом. Просто напоминаю, что если вы сделаете что-то вроде этого:
Calendar calendar = new GregorianCalendar();
calendar.set(2017, 7, 12);
Дата будет эквивалентна 12 августаth 2017 г. (поскольку месяцы в Calendar
API начинаются с нуля, поэтому 7 месяц – август), а время будет текущим. при создании календаря.
Если вы хотите указать час, у вас есть несколько вариантов его настройки:
// change the hour/minute/second to 10:20:45
start = start.with(LocalTime.of(10, 20, 45));
// change just the hour to 10
start = start.withHour(10);
// set to start of the day
start = start.toLocalDate().atStartOfDay(zone);
При этом вы можете соответствующим образом изменить поля времени (а также даты). Проверьте javadoc и учебник Oracle, чтобы увидеть все доступные варианты. Метод atStartOfDay
лучше, потому что он заботится об изменении летнего времени (в зависимости от перехода на летнее время день может начинаться в 1:00, а не в полночь, и этот метод заботится обо всех деталях).
Если вы не хотите полагаться на Calendar
, вы также можете создать дату напрямую:
// creating August 12th 2017, at 10:00
start = ZonedDateTime.of(2017, 8, 12, 10, 0, 0, 0, zone);
Обратите внимание, что август — это 8-й месяц (одно из лучших и наиболее очевидных улучшений старого API).
Теперь, когда у вас есть начальная дата, вы можете просмотреть весь год и проверить даты в соответствии с вашими правилами. Я использую пример отправки электронной почты каждые 16 дней и приспосабливаюсь к следующему понедельнику, если это выходные:
ZonedDateTime d = start;
// ends in 1 year - this method already takes care of leap years
ZonedDateTime end = start.plusYears(1);
while (end.isAfter(d)) {
d = d.plusDays(16);
if (d.getDayOfWeek() == DayOfWeek.SUNDAY || d.getDayOfWeek() == DayOfWeek.SATURDAY) {
// weekend, adjust to next monday
d = d.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
}
// send email
}
Если вы используете Java ‹= 7, вы можете использовать ThreeTen Backport, отличный вариант для Новые классы даты/времени Java 8.
Единственное отличие от Java 8 — это имена пакетов (в Java 8 — java.time
, а в ThreeTen Backport (или ThreeTenABP для Android) — org.threeten.bp
), но имена классов и методов те же.
Как @BasilBourque напомнил мне в комментариях, вы также можете преобразовать GregorianCalendar
в ZonedDateTime
, используя метод toZonedDateTime()
(при этом будет использоваться часовой пояс календаря - обычно это значение по умолчанию в системе, если вы его не установили). Вы также можете преобразовать его в Instant
, используя метод toInstant()
. Единственное ограничение состоит в том, что эти методы доступны только в Java 8 (поэтому, если вы используете ThreeTen Backport, просто используйте способ, описанный выше).
person
Community
schedule
31.07.2017
java.util.Date
,java.util.Calendar
иjava.text.SimpleTextFormat
теперь являются устаревшими, вытесненными java.time. См. учебник Oracle. - person Basil Bourque   schedule 31.07.2017