Группировка длинных дат UTC по дням
Вопрос
Есть ли разумный способ сгруппировать длинные даты UTC по дням?
Я бы изменил их на 86400, но это не учитывает високосные секунды.
У кого-нибудь есть какие-либо другие идеи, я использую java, чтобы я мог разобрать их в объекты Date, но меня немного беспокоят накладные расходы на производительность при использовании класса date.
Также есть ли более эффективный способ, чем сравнение частей года, месяца и дня объекта Date?
Решение
Соответствуют ли ваши исходные данные определенно включить для начала високосные секунды?Некоторые API поддерживают, а некоторые нет - время Joda (что я бы рекомендовал по сравнению со встроенными API даты / времени) не использует високосные секунды, например.API-интерфейсы даты и времени Java "иногда" работают - они поддерживают 60 и 61 как значения "секунда в минуту", но поддержка зависит от операционной системы (см. Ниже).Если у вас есть несколько хороших выборочных значений, я бы на вашем месте сначала проверил это.Очевидно, что просто разделить гораздо проще, чем что-либо еще.
Если вы делай нужно создать Date
объекты (или DateTime
в Joda) Я бы сравнил это, прежде чем делать что-либо еще.Вы вполне можете обнаружить, что производительность на самом деле совершенно адекватна.Нет смысла тратить время на оптимизацию чего-то, что подходит для ваших данных.Конечно, вам нужно будет решить, какой размер данных вам необходимо поддерживать, и насколько быстрым это должно быть в первую очередь :)
Даже тот java.util.Date
поддержка високосных секунд несколько неопределенна.От документы:
Хотя класс Date предназначен для того, чтобы отражать всемирное координированное время (UTC), он может делать это не совсем точно, в зависимости от среды хоста виртуальной машины Java.Почти все современные операционные системы предполагают, что 1 день = 24 × 60 × 60 = 86400 секунд во всех случаях.В UTC, однако, примерно раз каждый год или два появляется дополнительная секунда, называемая "високосной секундой". Високосная секунда всегда добавляется как последняя секунда дня и всегда включена 31 декабря или 30 июня.Например, последняя минута 1995 года длилась 61 секунду, благодаря добавленной високосной секунде.Большинство компьютерных часов недостаточно точны, чтобы быть в состоянии отразить разницу в високосной секунде.
Там есть довольно хороший пост в блоге о неразберихе с Java и високосными секундами, которые вы, возможно, тоже захотите прочитать.
Другие советы
Я бы изменил их на 86400, но это не учитывает високосные секунды....
Я почти уверен, что это будет прекрасно.Документация API для Date
на самом деле не следует включать ничего о високосных секундах, потому что факт заключается в том, что он эмулирует стандартный тикер времени Unix, который НЕ включает високосные секунды в свое значение.Вместо этого он делает 59-ю секунду, которая длится две секунды, устанавливая значение тикера обратно на 1 секунду в начале високосной секунды (как описано по ссылке в предыдущем посте).
Следовательно, вы можете предположить, что значение, которое вы получаете от Date.getTime()
Состоит всего из 86400 секундных дней.Если вам действительно нужно знать, является ли конкретный у дня была високосная секунда, в Интернете доступно несколько таблиц (с 1972 года их было всего 23-24, и компьютерные даты до этого все равно редко учитывали их).
ПРИВЕТ
Уинстон
tl; dr
Instant.ofEpochSecond( 1_493_367_302L ) // Convert a count of whole seconds from epoch of 1970 into a date-time value in UTC.
.atZone( ZoneId.of( "Pacific/Auckland" ) ) // Adjust into the time zone as a context for determining a date.
.toLocalDate() // Extract a date-only value by which we can sort/collect/organize our date-time values.
Часовой пояс
В java.util.Date
класс представляет момент на временной шкале в UTC.Таким образом, запрашивая у него дату, вы получаете дату, которая имеет смысл только в UTC.Этим же моментом может быть более раннее свидание в Квебеке или более позднее свидание в Окленде, Новая Зеландия.
Часовой пояс имеет решающее значение при определении даты, и ваш вопрос игнорирует эту проблему.
Использование java.time
В java.util.Date
class является частью проблемных старых классов date-time, которые теперь являются устаревшими, вытесненными классами java.time.
Что касается високосных секунд, как предполагали другие ответы, большинство источников count-from-epoch делают не считайте високосные секунды.Так что проверьте свой источник.
Если у вас есть отсчет целых секунд от эпохи 1970-01-01T00:00:00
, затем используйте статический метод для создания Instant
объект.
Instant instant = Instant.ofEpochSecond( 1_493_367_302L ) ;
мгновенный.toString():2017-04-28T08:15:02Z
Назначьте часовой пояс, чтобы создать контекст, в котором мы можем определить дату.Для любого данного момента дата варьируется по всему миру в зависимости от зоны.
Укажите a правильное название часового пояса в формате continent/region
, такие как America/Montreal
, Africa/Casablanca
, или Pacific/Auckland
.Никогда не используйте аббревиатуру из 3-4 букв , такую как EST
или IST
такими, какие они есть не настоящие часовые пояса, не стандартизированные и даже не уникальные (!).
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
здт.toString():2017-04-28T01:15:02-07:00[Америка/Los_Angeles]
С кучей таких ZonedDateDate
объекты, которые вы можете сравнить по дате.Вы можете извлечь LocalDate
объект.В LocalDate
класс представляет значение только для даты без указания времени суток и часового пояса.
LocalDate ld = zdt.toLocalDate();
ld.toString():2017-04-28
Таким образом, вы могли бы сделать Map
с LocalDate
в качестве ключа и List
или Set
из ZonedDateTime
объекты в качестве значения.И с современным лямбда-синтаксисом вы могли бы использовать Streams для выполнения этого сопоставления.
О java.time
В java.время фреймворк встроен в Java 8 и более поздние версии.Эти классы вытесняют неприятные старые наследие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
В Джода-Время проект, теперь в режим технического обслуживания, советует перейти на java.время классы.
Чтобы узнать больше, смотрите Учебное пособие по Oracle.И найдите Stack Overflow для множества примеров и объяснений.Спецификация является JSR 310.
Где получить классы java.time?
- Java SE 8, Java SE 9, и позже
- Встроенный.
- Часть стандартного Java API со встроенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Java SE 6 и Java SE 7
- Большая часть функциональности java.time обратно перенесена на Java 6 и 7 в ThreeTen-Задний порт.
- Android
- В Тритенабп проект адаптируется ThreeTen-Задний порт (упомянутый выше) специально для Android.
- Видишь Как использовать ThreeTenABP….
В Три дня-Дополнительно проект расширяет java.time дополнительными классами.Этот проект является испытательным полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
, и Еще.