Postgres
В Postgres, когда вы имеете в виду 9 AM везде или 9 AM где-либо, на определенную дату, используйте тип данных столбца TIMESTAMP WITHOUT TIME ZONE
.Любой часовой пояс или смещение от UTC, включенное во вход, игнорируется, а дата и время дня принимаются как есть (без регулировки) и сохраняются.В этом типе данных намеренно отсутствует какое-либо понятие часовой пояс или смещение от UTC .
Для времени суток без даты используйте данные TIME WITHOUT TIME ZONE
тип.Postgres также предлагает TIME WITH TIME ZONE
только потому, что это требуется спецификацией SQL;этот тип WITH
не имеет смысла и никогда не должен использоваться.
Postgres - отличный выбор для такого проекта, поскольку он предлагает отличную поддержку даты и времени как в его типах данных , так и в его функциях .Базы данных сильно различаются по своим функциям даты и времени.
Java
В бэкэнде Java используйте только современные java.time классы.Эти годы назад вытеснили ужасные старые классы даты и времени в комплекте с самыми ранними версиями Java.
Если вы еще не используете Java 8 или более позднюю версию, найдите почти все те же функции в обратном порте Java 6 & 7 в проекте ThreeTen-Backport .Стоит того, чтобы добавить эту библиотеку в ваш проект.От тех же самых замечательных людей, которые принесли вам классы java.time и проект Joda-Time, все под руководством одного и того же человека Стивена Колебурна.
LocalDateTime
В java.time используйте класс LocalDateTime
для случаев, когда вы имеете в виду 9 утра где угодно / везде на определенную дату.Как и TIMESTAMP WITHOUT TIME ZONE
в Postgres, в этом классе намеренно отсутствует какое-либо понятие зоны или смещения.
LocalDateTime ldt = LocalDateTime.of( 2018 , 1 , 23 , 15 , 0 , 0 , 0 ) ; // 3 PM on 23rd of January this year.
LocalTime
Если вы имеете в виду только время дня, без датыиспользуйте класс LocalTime
.
LocalTime lt = LocalTime.of( 15 , 0 ) ; // 3 PM.
JDBC
Начиная с JDBC 4.2 и более поздних версий вы можете обмениваться объектами java.time с базой данных через getObject
и setObject
методы.
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
Если ваши драйверы JDBC еще не обновлены до 4.2, вернитесь к ужасным старым классам прежних версий, но немедленно преобразуйте в классы java.time .
Учитывая, что у унаследованных классов отсутствует класс для даты плюс время суток без часового пояса, мы должны подделать его.Используйте java.sql.Timestamp
, который представляет момент в UTC с разрешением наносекунд, и просто игнорируйте тот факт, что он находится в UTC.
java.sql.Timestamp ts = myResultSet.getTimestamp( … ) ;
Для Java 8 и более поздних версий выполните преобразование с использованиемновые методы добавлены к старым классам.Сначала преобразуйте в java.time.Instant
, который также представляет момент в UTC с разрешением наносекунд.Затем преобразуйте в LocalDateTime
, эффективно удалив понятие UTC.
Instant instant = ts.toInstant() ; // Convert from legacy class to modern one.
LocalDateTime ldt = LocalDateTime.ofInstant( instant , ZoneOffset.UTC ) ; // Remove the concept of UTC (or any other offset or zone) from our data.
Для Java 6 и 7 с использованием библиотеки ThreeTen-Backport используйтеметоды преобразования в их полезности DateTimeUtils
class.
org.threeten.bp.Instant instant = org.threeten.bp.DateTimeUtils.toInstant( ts ) ; // Convert from legacy class to modern.
org.threeten.bp.LocalDateTime ldt = LocalDateTime.ofInstant( instant , ZoneOffset.UTC ) ; // Remove the concept of UTC (or any other offset or zone) from our data.
ZonedDateTime
Классы Local…
по определению не имеют реального значения, пока вы не поместите их вконтекст часового пояса.LocalDateTime
- это , а не момент, не представляет точку на временной шкале.
Укажите собственное имя часового пояса вформат continent/region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
.Никогда не используйте 2-4-буквенное сокращение, такое как PST
или BST
или EST
или IST
, поскольку они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).
LocalDateTime ldt =
LocalDateTime.of(
LocalDate.of( 2018 , Month.January , 23 ) ,
LocalTime.of( 9 , 0 )
)
;
ZoneId zLosAngeles = ZoneId.of( "America/Los_Angeles" ) ; // Seattle time zone.
ZonedDateTime zdtSeattle = ldt.atZone( zLosAngeles ) ;
ZoneId zChicago = ZoneId.of( "America/Chicago" ) ;
ZonedDateTime zdtChicago = ldt.atZone( zChicago ) ;
ZoneId zLondon = ZoneId.of( "Europe/London" ) ;
ZonedDateTime zdtLondon = ldt.atZone( zLondon ) ;
Там у нас есть три ZonedDateTime
объекта: zdtSeattle
, zdtChicago
и zdtLondon
.Это все 9 утра 23 января в начале этого года.Поймите, что это три совершенно разных момента, каждый на несколько часов раньше, когда вы идете на восток.У них у всех одинаковое время на настенных часах (9 утра 23 числа), но они представляют собой три разные точки на временной шкале.
JavaScript
Хотя я недостаточно хорошо знаю JavaScript, чтобы сказать наверняка,Я сомневаюсь, что у вас есть какая-нибудь библиотека для работы с датой и временем.Платформа java.time является ведущей в отрасли.
Что касается разработки пользовательского интерфейса веб-клиента, я использую Vaadin , так что это не проблема: чистая Java на внутреннем сервере автоматически генерирует HTML / CSS / DOM / JavaScript, необходимый длявеб-браузер.
найти способ захвата местного времени в JavaScript
Что касается определения текущего часового пояса по умолчанию на клиентском компьютере, я не эксперт,но, насколько я помню, браузеры не возвращают именованный часовой пояс, только смещение от UTC.См. Ответ Мэтта Джонсона для возможного решения.В конечном счете, в любом приложении (на рабочем столе или в Интернете), если необходим правильный часовой пояс, вы должны попросить или подтвердить желаемый / ожидаемый часовой пояс с пользователем .И может быть целесообразно всегда указывать где-нибудь в вашем пользовательском интерфейсе, какой часовой пояс используется вашим приложением.
Если вам нужно обмениваться значениями даты и времени между вашим бэкэндом Java и кодом JavaScript в front-end, у вас есть два варианта выбора:
- ISO 8601
- Count-from-epoch
ISO 8601
Стандарт ISO 8601 определяет множество текстовых форматов для обмена значениями даты и времени.Они продуманно разработаны, чтобы избежать двусмысленности.Их легко разобрать на машине и легко прочитать людям в разных культурах.
Классы java.time по умолчанию используют эти форматы при генерации / разборе строк.
Count-from-Epoch
Я не рекомендую этот подход, так как он запутанный и подвержен ошибкам, подвержен неоднозначности и неверным предположениям между людьми и библиотеками, которые отправляют или получают.
Ссылочная дата эпохи - это точка времени, используемая в качестве базовой линии.Тогда некоторый отсчет вперед или назад делается с некоторой гранулярностью.
Одна большая проблема заключается в том, что десятков ссылок эпохи используются различными системами.Классы java.time по умолчанию используют эпоху Unix первого момента 1970 года в UTC, 1970-01-01T00: 00Z.
Другая проблема заключается в том, что существует множество гранулярностей, таких как целые секунды, миллисекунды, микросекунды и наносекунды.Программисты должны четко задокументировать / сообщить, какая гранулярность находится в игре.
Если бы вы отправляли свои три момента открытия для ваших трех магазинов в JavaScript в качестве отсчета времени, вы бы отправляли три разных числа.
long millisecondsSeattle = zdtSeattle.toInstant().toEpochMilli() ;
long millisecondsChicago = zdtChicago.toInstant().toEpochMilli() ;
long millisecondsLondon = zdtLondon.toInstant().toEpochMilli() ;
В результате получается три разных числа для трех разных моментов.
О java.time
java.time Framework встроен в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .
Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .
Вы можете обмениваться java.time объектами непосредственно с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
и more .