Форматирование объекта даты - PullRequest
1 голос
/ 03 марта 2020

Я пытаюсь отформатировать введенную дату в Java, которая выглядит следующим образом в отладчике.

result = {Date@13861} "2019-09-29"
 fastTime = 1569729600000
 cdate = {Gregorian$Date@13873} "2019-09-29T00:00:00.000-0400"

Мне нужно преобразовать ее в: 2019-09-28 20:00:00.0.

Мой код:

DateTimeFormatter dateTimeformatter_Test = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

LocalDate tempDate = LocalDate.parse(date.toString(), DateTimeFormatter.ofPattern( "yyyy-MM-dd" , Locale.US ));

Но строка ниже выдает ошибку во время выполнения, говорящую: Неподдерживаемое поле: HourOfDay

String result= tempDate.format(dateTimeformatter_Test);

Что мне здесь не хватает, пожалуйста?

Спасибо.

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Вашему вопросу не хватает информации о часовом поясе, но вот один из способов преобразования 2019-09-29 в 2019-09-28 20:00:00.0:

System.out.println(
        LocalDate.parse("2019-09-29")
        .atStartOfDay(ZoneOffset.UTC)
        .withZoneSameInstant(ZoneId.of("America/New_York"))
        .format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S")));

Вывод

2019-09-28 20:00:00.0

Вот совершенно другой способ, показывающий значения, которые вы видели в отладчике:

TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));

java.sql.Date result = java.sql.Date.valueOf("2019-09-29");
System.out.println("result = " + result);

long fastTime = result.getTime();
System.out.println("fastTime = " + fastTime);

System.out.println("cdate = " + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(result));

ZonedDateTime zdt = Instant.ofEpochMilli(fastTime).atZone(ZoneId.of("America/Anchorage"));
System.out.println("zdt = " + zdt.format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S")));

Вывод

result = 2019-09-29
fastTime = 1569729600000
cdate = 2019-09-29T00:00:00.000-0400
zdt = 2019-09-28 20:00:00.0
0 голосов
/ 03 марта 2020

Если это отметка времени для вашей базы данных SQL: не указывайте в вашей базе данных отметку времени в виде строки. Дайте ему надлежащий объект даты и времени. Начиная с JDB C 4.2 это означает:

  • Для SQL timestamp with time zone (рекомендуется для подавляющего большинства целей) обеспечить OffsetDateTime; многие водители также принимают Instant.
  • Для SQL timestamp без часового пояса укажите LocalDateTime.

Так, например:

    java.sql.Date inputDate = getFromSomewhere();
    OffsetDateTime dateTimeForDatabase = inputDate.toLocalDate()
            .atStartOfDay(ZoneOffset.UTC)
            .toOffsetDateTime();
    System.out.println(dateTimeForDatabase);

    PreparedStatement stmt = yourDatabaseConnection.prepareStatement(
            "insert into your_table(your_timestamp_col) values (?)");
    stmt.setObject(1, dateTimeForDatabase);
    int rowsInserted = stmt.executeUpdate();

Пример вывода из оператора печати в середине:

2019-09-29T00: 00Z

Z означает UT C, поэтому это тот же момент времени, что и 2019-09-28 20:00:00.0, который вы запрашивали, при условии, что часовой пояс вашей JVM является некоторым вариантом североамериканского восточного времени (Америка / Торонто или Америка / Нью-Йорк).

Объект, который вы видите, в вашем отладчике очень похоже на java.sql.Date объект, поэтому я взял этот тип в качестве отправной точки. Класс java.sql.Date плохо спроектирован, хотя на самом деле это настоящий взлом на фоне уже плохо спроектированного класса java.util.Date. Это также давно устарело. Поэтому, если бы вы могли вместо этого получить современный тип, например LocalDate, это было бы выгодно.

Что пошло не так в вашем коде?

A LocalDate - это дата без времени дня, например 2019-09-29. Вы пытались отформатировать один, используя шаблон формата yyyy-MM-dd'T'HH:mm:ss.SSS'Z'. Итак, вы просите включить в результат время суток, но, как я уже сказал, у LocalDate нет времени суток, так что это не имеет смысла. Полученное сообщение об ошибке было довольно точным:

Неподдерживаемое поле: HourOfDay

...