Класс LocalDate в Java: методы и примеры - Вопросы
Всего: 5 вопросов
1. Как создать объект LocalDate в Java?
Как создать объект LocalDate в Java?
Публичного конструктора у LocalDate нет — объект создаётся статическими фабричными методами:
LocalDate.of(2024, 3, 15)илиLocalDate.of(2024, Month.MARCH, 15)— конкретная дата (месяцы нумеруются с 1);LocalDate.now()— текущая дата в зоне JVM по умолчанию,LocalDate.now(ZoneId.of("Asia/Tokyo"))— в указанной зоне;LocalDate.parse("2024-03-15")— разбор строки в формате ISO-8601yyyy-MM-dd;LocalDate.ofYearDay(2001, 32)(2001-02-01) иLocalDate.ofEpochDay(0)(1970-01-01).
Несуществующая дата не «перетекает» на следующий месяц: LocalDate.of(2023, 2, 29) выбрасывает DateTimeException, а LocalDate.parse("2023-1-5") — DateTimeParseException.
2. Почему после вызова date.plusDays(1); значение date не меняется?
Почему после вызова date.plusDays(1); значение date не меняется?
LocalDate неизменяем. Методы plus...(), minus...() и with...() не меняют объект, а возвращают новую дату. Если результат не присвоить, он теряется:
date.plusDays(1); // результат потерян
date = date.plusDays(1); // правильно
Благодаря неизменяемости LocalDate потокобезопасен: один объект можно использовать из нескольких потоков без синхронизации и хранить в static final поле.
3. Как сравнить две даты LocalDate и почему нельзя использовать ==?
Как сравнить две даты LocalDate и почему нельзя использовать ==?
Для сравнения служат методы isBefore(), isAfter() и isEqual(), которые возвращают boolean; на равенство можно проверять и через equals(). Оператор == сравнивает ссылки, а не значения, поэтому для двух разных объектов с одинаковой датой обычно даёт false.
Для сортировки используется compareTo() (LocalDate реализует Comparable). Он возвращает не строго -1/0/1, а разницу: LocalDate.of(2001, 1, 1).compareTo(LocalDate.of(2005, 6, 1)) вернёт -4. Поэтому результат сравнивают с нулём (< 0, > 0), а не с -1.
4. Как посчитать количество дней между двумя датами LocalDate?
Как посчитать количество дней между двумя датами LocalDate?
Используйте ChronoUnit.DAYS.between(start, end) или эквивалентный start.until(end, ChronoUnit.DAYS):
LocalDate start = LocalDate.of(2001, 1, 1);
LocalDate end = LocalDate.of(2001, 3, 1);
ChronoUnit.DAYS.between(start, end); // 59
ChronoUnit.DAYS.between(end, start); // -59
Результат имеет тип long, конечная дата в подсчёт не входит, а если конец раньше начала, число отрицательное. Аналогично считаются месяцы и годы: ChronoUnit.MONTHS.between(start, end) вернёт 2.
5. Как конвертировать LocalDate в java.util.Date и java.sql.Date и обратно?
Как конвертировать LocalDate в java.util.Date и java.sql.Date и обратно?
java.util.Date — момент времени, а у LocalDate нет ни времени, ни зоны, поэтому при конвертации нужно выбрать зону:
ZoneId zone = ZoneId.systemDefault();
Date utilDate = Date.from(localDate.atStartOfDay(zone).toInstant()); // полночь в зоне zone
LocalDate back = utilDate.toInstant().atZone(zone).toLocalDate();
С java.sql.Date зона не нужна: java.sql.Date.valueOf(localDate) и sqlDate.toLocalDate(). Метод sqlDate.toInstant() выбрасывает UnsupportedOperationException. Конвертируйте туда и обратно с одной и той же ZoneId, иначе дата может сдвинуться на день.