Java Joda解析GMT时区中的ISO8601日期

Java Joda解析GMT时区中的ISO8601日期,java,datetime,jodatime,Java,Datetime,Jodatime,我有一个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)

我有一个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(); 
现在我期待的结果是2012年CET标准时间1月20日星期五00:00:00

相反,我得到的是:
Fri Jan 20 01:00:00 CET 2012

我相信这是因为我在时区
GMT+1

有没有一种方法可以解析假装在不同时区的日期

编辑:基本上问题在于调用
toDate()
方法时。该方法将
日期时间
转换为
日期
,我需要这样做,但我在本地时间转换它


有人知道一种转换方法不受此限制吗?

下面是一个正在运行的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对象的元数据以指示其时区。仍然是相同的时间点,只是以不同的偏移显示
java.time Joda Time团队告诉我们迁移到内置于Java8和更高版本的框架。java.time框架由定义。java.time的大部分功能都已经实现了

抵消 time类包括表示时间线上的某个时刻,但不表示完整时区

在解析或生成字符串时,java.time类默认使用标准ISO 8601格式。因此,无需定义格式化模式

String input = "2012-01-19T19:00-05:00";
OffsetDateTime odt = OffsetDateTime.parse( input );
时区 A是偏移量加上处理异常(如夏令时(DST))的规则。A使用
大陆/地区
格式。您可以将时区()分配给
OffsetDateTime
,以获取一个时间

编辑

这是一个更好的解决方案


对于任何未来的读者,如果您试图解析格式为
yyymmddthhmmsz
的字符串。使用以下代码更容易解析它。代码在Kotlin中。示例说明了此格式可能出现的位置

// 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()
}
//从头到尾读取,以适应年份有4位以上数字的情况。例如10100。
乐趣iso8601GetPart(hashMap:hashMap,noOfCharsFromEnd:Int?):字符串{
var str=hashMap.get(“日期\时间”)
var endIndex=str.length
如果(str.get(str.length-1)='T'| | str.get(str.length-1)='Z'){
endIndex--
}
if(noOfCharsFromEnd==null){
返回str
}否则{
put(“日期时间”,str.substring(0,endIndex-noOfCharsFromEnd))
返回str.substring(endIndex noOfCharsFromEnd,endIndex)
}
}
fun foo(){
var hashMap=hashMap()
put(“DATE\u 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()
}
// 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()
}