Dates with no time or timezone component in Java/MySQL
Даты без компонента времени или часового пояса в Java / MySQL
Мне нужно иметь возможность хранить дату (год / месяц / день) без компонента времени. Это абстрактное понятие даты, такое как день рождения - мне нужно представить дату в году, а не конкретный момент времени.
Я использую Java для анализа даты из некоторого входного текста, и мне нужно сохранить ее в базе данных MySQL. Независимо от того, в каком часовом поясе находится база данных, приложение или любой клиент, все они должны видеть один и тот же год / месяц / день.
Мое приложение будет работать на компьютере с системным часовым поясом, отличным от системного часового пояса сервера базы данных, и я не могу контролировать ни то, ни другое. Есть ли у кого-нибудь элегантное решение для обеспечения правильного сохранения даты?
Я могу придумать эти решения, ни одно из которых не кажется очень приятным:
Запросите у моего соединения MySQL его часовой пояс и проанализируйте входную дату в этом часовом поясе
Полностью обработайте дату в виде строки гггг-ММ-дд
Переведено автоматически
Ответ 1
java.time
Это действительно было проблемой с java.util API даты и времени, пока JSR-310 не был включен в Java SE 8. java.util.Date Объект не является реальным объектом даты и времени, как современные типы даты и времени; скорее, он представляет количество миллисекунд, прошедших со стандартного базового времени, известного как "эпоха", а именно January 1, 1970, 00:00:00 GMT (или UTC). Когда вы печатаете объект из java.util.Date, его toString метод возвращает дату-время в часовом поясе JVM, вычисленное на основе этого значения в миллисекундах.
Например, вы могли бы использовать объект LocalDate для представления даты рождения, потому что большинство людей отмечают свой день рождения в один и тот же день, независимо от того, находятся ли они в своем городе рождения или по всему миру по другую сторону международной линии дат.
LocalDate представляет год, месяц, день в календаре ISO и полезен для представления даты без времени. Вы можете использовать LocalDate для отслеживания важного события, такого как дата рождения или свадьбы.
Для какого типа данных мне следует использовать LocalDate?
Он сопоставляется с DATE типом ANSI SQL. Сопоставление типов ANSI SQL с java.time типами было показано следующим образом в этой статье Oracle:
ANSI SQL
Java SE 8
Дата
LocalDate
ВРЕМЯ
LocalTime
ВРЕМЕННАЯ МЕТКА
LocalDateTime
ВРЕМЯ С ЧАСОВЫМ ПОЯСОМ
OffsetTime
ВРЕМЕННАЯ МЕТКА С ЧАСОВЫМ ПОЯСОМ
OffsetDateTime
Как использовать это в JDBC?
Ниже приведен пример кода для вставки LocalDate в columnfoo (который имеет DATE тип):
Ниже приведен пример кода для извлечения LocalDate из columnfoo:
Statementst= conn.createStatement(); ResultSetrs= st.executeQuery("SELECT * FROM mytable WHERE <some condition>"); while (rs.next()) { // Assuming the column index of columnfoo is 1 LocalDatelocalDate= rs.getObject(1, LocalDate.class)); System.out.println(localDate); } rs.close(); st.close();
Вы могли бы обнулить все данные о времени / часовом поясе:
publicstatic Date truncateDate(Date date) { GregorianCalendar cal = getGregorianCalendar(); cal.set(Calendar.ZONE_OFFSET, 0); // UTC cal.set(Calendar.DST_OFFSET, 0); // We don't want DST to get in the way.
Я пришел к выводу, что лучшим способом в моем текущем приложении (простой утилите, использующей jdbc напрямую) было вставить непосредственно в виде строки. Для приложения Hibernate большего размера я мог бы написать свой собственный пользовательский тип. Не могу поверить, что кто-то еще не решил эту проблему в каком-нибудь общедоступном коде...
Ответ 4
Не могли бы вы просто использовать тип MySQL DATE в своей таблице, а затем, по сути, использовать форматированную строку в вашем операторе insert? Я думаю, что что-то подобное позволит избежать каких-либо корректировок часового пояса.