Чому в класах 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клас
Вім Деблауве

Відповіді:


63

JSR-310 заснований на наносекунд, а НЕ мілісекунди. Таким чином, мінімальний набір розумних методів базується на годині, хвилинах, секунді та наносекунді. Рішення мати наносекундну основу було одним з оригінальних рішень проекту, і таке, на що я настійно вважаю, є правильним.

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

FWIW, я б виступав проти додавання getMillis()методу в майбутньому.


1
Я отримав кілька дуже хороших відповідей на це запитання, але моя відповідь є моєю улюбленою, оскільки вона коротка, але все ж це дуже добре підкреслює і справді переконує мене в необхідності такого підходу. Дякую.
Тармо

12
@ s3ib, якщо ви перевірите профіль Answerer , ви також помітите, що він є специфікацією для самого API, про який ви просите. Це робить відповідь настільки авторитетною, наскільки вона отримує, чи не так :)
gnat

Отже, якщо це зробити, instant.getEpochSecond * 1000 + instant.getNano / 1000000це розумно мати можливість спілкуватися із застарілими (на даний момент усіма) Java API, Javascript тощо?
nilskp

10
немає, в цьому випадку ви можете просто використовувати instant.toEpochMilli () download.java.net/jdk8/docs/api/java/time / ...
JodaStephen

20

До того, як бути учасником openJDK, тритен був на 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, оскільки з моменту епохи все базувалося на кількох мілісах. У новому API він менш релевантний ІМО. У більшості випадків використання вам потрібна або друга точність, або найкраща доступна точність (нанос). Я можу помилятися.
assylias

1
Це, здається, задає питання про іменування методів, а не які методи повинні існувати.
svick

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-бітні int наносекунди (без підпису).

...

Я вважаю за краще, щоб розкол був на другому рівні, оскільки це офіційна одиниця часу в науці СІ та найбільш загальновизнаний стандарт.

Розщеплення на рівні днів є проблематичним для примірників, оскільки воно не обробляє високосні секунди. Розщеплення на рівні мілісекунд, при цьому трохи краще інтегруючись з рештою 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 " => a LocalDateTime, безумовно, може мати getMillisметод, який би в основному повертався getNanos()/1e6- той факт, що він не є миттєвим часом, не заважає йому мати мілісекунд компонент.
Ассілія

2
мене є відчуття, що ще однією причиною було навмисне перешкоджати перетворенню з класів java.util.Date в класи JSR310 " Можливо, правда, але, на жаль, "milis з епохи" стала майже універсальним представленням часу, тому для всього, що потрібно для спілкування зі старими Java API, 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.