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
に変換しますが、現地時間で変換します。
この制限を課さない変換方法を誰かが知っていますか?
これが実用的なグルーヴィーなテストケースです。他のタイムゾーンの時刻を表示する方法を示します。
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))
}
}
注:
Joda-Timeチームは、Java 8以降に組み込まれている Java.time フレームワークに移行するように指示しました。Java.timeフレームワークは JSR 310 によって定義されます。Java.time機能の多くが戻ってきました- Java 6&= 7 および Android にさらに適合。
Java.timeクラスには OffsetDateTime
が含まれており、タイムライン上の瞬間を offset-from-UTC で表します。ただし、フルタイムゾーンではありません。
Java.timeクラスは、文字列を解析または生成するときに、デフォルトで標準のISO8601形式を使用します。したがって、フォーマットパターンを定義する必要はありません。
String input = "2012-01-19T19:00-05:00";
OffsetDateTime odt = OffsetDateTime.parse( input );
タイムゾーン は、夏時間(DST)などの異常を処理するためのオフセットplusルールです。 適切なタイムゾーン名 はcontinent/region
形式を使用します。タイムゾーン( ZoneId
)をOffsetDateTime
に割り当てて、 ZonedDateTime
を取得できます。 。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = odt.atZoneSameInstant( zoneId );
[〜#〜]編集[〜#〜]
https://stackoverflow.com/a/23242779/812919
より良い解決策です。
将来の読者のために、yyyyMMddTHHmmssZ
の形式の文字列を解析しようとしている場合。次のコードで解析する方が簡単です。コードはKotlinにあります。 iCalendar recur rule は、この形式が表示される場所の例です。
// 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()
}