В этом конкретном случае он дает точно такой же результат, вплоть до наносекунды. Я не уверен, что с другими входами микросекунды могут оказаться неточными, но, с другой стороны, если вы получите двойное число (не строку), вы ничего не можете с этим поделать.

я возникла проблема с преобразованием двойного объекта даты в объект Java в формате: гггг-мм-дд чч: мм: сс

Я попытался преобразовать это двойное значение в длинное значение, а затем создать экземпляр объекта Date с результатом, но я получил ошибки, в которых говорится, что я не могу преобразовать значение типа double в long.

двойные значения моей метки времени в этом формате:

1.511554592277516E9

Кто-нибудь может мне помочь с этим вопросом, пожалуйста, заранее спасибо.

 darkpbj07 дек. 2017 г., 19:58
Можете ли вы поделиться тем, что вы пробовали до сих пор? Вы используете примитивы илиDouble а такжеLong типы?
 Filipe Fedalto07 дек. 2017 г., 20:03
В любом случае, почему вы используете удвоение для выражения времени? Это не так, что это запрещено, но вы обычно подсчитываете количество прошедших миллисекунд со стандартного времени. Длинный подойдет для этого. Используете ли вы double, потому что какая-то система имеет такое наложение?
 Makoto07 дек. 2017 г., 19:58
Вы делаете что-то вроде ... считая секунды после эпохи или что-то?
 Aniss Chohra07 дек. 2017 г., 20:04
это не мой выбор, я получаю данные в лог-файлы и хранится таким образом: 1.511531688957562E9
 Aniss Chohra07 дек. 2017 г., 20:01
Я прочитал метку времени из объекта карты следующим образом: double timestamp = (double) Map.get ("ts"); затем преобразуйте его в long, используя: long timestampLong = (long) timestamp; и, наконец, создайте объект даты следующим образом: Date date = new Date (timestampLong); и это дает мне такой результат: Sun Jan 18 06:52:11 EST 1970

Ответы на вопрос(2)

что это значение с плавающей точкой находится в секундах после эпохи Unix 1 января 1970 года в 0:00 по Гринвичу, это обеспечит преобразование вLocalDateTime с этим смещением:

LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(
                Double.valueOf(1.511554592277516E9).longValue(), 0, ZoneOffset.UTC);
System.out.println(localDateTime);

Я оставляю преобразование этого вDate в качестве упражнения для читателя.

 Makoto08 дек. 2017 г., 00:08
@BasilBourque: Я дам вам C- за усилие, но это число ближе к 1,511,554,592.277516, что не меньше полутора секунд от 1970 года.
 Ole V.V.07 дек. 2017 г., 20:47
Я думаю, я бы пошел наInstant а неLocalDateTime. Instant тоже имеетofEpochSecond метод, и он сохраняет точку на временной шкале, чтоlongпредставлял. Преобразование вDateЯ бы избежал этого, если бы увидел способ. С современным API гораздо приятнее работать.
 Aniss Chohra07 дек. 2017 г., 20:07
Большое спасибо, это сработало так, как я хотел.
 Basil Bourque07 дек. 2017 г., 23:47
@AnissChohra Итак, ваш файл журнала записан через полторы секунды после даты начала эпохи первого момента 1970 года? Трудно поверить. Эти файлы журнала взяты изНазад в будущее кино?

1.511554592277516E9несомненно, обозначает секунды с 1 января 1970 года в полночь по UTC с точностью до микросекунды: 1 511 554 592 секунды и 277 516 микросекунд (миллионные доли секунды).

Я предлагаю использоватьjava.timeдля этого современный API даты и времени Java, также известный как JSR-310. Намного приятнее работать с устаревшимиDate класс и друзья, а также предлагает наносекундную точность (Date только с точностью до миллисекунды, так что вы потеряете точность при преобразовании в единицу). Более конкретно я сначала создамjava.time.Instant объект (преобразование в другие типы даты и времени будет простым, в конце я приведу один пример).

Получение полной точности вInstant требует немного подумать Я немного поиграл сdouble а такжеlong, но понял (1)double не обладает необходимой точностью, наносекунды не будут правильными (2) преобразование вlong проведение наносекунд (не единственный, но, безусловно, самый простой) создаст «проблему 2262 года», поэтому, если вы будете обрабатывать даты в далеком будущем, это не сработает. В любом случае, я думаю, что простым и безопасным решением является использованиеBigDecimal для математики, необходимой перед подачей чисел вInstant.

    String secondsSinceEpoch = "1.511554592277516E9";
    BigDecimal decimalSeconds = new BigDecimal(secondsSinceEpoch);
    long seconds = decimalSeconds.longValue();
    long nanos = decimalSeconds.subtract(BigDecimal.valueOf(seconds))
            .movePointRight(9)
            .longValueExact();
    Instant inst = Instant.ofEpochSecond(seconds, nanos);
    System.out.println(inst);

Это печатает:

2017-11-24T20:16:32.277516Z

Дата и время печатаются в формате UTC. Если значение соответствует ожидаемому, я должен сказать, что оно подтверждает, что ваше значение с плавающей точкой действительно было секундами с начала эпохи.

Вы запросили дату и время в формате гггг-мм-дд чч: мм: сс. Вам нужно будет решить, в каком часовом поясе вы хотите установить дату и время. У объектов даты нет формата, поэтому вам также необходимо получить формат в виде строки. Например:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    System.out.println(inst.atZone(ZoneId.of("America/Vancouver")).format(formatter));

Это печатает

2017-11-24 12:16:32

Разумеется, вы заменяете желаемый часовой пояс.atZone() преобразуетInstant вZonedDateTimeеще один часто используемый классjava.time.

РЕДАКТИРОВАТЬ: Если вы не хотите беспокоиться оBigDecimal, вы принимаете небольшую неточность и / или получаете свое значение как двойную, а не строку, вот альтернатива в меньшем количестве строк кода:

    double secondsSinceEpoch = 1.511554592277516E9;
    long longSeconds = (long) secondsSinceEpoch;
    long micros = Math.round((secondsSinceEpoch - longSeconds) * 1_000_000);
    Instant inst = Instant.ofEpochSecond(longSeconds).plus(micros , ChronoUnit.MICROS);

В этом конкретном случае он дает точно такой же результат, вплоть до наносекунды. Я не уверен, что с другими входами микросекунды могут оказаться неточными, но, с другой стороны, если вы получите двойное число (не строку), вы ничего не можете с этим поделать.

Ваш ответ на вопрос