2016-09-01 3 views
0

У меня есть дата в формате String Мне нужно разобрать. Формат выглядит следующим образом с часовым поясом со всего миром:Как сохранить исходный часовой пояс с JodaTime

String stringDate = "2016-04-29 12:16:49.222+04:30"; 
String pattern = "yyyy-MM-dd HH:mm:ss.SSSZ"; 

Кажется, что java.util.Date не принимает часовой пояс с : сепаратором. Так что я пытаюсь с Jodatime библиотеки:

DateTime formattedDate = DateTimeFormat.forPattern(pattern).parseDateTime(stringDate); 
LocalDateTime formattedDate2 = DateTimeFormat.forPattern(pattern).parseLocalDateTime(stringDate); 
MutableDateTime formattedDate3 = DateTimeFormat.forPattern(pattern).parseMutableDateTime(stringDate); 

System.out.println(formattedDate); 
System.out.println(formattedDate2); 
System.out.println(formattedDate3); 

Эти строки вывода:

2016-04-29T09:46:49.222+02:00 
2016-04-29T12:16:49.222 
2016-04-29T09:46:49.222+02:00 

Насколько я понимаю форматировщик изменить выходной часовой пояс, чтобы соответствовать на мой (я в Париже, UTC + 2), но Я хочу, чтобы выход сохранялся в исходном часовом поясе. Можно ли это сделать с библиотекой Jodatime? Или я должен измениться для другого?

Edit: На самом деле мне нужно, чтобы получить Date объект, на котором смещение часового пояса будет 270 (часовой пояс смещение stringDate: 4 часа и 30 минут) вместо 120 (мой местный смещение часового пояса):

System.out.println(formattedDate.toDate().getTimezoneOffset()); // I expect 270 but I get 120 
+0

Какой будет ваш ожидаемый выход? похоже, вам нужно просто распечатать исходную строку .... – joc

+0

@joc На самом деле мне нужен объект 'Date', на котором' TimeZoneOffset() 'whould * 270 * вместо 120 *'. (Я обновляю свой вопрос) – Fractaliste

+1

'Date.getTimezoneOffset()' устарел с JDK 1.1 и всегда возвращает _ ваше местное смещение часового пояса. Чтобы получить поддержку часового пояса, вы можете использовать либо jown-файл 'DateTime', либо java-8' ZonedDateTime'. Какой из них вы предпочитаете? – Roman

ответ

0

Когда я запускаю тот же код, который вы выложили, я в конечном итоге с

2016-04-29T02:46:49.222-05:00 
2016-04-29T12:16:49.222 
2016-04-29T02:46:49.222-05:00 

который, если вы заметите, имеет различные значения часа и т ime-zone. Тем не менее, если вы посмотрите на их Millis:

System.out.println(formattedDate.getMillis()); 
System.out.println(formattedDate2.toDateTime().getMillis()); 
System.out.println(formattedDate3.getMillis()); 

вы увидите выход

1461916009222 
1461950209222 
1461916009222 

Таким образом, они имеют такое же время эпохи, но напечатаны по-разному. Это связано с механизмом toString() на объектах DateTime и как их интерпретировать.

DateTime и LocalDateTime (MutableDateTime - это просто изменяемая версия DateTime) имеют дело с тем же временем эпохи по-разному. LocalDateTime будет всегда Предположим, что время эпохи - время UTC (за javadoc for LocalDateTime), а DateTime будет считать, что эпоха представлена ​​в часовом поясе Хронологии, которую она удерживает (за javadoc again). Если TimeZone не указывается во время построения, то Chronology предположит, что вы хотите часовой пояс своего по умолчанию Locale, который устанавливается JVM. В вашем случае по умолчанию Locale - Париж Франция, а мой Сент-Луис США. В настоящее время в Париже имеется смещение часового пояса +2: 00, а у Сент-Луиса - 5: 00, что приводит к появлению различных представлений часовых поясов при его печати.

Чтобы еще более раздражать, эти смещения могут меняться со временем. Если я вернусь через 6 месяцев и попытаться ответить на этот раз, мои ценности покажут -6: 00 (! Глупое декретное время)

Важно помнить о том, что эти две даты имеют одинаковое время эпоха : мы говорим об одном и том же мгновении во времени, мы просто представляем это время по-разному, когда печатаем его.

Если вы хотите использовать другой часовой пояс, представляющий выход результата синтаксического анализа, то вы можете установить DateTimeZone во время форматирования с помощью DateTimeFormat.withZone() или DateTimeFormat.withLocale:

DateTimeFormatter sdf = DateTimeFormat.forPattern(pattern).withZone(DateTimeZone.forOffsetHoursMinutes(4,30)); 
System.out.println(formattedDate.getMillis()); 
System.out.println(formattedDate2.toDateTime().getMillis()); 
System.out.println(formattedDate3.getMillis()); 

, который будет печатать

2016-04-29 12:16:49.222+0430 
2016-04-29 12:16:49.222 
2016-04-29 12:16:49.222+0430 

Обратите внимание, что версия LocalDateTime все еще печатается без TimeZone. Это своего рода функция LocalDateTime: она представлена ​​без необходимости иметь дело со всем этим бизнесом.

Так вот почему ваши значения печати выглядят странно. Чтобы продолжить ваш вопрос о получении объекта java.util.Date из проанализированного объекта DateTime: toDate предоставит вам java.util.Date, который представляет одно и то же время. Однако java.util.Date ведет себя аналогично DateTime, в этом случае, если не указано иное, он будет использовать TimeZone по умолчанию Locale. Если вы знаете Locale раньше времени, вы можете использовать метод toDate(Locale), чтобы убедиться, что вы используете смещение TimeZone этого языка.

Это намного сложнее, если вы не знаете TimeZone раньше времени; в прошлом мне приходилось вручную анализировать часовые и минутные смещения TimeZone, чтобы определить правильный TimeZone для использования. В этом точный случай не слишком сложный, так как последние 6 символов чрезвычайно хорошо сформированы и правильны (если, конечно, они не являются :)).

1

Что вы пропустили это DateTimeFormatter#withOffsetParsed:

Возвращает новый форматчик, который будет создавать DateTime с временной зоной, равной смещению разобранной строки.

В противном случае форматтер проанализирует его в ваш местный часовой пояс (удивительно, я знаю).

@Test 
public void preserveTimeZone() { 
    String stringDate = "2016-04-29 12:16:49.222+04:30"; 
    String pattern = "yyyy-MM-dd HH:mm:ss.SSSZ"; 

    DateTime dt = DateTimeFormat.forPattern(pattern).withOffsetParsed().parseDateTime(stringDate); 

    System.out.println(dt); // prints "2016-04-29T12:16:49.222+04:30" 
} 

Как для редактирования - java.util.Date не содержат информацию о часовом поясе и устаревшее getTimezoneOffset() метод только

Возвращает смещение, измеренное в течение нескольких минут, для местного часового пояса относительно UTC, который подходит за время, представленное этим объектом Date.

Для правильной обработки часовых поясов вам лучше использовать классы Joda Time или java.time.

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