Joda проанализирует дату ISO8601 в часовом поясе GMT
У меня есть дата ISO 8601, скажем: 2012-01-19T19:00-05:00
Мой часовой пояс машины GMT+1
Я пытаюсь использовать joda для синтаксического анализа и преобразования его в соответствующую дату и время GMT:
DateTimeFormatter simpleDateISOFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mmZZ");
creationDate = simpleDateISOFormat.withZone(DateTimeZone.UTC)
.parseDateTime(date + "T" + time)
.toDate();
Теперь результат, который я ожидаю, Fri Jan 20 00:00:00 CET 2012
Вместо этого я получаю: Fri Jan 20 01:00:00 CET 2012
Я считаю, что это потому, что я вовремя GMT + 1
.
Есть ли способ проанализировать фальсификацию даты в другом часовом поясе?
Изменить: В основном проблема заключается в том, что я вызываю метод toDate()
. Метод преобразует DateTime
в Date
, как мне нужно, но я преобразовываю его в локальное время.
Кто-нибудь знает метод преобразования, который не налагает это ограничение?
Ответы
Ответ 1
Здесь работает тестовый файл groovy. Показывает, как могут отображаться часы в других часовых поясах.
import org.joda.time.*
import org.joda.time.format.*
@Grapes([
@Grab(group='joda-time', module='joda-time', version='1.6.2')
])
class JodaTimeTest extends GroovyTestCase {
void testTimeZone() {
DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser()
DateTimeFormatter formatter = ISODateTimeFormat.dateTimeNoMillis()
DateTime dateTimeHere = parser.parseDateTime("2012-01-19T19:00:00-05:00")
DateTime dateTimeInLondon = dateTimeHere.withZone(DateTimeZone.forID("Europe/London"))
DateTime dateTimeInParis = dateTimeHere.withZone(DateTimeZone.forID("Europe/Paris"))
assertEquals("2012-01-20T00:00:00Z", formatter.print(dateTimeHere))
assertEquals("2012-01-20T00:00:00Z", formatter.print(dateTimeInLondon))
assertEquals("2012-01-20T01:00:00+01:00", formatter.print(dateTimeInParis))
}
}
Примечание:
- Вам придется корректировать утверждения, потому что я располагаюсь в лондонском часовом поясе: -)
- Метод "withZone" изменяет метаданные объекта DateTime, чтобы указать его часовой пояс. Все тот же момент времени, просто отображается с другим смещением.
Ответ 2
java.time
Команда Joda-Time сообщила нам перейти на java.time, встроенную в Java 8 и более поздние версии. Структура java.time определяется JSR 310. Большая часть функций java.time была возвращена обратно портирована на Java 6 и 7 и далее адаптирован для Android.
Offset
Классы java.time включают OffsetDateTime
, чтобы представить момент на временной шкале с offset-from-UTC, но не полный часовой пояс.
В классах java.time по умолчанию используются стандартные форматы ISO 8601 при разборе или генерации строк. Поэтому нет необходимости определять шаблон форматирования.
String input = "2012-01-19T19:00-05:00";
OffsetDateTime odt = OffsetDateTime.parse( input );
Часовой пояс
A часовой пояс - это смещение плюс правила для обработки аномалий, таких как переход на летнее время (DST). A имя часового пояса использует формат continent/region
. Вы можете назначить часовой пояс (ZoneId
) на OffsetDateTime
, чтобы получить ZonedDateTime
.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = odt.atZoneSameInstant( zoneId );
Ответ 3
РЕДАКТИРОВАТЬ
fooobar.com/info/2129427/...
Это лучшее решение.
Для любых будущих читателей, если вы пытаетесь разобрать строку в формате yyyyMMddTHHmmssZ
. Его проще разобрать с помощью следующего кода. Код находится в Котлине. Правило iCalendar recur - пример того, где может выглядеть этот формат.
// Reads from end to start to accommodate case where year has 4+ digits. 10100 for example.
fun iso8601GetPart(hashMap : HashMap,noOfCharsFromEnd : Int?) : String{
var str = hashMap.get("DATE_TIME")
var endIndex = str.length
if(str.get(str.length-1)=='T' || str.get(str.length-1)=='Z'){
endIndex--
}
if(noOfCharsFromEnd==null){
return str
}else{
hashMap.put("DATE_TIME", str.substring(0, endIndex - noOfCharsFromEnd))
return str.substring(endIndex-noOfCharsFromEnd,endIndex)
}
}
fun foo(){
var hashMap = HashMap<String,String>()
hashMap.put("DATE_TIME",dateTimeString)
var secOfMin = iso8601GetPart(hashMap,2).toInt()
var minOfHour = iso8601GetPart(hashMap,2).toInt()
var hourOfDay = iso8601GetPart(hashMap,2).toInt()
var dayOfMonth = iso8601GetPart(hashMap,2).toInt()
var monthOfYear = iso8601GetPart(hashMap,2).toInt()
var years = iso8601GetPart(hashMap,null).toInt()
}