2016-09-16 1 views
3
года

У меня следующий фрагмент кода:android - SimpleDateFormat разбирает данные странным образом. Неправильный месяц или/и

final Date d = format.parse(value); 
LOGGER.debug("Compare:\nOriginal: {}, Format: {}, Result: {}", value, format.toPattern(), d); 
return d; 

value является строковым значением из JSON,

format является java.text.SimpleDateFormat,

d является датой который анализируется от value


раз он отлично работает, но иногда он возвращает странные даты.

Пример из LogCat:

 
D/App: 20:14:47.309 com.example.backend.BackendHelper - Compare: 
    Original: 2016-09-16 13:45:00.000+0200, Format: yyyy-MM-dd HH:mm:ss.SSSZ, Result: Fri Jan 01 05:00:00 GMT+07:00 2016 
D/App: 20:14:47.309 com.example.backend.BackendHelper - Compare: 
    Original: 2016-09-16 13:20:00.000+0200, Format: yyyy-MM-dd HH:mm:ss.SSSZ, Result: Fri Jan 01 18:20:00 GMT+07:00 2016 
D/App: 20:14:47.338 com.example.backend.BackendHelper - Compare: 
    Original: 2016-09-16 15:20:00.000+0200, Format: yyyy-MM-dd HH:mm:ss.SSSZ, Result: Thu Jan 01 05:00:00 GMT+07:00 1970

Как вы можете видеть, он возвращает неправильную Дату (неправильный год или/и месяц или/и час) для строковых значений, которые имеют абсолютно одинаковый формат и отличаются друг от друга другие только по часам и минутам.

Вопрос: Почему?

+0

Как вы инициализировали 'format'? –

+0

@ Code-Apprentice new SimpleDateFormat («yyyy-MM-dd HH: mm: ss.SSSZ», Locale.US), –

+0

Невозможно воспроизвести на простой Java (1.8.0_91 Win64). – Andreas

ответ

5

Ваш шаблон формата правильный. И местность здесь не уместна.

Ну, вы также внесли ввод в свой вопрос, чтобы мы могли исследовать, были ли какие-либо непечатаемые символы. Их нет (и JSON не производит такой вздор - очень маловероятно).

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

Как обходить это ограничение SimpleDateFormat?

  • Синхронизировать вызов для синтаксического анализа() - метод (вызывает снижение производительности)
  • следует хранить SimpleDateFormat -объект в ThreadLocal (лучше)
  • Использование FastDateFormat (производительность, сравнимую с ThreadLocale раствора, префикс «Быстрое» в настоящее время немного устарело)
  • Использование библиотеки ThreetenABP (адаптация Android вокруг резервного пакета нового пакета времени java.time, встроенного в Java-8), предлагает непреложный синтаксический анализатор), например: OffsetDateTime.parse(input, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSZ"))
  • Использование Joda-Time-Android (быстрее разборе чем ThreetenABP, также неизменны), например: DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSSZ").parseDateTime(input)
  • Или попробовать мою библиотеку Time4A (ИМХО самое быстрое решение, неизменное, тоже), например: ChronoFormatter.ofMomentPattern("yyyy-MM-dd HH:mm:ss.SSSZ", PatternType.CLDR, Locale.ROOT, ZonalOffset.UTC).parse(input)

Выбор в неизменный форматирующий/парсер - это, безусловно, лучший и самый современный способ перехода в многопоточную среду.Для Android библиотеки Apache Commons и ThreetenABP более компактны, чем более быстрые альтернативы Joda-Time или Time4A. Вы должны сделать свою собственную оценку более важной для вас, будь то размер или производительность (или, возможно, другие функции, которые вам нужны).

Смежные вопросы