SimpleDateFormat не может проанализировать дату со значением смещения, подобным — ‘GMT-0500’

#java #date #datetime

#java #Дата #дата-время

Вопрос:

Я пытаюсь проанализировать эту (и многие подобные) строку данных — «Ср. 26 авг. 2020 г. 11:03:30 GMT-0500»

Просматривая документацию SimpleDateFormat, я предполагал, что подобный шаблон должен работать:

String dateFormat = "EEE MMM d yyyy HH:mm:ss z";

Однако это не так. Но следующий формат способен анализировать

String dateFormat = "EEE MMM d yyyy HH:mm:ss 'GMT'z";

Но когда я печатаю проанализированную дату, я получаю время с добавлением часа и уменьшением смещения на час — Ср. 26 авг. 12:03:30 GMT-04:00 2020

Что я могу сделать, чтобы предотвратить это изменение смещения?

Вот пример кода:

 String dateStr = "Wed Aug 26 2020 11:03:30 GMT-0500";        
String dateFormat = "EEE MMM d yyyy HH:mm:ss 'GMT'z";
Date date = new SimpleDateFormat(dateFormat).parse(dateStr);
System.out.println("Original Date String : " dateStr);
System.out.println("Original Date  Object : " date);
  
 Output:
Original Date String : Wed Aug 26 2020 11:03:30 GMT-0500
Original Date  Object : Wed Aug 26 12:03:30 GMT-04:00 2020
  

Комментарии:

1. Date не сохраняет информацию о часовом поясе, поэтому при печати значения оно форматируется в часовом поясе JVM по умолчанию. Чтобы сохранить информацию о часовом поясе, используйте более новые классы OffsetDateTime и DateTimeFormatter .

2. Название этого вопроса совершенно неверно, кстати. Он отлично анализирует дату. ваша проблема в том, что вы недовольны тем, как он снова печатает эту проанализированную дату.

3. Никогда не используйте Date и SimpleDateFormat . Вместо этого используйте новый Java Date and Time API (в java.time пакете).

4. @MCEmperor За исключением случаев, когда у вас нет выбора, например, при использовании библиотеки, для которой требуется Date . Никогда не говори никогда.

5. @Andreas Конечно, но сначала изучите правило, а затем исключение. Не наоборот.

Ответ №1:

Используйте java.time.OffsetDateTime здесь, потому что в этой строке нет зоны, только смещение, а используемые вами классы устарели по уважительным причинам… Избавьтесь от java.util.Date и java.text.SimpleDateFormat .

Смотрите этот пример:

 public static void main(String[] args) {
    // provide the String to be parsed
    String dateStr = "Wed Aug 26 2020 11:03:30 GMT-0500";
    // provide a matching pattern
    String dateFormat = "EEE MMM d yyyy HH:mm:ss 'GMT'Z";
    // create a formatter with this pattern and a suitable locale for unit names
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern(dateFormat, Locale.ENGLISH);
    // parse the String to an OffsetDateTime using the formatter
    OffsetDateTime odt = OffsetDateTime.parse(dateStr, dtf);
    // print the result in the default format
    System.out.println("Default/ISO format:t"   odt);
    // and print it in your custom format
    System.out.println("Custom format:tt"   odt.format(dtf));
}
  

Вывод:

 Default/ISO format: 2020-08-26T11:03:30-05:00
Custom format:      Wed Aug 26 2020 11:03:30 GMT-0500
  

Комментарии:

1. Если вы используете Z вместо x , вывод будет GMT-0500 соответствовать вводу.

2. @Andreas да, спасибо… Только что добавлено 😉 С неправильной локализацией… Скоро исправится

3. Z также анализирует, не нужно иметь 2 разных форматера. Просто используйте Z и забудьте о x .

4. @Andreas да, даже лучше… Последовал вашему совету.