Ошибка часового пояса SimpleDateFormat на Android
Я пытаюсь изолировать ошибку в своем приложении. Мне удалось создать следующую "загадку":
SimpleDateFormat f1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
SimpleDateFormat f2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date d = f1.parse("2012-01-01T00:00:00+0700");
String s1 = f1.format(d); // 2011-12-31T18:00:00+0700
String s2 = f2.format(d); // 2011-12-31T18:00:00+0100
Я получаю значения в комментариях при запуске этого кода в Android API 7 (да, действительно). Это зависит от конкретной реализации Java.
Мои вопросы:
- Почему s1 не равно s2?
- И что еще более важно, почему s1 неверен? Пока
s2
указывает на правильный момент времени, s1
нет. Кажется, что ошибка в реализации Android SimpleDateFormat.
ОТВЕТ НА ВОПРОС 1: См. ответ BalusC:
- [После использования
SimpleDateFormat#parse
] любое другое значение TimeZone, которое ранее было установлено вызовом setTimeZone, возможно, потребуется восстановить для дальнейших операций.
ОТВЕТ НА ВОПРОС 2: См. ответ wrygiel (я).
- Это связано с ошибкой в Android 2.1 (API 7).
Ответы
Ответ 1
Это упоминается в javadoc DateFormat#parse()
:
Разбирайте строку даты/времени в соответствии с заданной позицией анализа. Например, текст времени "07/10/96 4:5 PM, PDT"
будет анализироваться в Дате, эквивалентной Date(837039900000L)
.
По умолчанию разбор является мягким: если вход не находится в форме, используемой этим методом объектного формата, но все равно может быть проанализирован как дата, тогда синтаксический анализ завершается успешно. Клиенты могут настаивать на строгом соблюдении формата, вызывая setLenient(false)
.
Эта операция синтаксического анализа использует calendar
для создания Date
. В результате поля calendar's
даты и времени TimeZone
могут быть перезаписаны в зависимости от реализаций подкласса. Любое значение TimeZone
, которое ранее было установлено вызовом setTimeZone
, возможно, потребуется восстановить для дальнейших операций.
Обратите внимание на последний абзац. К сожалению, это не объясняет, когда именно это произойдет. Чтобы исправить вашу конкретную проблему, вам нужно явно задать желаемый часовой пояс перед операцией форматирования.
Что касается изменчивости самого SimpleDateFormat
, это известно уже много лет. Вы никогда не должны создавать и присваивать ему экземпляр как статическую или классную переменную, но всегда как переменную метода (threadlocal).
Ответ 2
Это связано с ошибкой в Android 2.1 (API 7). Похоже, что Android-программисты пропустили некоторое недокументированное поведение Java (которое классифицируется как самореактивная ошибка!) В их реализации Android 2.1.
Ответ 3
Ваш вопрос заинтриговал меня, поэтому я пошел дальше и скомпилировал ваш код. Результат? Как и ожидалось...
2011-12-31T18:00:00+0100
2011-12-31T18:00:00+0100
Два значения одинаковы: используете ли вы concurrency? Возможно, переменная изменяется на другой поток прямо перед f2.format(d)
.
Ответ 4
Я попытался сравнить s1 и s2, запустив ту же программу. они равны мне.
![enter image description here]()