Как бы вы представили дату рождения в своей модели java?

и подождите, не спешите отвечать " java.утиль.Дата", рассмотрим следующий сценарий.

объект Person, имеющий 2 поля:" день рождения "и" nextMeeting " оба java.утиль.Дата. Теперь день рождения хранится в базе данных как столбец типа даты (нет времени), например. 01-10-1979, и nextMeeting как тип datetime для ex. 01-10-2010 20:00:00.

вы вытащите его из БД, "день рождения" будет автоматически установлен в полночь JDBC. Теперь вам нужно отправить этот объект в другой JVM, используя, скажем, RMI или любой технологии.

на другом конце JVM имеет часовой пояс-1h от исходного JVM. Здесь начинается проблема. nextMeeting стал 01-10-2010 19: 00: 00, что абсолютно нормально и правильно с точки зрения пользователя и т. д...

но день рождения станет 30-09-1979 23: 00: 00, который будет представлен пользователю как 30 сентября, что на самом деле не то, что мы хотим, потому что, очевидно, день рождения-это что-то статическое и не зависит от часовых поясов.

So тип столбца в db правильно выбрана (дата). Этот тип столбца обычно представлен как java.утиль.Дата. Но в нашем случае это неправильный тип java для использования.

Итак, как бы вы представляли день рождения? Учтите,что вам нужно манипулировать этим объектом в пользовательском интерфейсе, как в компоненте datepicker и т. д...

6 ответов


использовать LocalDate С JodaTime и хранить только дату рождения, а не время.


в других ответах используются устаревшие классы.

java.время

как Joda-Time, так и старая java.утиль.Дата./Классы календаря были заменены java.время фреймворк, встроенный в Java 8 и более поздние версии. Определяется JSR 310. Расширено ThreeTen-Extra. Обратно портирован на Java 6 & 7 с помощью ThreeTen-BackPort проект, который обернут для Android с помощью ThreeTenABP проект.

LocalDate

значение только даты без времени суток и без часового пояса может быть представлено LocalDate класса. Такой класс отсутствовал в старых классах даты и времени в комплекте с самыми ранними версиями Java. Старый java.sql.Date класс притворяется только датой, но на самом деле имеет время суток, унаследованное от java.util.Date (значение даты и времени).

LocalDate dateOfBirth = LocalDate.new( 1979 , 1 , 10 );

без времени суток и часового пояса дата рождения по своей сути неточно для определения возраста. Но почти во всех случаях использования мы не заботимся; дайте-или-возьмите часть дня достаточно близко.

ZonedDateTime

для встречи мы не можем быть такими расслабленными. Нам нужна дата, время и часовой пояс. в Java.время, которое означает ZonedDateTime класса. The часовой пояс является ключевым элементом отсутствует в сценарии в вопросе. Добавьте часовой пояс, и все будет хорошо.

ZoneId zoneIdMontreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtMontreal = ZonedDateTime.of( 2010 , 1 , 10 , 20 , 0 , 0 , zoneIdMontreal );

теперь общаться в другое машина. Оба остаются нетронутыми, одна и та же дата-только для даты рождения (1979-01-10) и одна и та же Монреальская дата-время встречи.

настройка часового пояса

затем вы можете настроить эту встречу на другой часовой пояс, ожидаемый человеком, использующим эту другую машину.

ZoneId zoneIdParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdtMontreal.withZone( zoneIdParis );

у нас есть один и тот же момент на временной шкале, представленной в двух модах, в двух объектах, zdtMontreal & zdtParis.

LocalDateTime

если ваш nextMeeting не имеет часового пояса или смещения от-UTC информации, а затем представляют как вызов setDate и setTimestamp на PreparedStatement.

идя в другом направлении, от базы данных к Java, вызовите getDate и getTimestamp на ResultSet. Затем немедленно перевести на java.типы времени, избегая использования java.типы sql в бизнес-логике.

для значения даты-времени мы должны пройти через Instant объект. The Instant момент на временной шкале в UTC. Мы применяем часовой пояс, чтобы получить времени для пользователей.

LocalDate dateOfBirth = mySqlDate.toLocalDate();
Instant instant = mySqlTimestamp.toInstant();
ZonedDateTime zdtMontreal = ZonedDateTime.ofInstant( instant , zoneIdMontreal );

для манипуляции я посоветую java.утиль.Календарь

для представления интересов

день рождения как java.утиль.Дата
NextMeetin как java.язык SQL.Метка


каким-то образом две системы java должны будут согласовать информацию о календаре/часовом поясе, или объект Date должен будет быть преобразован в метку времени при передаче в удаленную систему.

самый простой метод может заключаться в том, чтобы просто потребовать от всех клиентов рассматривать День рождения как время GMT - - - когда они отображают/сравнивают / независимо от дней рождения, попросите их создать Calendar с "GMT" TimeZone, а потом setTime() на нем с помощью прилагаемого Date.

если вы работая с моделью локально, вы должны иметь объект Date, а не только временную метку.


Это очень хороший вопрос...

Android, например, хранит день рождения как строку в формате "гггг-ММ-ДД". Мне было интересно, почему они не используют Java.утиль.Дата и я предполагаю, что причиной будет та же проблема, которую вы принесли сюда.

поэтому я бы рекомендовал либо строку, либо некоторую "независимую от часового пояса дату". Но после нескольких минут поиска в документации Java и joda-time я понятия не имею, как это сделать.

EDIT: кажется, @Jeroen прав-используйте LocalDate.


Если вы имеете дело с датами, лучше использовать Джода времени. Вы можете построить DateTime объект с информацией о дате / времени и часовом поясе, чтобы у вас была вся информация, необходимая для работы с различными часовыми поясами.