javax. xml .datatype. Длительность до наносекунд - PullRequest
1 голос
/ 28 января 2020

У меня есть javax.xml.datatype.Duration, который содержит доли миллисекунды, например, длительность 1,5 мс (1500 микросекунд):

Duration duration = DatatypeFactory.newInstance().newDuration("PT0.0015S");

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

Как получить длительность в наносекундах?

Ответы [ 2 ]

3 голосов
/ 28 января 2020

Вы можете проанализировать продолжительность до java.time.Duration. Затем вызовите метод toNanos().

Duration duration = DatatypeFactory.newInstance().newDuration("PT0.0015S");
java.time.Duration.parse(duration.toString()).toNanos();
1 голос
/ 28 января 2020

API Duration был немного , что меня удивило, потому что вы должны получить часть длительности секунд с Duration.getField (Field) . Этот метод возвращает Number, то есть либо BigInteger (для дней, часов, минут и т. Д. c), либо BigDecimal (только для секунд).

Таким образом, чтобы получить доли секунды, вы можете использовать getField(DatatypeConstants.SECONDS), а затем преобразовать значение:

Duration duration = DatatypeFactory.newInstance().newDuration("PT0.0015S");
BigDecimal seconds = (BigDecimal) duration.getField(DatatypeConstants.SECONDS);
// Note that `getField` will return `null` if the field is not defined.
if(seconds != null) {
    System.out.println(seconds + "s");                    // 0.0015s
    System.out.println(seconds.movePointRight(9) + "ns"); // 1500000ns
}

Но это не общее количество секунд продолжительности. Это только значение секунд поле , остальные поля игнорируются. Для длительности, например P1M0.0015 (1 минута и 1,5 миллисекунды), эта минута игнорируется и просто возвращает 1,5 мс.

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

Duration duration = DatatypeFactory.newInstance().newDuration("PT1M0.0015S");
BigDecimal seconds = (BigDecimal) duration.getField(DatatypeConstants.SECONDS);

// only keep the fractional part
BigDecimal fractionalSeconds = seconds.remainder(BigDecimal.ONE);

long totalMillis = duration.getTimeInMillis(new Date(0));
// convert total millis to whole seconds (removes fractional part)
BigDecimal totalIntegerSeconds = 
    new BigDecimal(totalMillis).movePointLeft(3).setScale(0, RoundingMode.FLOOR);

// add both to get total seconds 
BigDecimal totalSeconds = totalIntegerSeconds.add(fractionalSeconds);

System.out.println(totalSeconds + "s");                     // 60.0015s
System.out.println(totalSeconds.movePointRight(9) + "ns");  // 60001500000ns

Это работает, но слишком сложно. Должен быть более простой способ сделать это.

@ ответ hasnae решение выглядит намного лучше, если вы используете Java 1.8. Интересно, каким был намеренный для разработчика API способ получить точность наносекунды, поскольку java.time.Duration был введен на несколько лет позже, чем javax.xml.datatype.Duration.

...