Часовой пояс
Ваш код и другие ответы не учитывают часовой пояс аномалий.Если вы отслеживаете фактические моменты, когда люди фактически припарковались, в отличие от теоретических 24-часовых дней, вы должны учитывать такие аномалии, как летнее время (DST).Политики всего мира продемонстрировали склонность к пересмотру часового пояса в своей юрисдикции.Таким образом, дни могут быть любой длины, например, 25 часов, 23 часа, 23,5 часа, 24,25 или другие.
Часовой пояс - это история прошлых, настоящих и будущих изменений в offset-from-UTC , используемых людьми определенного региона.
Класс LocalDateTime
совершенно не подходит для этой цели.Этот класс намеренно не имеет понятия о часовом поясе или смещении от UTC.Вы можете использовать его как часть строительного блока в своем коде, но ему нужно присвоить ZoneId
для определения фактического момента с помощью класса ZonedDateTime
.
ZoneId
Укажитеваш часовой пояс.
Если часовой пояс не указан, JVM неявно применяет свой текущий часовой пояс по умолчанию.Это значение по умолчанию может измениться в любой момент во время выполнения (!), Поэтому ваши результаты могут отличаться.Лучше явно указать желаемый / ожидаемый часовой пояс в качестве аргумента.Если критично, подтвердите зону с вашим пользователем.
Укажите правильное имя часового пояса в формате Continent/Region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
,Никогда не используйте 2-4 буквенные сокращения, такие как EST
или IST
, так как они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
Если вы хотите использовать текущий часовой пояс JVM по умолчанию, запросите его и передайте в качестве аргумента.Если опущен, код становится неоднозначным для чтения, поскольку мы точно не знаем, намеревались ли вы использовать значение по умолчанию или если вы, как и многие программисты, не знали о проблеме.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Дата сборки, время и зона для определения момента
Соберите дату и время суток.
LocalDate startDate = LocalDate.of( 2019 , 1 , 23 ) ; // 23rd of January in 2019.
LocalTime startTime = LocalTime.of( 18 , 50 ) ; // 6:50 PM.
ZonedDateTime startMoment = ZonedDateTime.of( startDate , startTime , z ) ;
LocalDate stopDate = LocalDate.of( 2019 , 1 , 23 ) ; // 23rd of January in 2019.
LocalTime stopTime = LocalTime.of( 20 , 50 ) ; // Two hours later, exactly — maybe! Depends on any anomalies at that time in that zone.
ZonedDateTime stopMoment = ZonedDateTime.of( stopDate , stopTime , z ) ;
➥ Обратите внимание, что в этом примере мы можем иметьпромежуток времени ровно 2 часа, но может и не .Это может быть 3 часа или какой-то другой промежуток времени, в зависимости от аномалий, запланированных на эту дату в это время в этой зоне.
Истекшее время
Чтобы рассчитать истекшее время, это сроки дней (24-часы времени, не связанные с календарем), часы, минуты и секунды, используйте Duration
.(Для года-месяца-дня используйте Period
.)
Duration d = Duration.between( startMoment , stopMoment ) ;
Опрос за весь промежуток времени в единицах целых часов.
long hours = d.toHours() ; // Entire duration as count of whole hours.
Half-Open
Во включенном пастбине время запуска 18:50 и время окончания 20:49.Если мы введем эти данные, на выходе должно быть 2 начальных дня.Теперь, если минута совпадает, она не считается начальным часом.Но если мы изменим ввод на 20:51, то начнется еще один час, поэтому DayHoursTotal должен быть равен 3.
Этот подход известен как Half-Open , когда начало включительно , а окончание эксклюзивно .Это обычно используется при обработке даты и времени.Классы Duration
и Period
применяют этот подход.
Но будьте осторожны, сопоставляя только номер минуты.Ваши объекты даты и времени могут содержать секунды и / или доли секунды, что отбросит ваш алгоритм.Как правило, обрезайте ваши объекты даты и времени явно, если есть какая-либо вероятность меньшей детализации, чем вы хотите.Например, ZonedDateTime.truncatedTo
.
Изменение курса
Очевидно, что изменение курса усложняет ситуацию.Другие ответы, кажется, охватили это, поэтому я не буду повторяться.Но я могу добавить большой совет: см. ThreeTen-Extra для его классов Interval
и LocalDateRange
, которые могут быть вам полезны.Они включают удобные методы сравнения перекрытий, содержаний, примыканий и т. Д.