【问题标题】:Joda parse ISO8601 date in GMT timezoneJoda 在 GMT 时区解析 ISO8601 日期
【发布时间】:2012-01-31 09:31:16
【问题描述】:

我有一个 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,这是我需要做的,但我在当地时间进行了转换。

有人知道没有这种限制的转换方法吗?

【问题讨论】:

    标签: java datetime jodatime


    【解决方案1】:

    这是一个工作正常的测试用例。显示如何显示其他时区的时间。

    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 8 及更高版本中内置的 java.time 框架。 java.time 框架由JSR 310 定义。 java.time 的大部分功能已被退回-ported to Java 6 & 7further adapted for Android

      偏移

      java.time 类包括OffsetDateTime 来表示时间线上的时刻,offset-from-UTC 但不是完整的时区。

      java.time 类在解析或生成字符串时默认使用标准 ISO 8601 格式。所以不需要定义格式化模式。

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

      时区

      time zone 是一个偏移规则,用于处理夏令时 (DST) 等异常情况。 proper time zone name 使用 continent/region 格式。您可以将时区 (ZoneId) 分配给 OffsetDateTime 以获取 ZonedDateTime

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

      【讨论】:

        【解决方案3】:

        编辑

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

        【讨论】:

          猜你喜欢
          • 2011-06-05
          • 2014-11-14
          • 1970-01-01
          • 2013-05-23
          • 2018-01-12
          • 1970-01-01
          • 2014-08-20
          • 2012-07-30
          • 2010-11-22
          相关资源
          最近更新 更多