Чому в класах 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.