Почему новый Java 8 Date Time API не имеет наносекундной точности?

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

DateTimeFormatter formatter = DateTimeFormatter
    .ofPattern("yyyy-MM-dd'T'HH:mm:ss,nnnnnnnnnZ");
System.out.println(OffsetDateTime.now().format(formatter)); 

Я вижу только точность до миллисекунды: 2015-11-02T12: 33: 26,746000000 + 0100

Операционная система, похоже, поддерживает точность наносекунд. Когда я печатаю текущую дату и время через Терминал

date -Ins

Я вижу 2015-11-02T12: 33: 26,746134417 + 0100

Как добиться в Java точности наносекунд? Я использую Oracle Java 1.8.0_66 на 64-разрядной версии Ubuntu 14.04.


person Thomas Oellrich    schedule 02.11.2015    source источник
comment
Исправлено в Java 9. Новая реализация _ 1_ фиксирует текущий момент с разрешением до наносекунды (в зависимости от возможностей часов вашего хоста).   -  person Basil Bourque    schedule 19.09.2016


Ответы (2)


java.time API в целом действительно имеет точность наносекунды. Например:

DateTimeFormatter formatter = DateTimeFormatter
    .ofPattern("yyyy-MM-dd'T'HH:mm:ss,nnnnnnnnnZ");
OffsetDateTime odt = OffsetDateTime.of(2015, 11, 2, 12, 38, 0, 123456789, ZoneOffset.UTC);
System.out.println(odt.format(formatter));

Вывод:

2015-11-02T12:38:00,123456789+0000

Однако это значение часов, возвращаемое OffsetDateTime.now(), которое возвращает значение, имеющее только миллисекунды.

Из реализации Clock в Java 8:

Представленная здесь реализация часов основана на System.currentTimeMillis(). Этот метод практически не дает гарантии точности часов. Приложения, которым требуются более точные часы, должны сами реализовать этот абстрактный класс, используя другие внешние часы, такие как сервер NTP.

Так что здесь нет ничего неточного по своей сути - просто реализация Clock по умолчанию с использованием System.currentTimeMillis(). Вы потенциально можете создать свой собственный более точный подкласс. Однако следует отметить, что увеличение точности без увеличения точности, вероятно, не очень полезно. (Бывают моменты, когда это может быть, правда ...)

person Jon Skeet    schedule 02.11.2015
comment
Последнее особенно важно. nanosleep(2) имеет аналогичные проблемы на стандартном потребительском оборудовании, так как спит в течение определенного количества наносекунды влекут за собой планку ошибок ~ 1 цикл ЦП, что невозможно сделать в среде с вытесняющей многозадачностью. Тем не менее, высокий уровень точности может быть полезен, если вам просто нужно упорядочить различные события относительно друг друга и не заботиться о точных интервалах между ними. Я предполагаю, что часы монотонно растут, что, как я надеюсь, правда. - person Kevin; 03.11.2015

Чтобы сделать важное дополнение к ответу Джона Скита, Java 9 должна предоставлять часы с повышенной точностью - см. журнал ошибок. Предыстория: во многих операционных системах (особенно Linux) доступны лучшие часы.

В спецификации Java SE 8 для java.time.Clock указано, что «методы системной фабрики предоставляют часы на основе наилучших доступных системных часов. Это может использовать System.currentTimeMillis () или часы с более высоким разрешением, если они доступны. ". В JDK 8 реализация возвращаемых часов была основана на System.currentTimeMillis () и, таким образом, имеет разрешение только миллисекунды. В JDK 9 реализация
основана на базовых собственных часах, которые использует System.currentTimeMillis (), обеспечивая максимальное разрешение, доступное для этих часов. В большинстве систем это могут быть микросекунды, а иногда даже десятые доли микросекунд.

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

Следует также отметить (экзотический) факт, что секундная точность не будет существовать рядом с дополнительными секундами - даже в Java 9.

person Meno Hochschild    schedule 02.11.2015
comment
Есть ли дополнительная информация о том, почему секундная точность не существует рядом с високосными секундами? Это потому, что существует несколько способов их реализации (например, «мазок скачком»)? - person Thunderforge; 03.11.2015
comment
@Thunderforge Выражение типа ChronoUnit.SECONDS.between(instant1, instant2) никогда не может считать високосные секунды. java.time-дизайнеры решили скрыть високосные секунды и сделать вид, что каждая минута состоит из 60 секунд. Их спецификация официально требует UTC-SLS, а реальная реализация в JDK де-факто похожа на POSIX, а не на UTC-SLS - просто игнорируя дополнительные секунды. Все известные часы ОС (в качестве основы Clock.systemUTC() ведут себя одинаково или применяют какой-то сброс часов или размытие секунд прыжка. SI-секунды не моделируются. Если вы серьезно ищете поддержку истинных секунд прыжка, то рассмотрите мою библиотеку Time4J. - person Meno Hochschild; 03.11.2015