val date: java.sql.Date = ???
val month = date.toLocalDate().getMonthValue()
Вы сами это сказали, и я все еще думаю: вам следует использовать java .time, современный Java API даты и времени. Когда вы получаете старомодный java.sql.Date
из устаревшего API, еще не обновленного до java .time, преобразуйте его в современный LocalDate
и наслаждайтесь написанием естественного кода с java .time.
Почему были объявлены устаревшими getMonth () и другие методы getXxx?
Хотя Майкл уже ответил на вопрос относительно java.util.Date
, мне есть что добавить, когда дело доходит до java.sql.Date
. Для этого класса ситуация несколько хуже, чем то, о чем сообщил Майкл.
Что осталось нерекомендованным (оцененным?) Из java.util.Date
после устаревания, так это то, что Date
- это момент времени. С другой стороны, java.sql.Date
никогда не должен был быть моментом во времени. Один из способов проиллюстрировать этот факт состоит в том, что его метод toInstant
, который должен преобразовать его в Instant
, момент времени, безоговорочно выдает UnsupportedOperationException
. java.sql.Date
должен был быть календарной датой, которая будет использоваться с базой данных SQL и ее типом данных date
, который в большинстве случаев также является датой, определяемой годом, месяцем и днем месяца. Поскольку Date
больше не является годом, месяцем и днем месяца, они практически устарели все, что java.sql.Date
должно было быть . И они не дали нам замену, пока с JDB C 4.2 мы не сможем обменивать LocalDate
объектов с SQL базами данных.
Наблюдения, которые приводят к устареванию, имеют очень практические последствия. Давайте попробуем это (в Java, потому что это то, что я могу написать):
void foo(java.sql.Date sqlDate) {
System.out.println(sqlDate);
TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Pacific/Samoa")));
System.out.println(sqlDate.getMonth());
}
За один вызов напечатанный метод:
2020-11-02
9
Итак, мы был 2-й день 11-го месяца, а месяц печатался как 9? Происходят две вещи:
- Как ни странно, номер месяца, который возвращает
getMonth()
, отсчитывается от 0, поэтому 9 означает октябрь. Date
внутренне представлено как количество миллисекунд с начала эпохи до начала дня в часовом поясе JVM по умолчанию. 2020-11-02 00:00:00 в моем исходном часовом поясе (для этой демонстрации установлен Тихий океан / Киритимати) - это тот же момент времени, что и 23:00:00 31.10.2020 в Самоа. Таким образом, мы получаем октябрь.
Вам не нужно самостоятельно менять часовой пояс, чтобы это произошло. Ситуации, в которых это может произойти, включают:
- Часовой пояс JVM по умолчанию можно изменить из любой части вашей программы и из любой другой программы, работающей в той же JVM.
- date может быть сериализован в программе, запущенной в одной JVM, и десериализован в другой JVM с другой настройкой часового пояса.
Кстати, первый фрагмент, который я представил вверху, часто не помогает против неожиданных результатов в этих ситуациях. Если что-то go сбилось с пути до того, как вы преобразовали из java.sql.Date
в LocalDate
, преобразование также даст вам неправильную дату. Если вы можете это сделать, конвертируйте в LocalDate
, прежде чем кто-нибудь испортит настройку часового пояса JVM, и будьте осторожны.