Почему в классах 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()метода в будущем.

JodaStephen
источник
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, поэтому вопрос, по-видимому, впоследствии не обсуждался.

assylias
источник
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.

mkadunc
источник
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