Почему в классах Java 8 java.time отсутствует метод getMillis ()?


64

Java 8 имеет совершенно новую библиотеку для дат и времени в пакете java.time, что очень приветствуется для всех, кому раньше приходилось использовать JodaTime или из-за необходимости создавать собственные вспомогательные методы обработки дат. Многие классы в этом пакете представляют временные метки и имеют вспомогательные методы, такие как getHour()получение часов из временной метки, getMinute()получение минут из временной метки, getNano()получение наночастиц из временной метки и т. Д.

Я заметил, что у них нет метода, вызываемого getMillis()для получения миллис метки времени. Вместо этого нужно было бы вызвать метод get(ChronoField.MILLI_OF_SECOND). Мне кажется, что это противоречие в библиотеке. Кто-нибудь знает, почему такой метод отсутствует, или поскольку Java 8 все еще находится в разработке, есть ли вероятность, что он будет добавлен позже?

https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

Определенные здесь классы представляют основные понятия даты и времени, включая моменты времени, длительности, даты, время, часовые пояса и периоды. Они основаны на календарной системе ISO, которая является де-факто мировым календарем, следующим лептическим григорианским правилам. Все классы являются неизменяемыми и потокобезопасными.

Каждый экземпляр даты и времени состоит из полей, которые удобно доступны через API. Для более низкого уровня доступа к полям обратитесь к java.time.temporalпакету. Каждый класс включает в себя поддержку печати и парсинга всевозможных дат и времени. Обратитесь к java.time.formatпакету для настройки параметров ...

Пример такого класса:
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html.

Дата-время без часового пояса в календарной системе ISO-8601, например 2007-12-03T10: 15: 30.

LocalDateTimeявляется неизменным объектом даты-времени, который представляет дату-время, часто рассматриваемый как год-месяц-день-час-минута-секунда. Другие поля даты и времени, такие как день года, день недели и неделя года, также могут быть доступны. Время представляется с точностью до наносекунды. Например, значение «2 октября 2007 в 13: 45.30.123456789» может быть сохранено в LocalDateTime...


Похоже, они хотели использовать полиморфизм для разрешения всех вызываемых методов get(), вместо того, чтобы давать им индивидуальные, уникальные имена. Если это вас беспокоит, напишите класс, который наследует исходный класс, и поместите свой собственный getMillis()метод в новый класс.
Роберт Харви

@RobertHarvey Большинство классов в пакете java.time являются неизменяемыми и не могут быть расширены.
assylias

2
@RobertHarvey Вопрос для меня не в том, как я могу решить это. Это показалось странным несоответствием, и я подумал, есть ли интересное объяснение этому.
Тармо

У меня есть идея, что некоторые архитектуры / ОС не надежно поддерживают миллисекунды. Другими словами, системное время не может быть восстановлено с точностью до миллисекунды, только с точностью до сантисекунды или секунды.
Марко

См. Stackoverflow.com/a/23945792/40064 о том, как это сделать с помощью Instantкласса
Wim Deblauwe

Ответы:


63

JSR-310 основан на наносекундах, а не миллисекундах. Таким образом, минимальный набор разумных методов основан на часах, минутах, секундах и наносекундах. Решение о создании наносекундной базы было одним из первоначальных решений проекта, и я убежден, что это правильно.

Добавление метода для миллиса будет перекрывать метод наносекунды - неочевидный способ. Пользователи должны будут думать о том, было ли нано поле нано секунды или нано милли миллиметров, например. Добавление запутанного дополнительного метода нежелательно, поэтому этот метод был опущен. Как указано, альтернатива get(MILLI_OF_SECOND)доступна.

FWIW, я был бы против добавления getMillis()метода в будущем.


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

12
@ s3ib. Если вы проверите профиль ответчика , вы также заметите, что он является специалистом по спецификации того самого API, о котором вы спрашиваете. Это делает ответ настолько авторитетным, насколько это возможно, не так ли :)
gnat

Таким образом, необходимость в instant.getEpochSecond * 1000 + instant.getNano / 1000000разумных шаблонах для связи с унаследованными (на данный момент, всеми) API-интерфейсами Java, Javascript и т. Д.?
nilskp

10
нет, в этом случае вы можете просто использовать instant.toEpochMilli () download.java.net/jdk8/docs/api/java/time/…
JodaStephen

20

До того, как стать частью openJDK, Threeten был на GitHub, а до этого он был на SourceForge. Тогда Стивен Колебурн, ведущий специалист по спецификации на jsr-310, провел опрос, который все еще можно найти на сайте sourceforge .

The fourth question on the survey covered the method names for LocalTime:
1) getHourOfDay(), getMinuteOfHour(), getSecondOfMinute(), getNanoOfSecond()
2) getHour(), getMinute(), getSecond(), getNanoOfSecond()
3) getHour(), getMinute(), getSecond(), getNano()
4) another idea

только 6,23% выбрали ответ № 4, и среди них примерно 15% попросили ответить getMillis(), т. е. менее 1% от общего числа голосов.

Вероятно, поэтому и не было, getMillisво-первых, и я не смог найти ничего связанного в списке рассылки openjdk, поэтому вопрос, по-видимому, впоследствии не обсуждался.


3
Я думаю, что предоставление людям нескольких вариантов делает более вероятным, что они выбирают один из этих вариантов, даже если их идеальный выбор находится под «другим». Хотя я могу ошибаться.
Аллон Гуралнек

2
@AllonGuralnek Да, определенно - однако компонент миллисекунд был важен в API даты, потому что все было основано на количестве миллисекунд с начала эпохи. В новом API это менее актуально IMO. В большинстве случаев вам нужна либо вторая точность, либо наилучшая доступная точность (нанос). Я могу ошибаться
assylias

1
Похоже, возникает вопрос о наименовании методов, а не о том, какие методы должны существовать.
свик

1
Правильно, извините, мне было непонятно: я имел в виду вопрос из опроса, что он не имеет прямого отношения к этому вопросу.
svick

15

Классы, которые представляют однозначное время UTC (это Instant, OffsetDateTime, ZonedDateTime), имеют два вспомогательных метода для доступа к абсолютному смещению эпохи Java, то есть то, что вы называете «миллисекундным временем» в java.util.Date, которое вы можете использовать чтобы получить в миллисекундах

long getEpochSecond()
int getNano()

1000L*getEpochSecond() + getNano() / 1000000L;

Некоторые причины того, почему это было выбрано вместо того, чтобы long getEpochMillis()обсуждаться в списке рассылки jsr 310 , некоторые из которых я извлек для удобства:

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

...

Чтобы реализовать это, я предпочел бы 64-битные длинные секунды (со знаком) + 32-битные инт наносекунды (без знака).

...

Я предпочитаю разделение на втором уровне, поскольку это официальная единица времени СИ в науке и наиболее универсально согласованный стандарт.

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

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

У меня есть ощущение, что другой причиной было намеренное затруднить преобразование классов java.util.Date в классы JSR310, в надежде, что разработчики попытаются понять различия между различными вариантами, а не просто слепо (неправильно) использовать новые классы.

Относительно того, почему у LocalDateTimeкласса нет этих методов - они не могут существовать там, потому что LocalDateTimeне привязаны к временной шкале UTC, пока вы не решите, в какой зоне вы находитесь или каково ваше смещение UTC, в какой момент вы сами OffsetDateTimeили ZonedDateTime(оба из которых имеют необходимые методы).

В качестве альтернативы, вы можете определить свою собственную LOCAL_EPOCHконстанту 1970-01-01T00:00:00и затем сделать a, MILLIS.between(LOCAL_EPOCH, localTime)чтобы получить некоторую продолжительность в миллисекундах. Это значение, однако, не будет совместимо с каким-либо значением, возвращаемым System.currentTimeMilliseconds()или java.util.Date.getTime(), если, конечно, вы не определите свое местное время как время UTC; но в этом случае вы также можете использовать Instant напрямую или OffsetDateTime с ZoneOffset.UTC.


4
« они не могут существовать там, потому что LocalDateTime не привязан к временной шкале UTC » => LocalDateTime, безусловно, может иметь getMillisметод, который в основном возвращает getNanos()/1e6- тот факт, что это не мгновение во времени, не мешает ему иметь миллисекунду составная часть.
assylias

2
« У меня есть ощущение, что другой причиной было намеренное затруднить преобразование классов java.util.Date в классы JSR310 ». Возможно, это правда, но, к сожалению, «миллис с эпохи» стало почти универсальным представлением времени, поэтому для всего, что нужно чтобы общаться со старыми API Java, Javascript, чем-либо еще, это упущение является настоящей проблемой.
nilskp

Ваш фрагмент кода вверху неверен - вам нужно умножить getEpochSecond на 1000.
Tin Man

@nilskp Это две разные вещи. Вопрос getMillis()задается как в getMillis-of-second; ты говоришь о "миллис с эпохи". Первый отсутствует, как объяснено в принятом ответе. Последний уже доступен как Instant.toEpochMillis(). Итак, LocalDateTimeвы бы пошли:ldt.toInstant(offset).toEpochMillis()
SusanW
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.