简体   繁体   English

Joda在GMT时区解析ISO8601日期

[英]Joda parse ISO8601 date in GMT timezone

I have a ISO 8601 date, lets say: 2012-01-19T19:00-05:00 我有一个ISO 8601日期,让我们说: 2012-01-19T19:00-05:00

My machine timezone is GMT+1 我的机器时区是GMT+1

I'm trying to use joda to parse this and convert it to the respective GMT date and time: 我正在尝试使用joda来解析它并将其转换为相应的GMT日期和时间:

DateTimeFormatter simpleDateISOFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mmZZ"); 
creationDate = simpleDateISOFormat.withZone(DateTimeZone.UTC)
                                  .parseDateTime(date + "T" + time)
                                  .toDate(); 

Now the result that I'm expecting is Fri Jan 20 00:00:00 CET 2012 现在我期待的结果是Fri Jan 20 00:00:00 CET 2012

Instead I'm getting: Fri Jan 20 01:00:00 CET 2012 相反,我得到: Fri Jan 20 01:00:00 CET 2012

I believe this is because I'm in timezone GMT + 1 . 我相信这是因为我在时区GMT + 1

Is there a way to parse the date faking to be in a different time zone? 有没有办法解析日期伪装在不同的时区?

Edit: Basically the problem is when I call the toDate() method. 编辑:基本上问题是当我调用toDate()方法时。 The method converts the DateTime into a Date as I need to do but I transforms it in local time. 该方法将DateTime转换为我需要做的Date ,但我在本地时间转换它。

Do someone know a conversion method which doesn't impose this limitation? 有人知道一种不会施加此限制的转换方法吗?

Here's a working groovy testcase. 这是一个工作的groovy测试用例。 Shows how times in other timezones can be displayed. 显示其他时区的时间显示方式。

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))
    }
}

Note: 注意:

  • You'll have to adjust the assertions, because I'm located in the London timezone :-) 你必须调整断言,因为我位于伦敦时区:-)
  • The "withZone" method changes the DateTime object's metadata to indicate it's timezone. “withZone”方法更改DateTime对象的元数据以指示其时区。 Still the same point in time, just displayed with a different offset. 仍然是相同的时间点,只是显示不同的偏移量。

java.time java.time

The Joda-Time team has told us to migrate to the java.time framework built into Java 8 and later. Joda-Time团队告诉我们要迁移到Java 8及更高版本中内置的java.time框架。 The java.time framework is defined by JSR 310 . java.time框架由JSR 310定义。 Much of the java.time functionality has been back- ported to Java 6 & 7 and further adapted for Android . 许多java.time功能已被反向Java 6和7,进一步适用于Android

Offset 抵消

The java.time classes include OffsetDateTime to represent a moment on the timeline with an offset-from-UTC but not a full time zone. java.time类包括OffsetDateTime用于表示时间轴上的时刻,具有从UTC偏移但不是全时区。

The java.time classes use the standard ISO 8601 formats by default when parsing or generating strings. 在解析或生成字符串时,java.time类在默认情况下使用标准ISO 8601格式。 So no need to define a formatting pattern. 因此无需定义格式化模式。

String input = "2012-01-19T19:00-05:00";
OffsetDateTime odt = OffsetDateTime.parse( input );

Time Zone 时区

A time zone is an offset plus rules for handling anomalies such as Daylight Saving Time (DST). 时区是偏移加上用于处理诸如夏令时(DST)之类的异常的规则。 A proper time zone name uses a continent/region format. 正确的时区名称使用continent/region格式。 You can assign a time zone ( ZoneId ) to an OffsetDateTime to get a ZonedDateTime . 您可以将时区( ZoneId )分配给OffsetDateTime以获取ZonedDateTime

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = odt.atZoneSameInstant( zoneId );

EDIT 编辑

https://stackoverflow.com/a/23242779/812919 https://stackoverflow.com/a/23242779/812919

Is a better solution. 是更好的解决方案。


For any future readers, if you are trying to parse a string in the format yyyyMMddTHHmmssZ . 对于任何未来的读者,如果您尝试以yyyyMMddTHHmmssZ格式解析字符串。 Its easier to parse it with the following code. 使用以下代码更容易解​​析它。 Code is in Kotlin. 代码在Kotlin。 The iCalendar recur rule is an example of where this format might appear. iCalendar重复规则是此格式可能出现的示例。

// 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()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM