Как преобразовать строку даты UTC и удалить T и Z в Java? - PullRequest
0 голосов
/ 24 мая 2018

Я использую Java 1.7.

Попытка преобразовать:

2018-05-23T23:18:31.000Z 

в

2018-05-23 23:18:31

Класс DateUtils:

public class DateUtils {

    public static String convertToNewFormat(String dateStr) throws ParseException {
        TimeZone utc = TimeZone.getTimeZone("UTC");
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        sdf.setTimeZone(utc);
        Date convertedDate = sdf.parse(dateStr);
        return convertedDate.toString();
    }
}

При попытке использовать его:

String convertedDate = DateUtils.convertToNewFormat("2018-05-23T23:18:31.000Z");
System.out.println(convertedDate);

Получите следующее исключение:

Exception in thread "main" java.text.ParseException: Unparseable date: "2018-05-23T23:22:16.000Z"
   at java.text.DateFormat.parse(DateFormat.java:366)
   at com.myapp.utils.DateUtils.convertToNewFormat(DateUtils.java:7)

Что я, возможно, делаю неправильно?

Есть ли более простой способ сделать это (например, Apache Commons lib)?

Ответы [ 4 ]

0 голосов
/ 24 мая 2018

tl; др

Instant.parse( "2018-05-23T23:18:31.000Z" )                // Parse this String in standard ISO 8601 format as a `Instant`, a point on the timeline in UTC. The `Z` means UTC.
.atOffset( ZoneOffset.UTC )                                // Change from `Instant` to the more flexible `OffsetDateTime`.
.format(                                                   // Generate a String representing the value of this `OffsetDateTime` object.
    DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" )   // Specify a formatting pattern as desired.
)                                                          // Returns a `String` object.

2018-05-23 23: 18: 31

ISO 8601

Ваша входная строка находится встандартный ISO 8601 формат.

Классы java.time по умолчанию используют эти стандартные форматы при разборе / генерации строк.

Tотделяет часть год-месяц-день от часа-минуты-секунды.Z произносится Zulu и означает UTC .

java.time

Вы используете проблемные старые классы даты и времени, которые были вытеснены несколько лет назад java.time классы.Apache DateUtils также больше не нужен, так как его функциональность вы найдете в java.time .

Анализ этой входной строки как Instant объекта.Класс Instant представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичной дроби).

String input = "2018-05-23T23:18:31.000Z" ;
Instant instant = Instant.parse( input ) ;

Чтобы сгенерировать строку в другом формате, нам нужен более гибкий объект.Класс Instant должен быть базовым строительным блоком.Позвольте s convert it to a OffsetDateTime`, используя сам UTC в качестве указанного смещения от UTC.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ; 

Определите шаблон форматирования, чтобы соответствовать желаемому выводу.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" ) ;
String output = odt.format( f ) ;

Совет: Рассмотримиспользование DateTimeFormatter::ofLocalized… методов для автоматической локализации генерации строки для некоторого Locale вместо жесткого кодирования шаблона форматирования.


О java.time

Инфраструктура java.time встроена в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

Вы можете обмениваться java.time объектами непосредственно с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

  • Java SE 8 , Java SE 9 , Java SE 10, а позже
    • Встроенный.
    • Часть стандартного Java API с встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функций java.time перенесена на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии реализации комплекта Android классов java.time.
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .

ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и more .

0 голосов
/ 24 мая 2018

Попробуй это.Вы должны использовать один шаблон для разбора, а другой для форматирования.

public static String convertToNewFormat(String dateStr) throws ParseException {
    TimeZone utc = TimeZone.getTimeZone("UTC");
    SimpleDateFormat sourceFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    SimpleDateFormat destFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sourceFormat.setTimeZone(utc);
    Date convertedDate = sourceFormat.parse(dateStr);
    return destFormat.format(convertedDate);
}
0 голосов
/ 24 мая 2018

Для других без Java 1.7 Ограничения:

Начиная с Java 1.8 вы можете сделать это, используя LocalDateTime и ZonedDateTime из пакета java.time

public static void main(String[] args) {
    String sourceDateTime           = "2018-05-23T23:18:31.000Z";
    DateTimeFormatter sourceFormat  = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
    DateTimeFormatter targetFormat  = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    LocalDateTime dateTime          = LocalDateTime.parse(sourceDateTime, sourceFormat);
    String formatedDateTime         = dateTime.atZone(ZoneId.of("UTC")).format(targetFormat);
    System.out.println(formatedDateTime);
}

РЕДАКТИРОВАТЬ: (см.Комментарии)

Цитата из документации Oracle Java по LocalDateTime :

LocalDateTime - это неизменяемый объект даты и времени, представляющий дату и время, часто рассматриваемый какгод-месяц-день-часы-минуты-секунды.Другие поля даты и времени, такие как день года, день недели и неделя года, также могут быть доступны.Время представляется с точностью до наносекунды.Например, значение «2 октября 2007 года в 13: 45.30.123456789» может быть сохранено в LocalDateTime.

Этот класс не хранит или не представляет часовой пояс.Вместо этого, это описание даты, используемой для дней рождений, в сочетании с местным временем, показанным на настенных часах.Он не может представлять момент на временной шкале без дополнительной информации, такой как смещение или часовой пояс.

ОП запрашивает ПРОСТО разбор входной строки в дату-время (как годмесяц-день-час-минута-секунда) и документация гласит

LocalDateTime ... представляет дату-время, часто рассматриваемое как год-месяц-день-час-минута-секунда

, поэтому важная информация здесь не теряется.А часть dateTime.atZone(ZoneId.of("UTC")) возвращает ZonedDateTime, поэтому ZimeZone снова обрабатывается на этом этапе, если пользователю нужно работать с часовым поясом ... и т. Д.

, поэтому не пытайтесь заставить пользователей использовать«Единственное» решение, которое вы представляете в своем ответе.

0 голосов
/ 24 мая 2018

YYYY не совпадает с частью года.В Java 7 вам нужно yyyy.

Для T, используйте 'T', чтобы соответствовать

Вы также пропускаете фракцию миллисекундной части: .SSS

Попробуйте это:

String dateStr="2018-05-23T23:18:31.000Z";
TimeZone utc = TimeZone.getTimeZone("UTC");
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss.SSS'Z'");
sdf.setTimeZone(utc);
Date convertedDate = sdf.parse(dateStr);
convertedDate.toString();
...