简体   繁体   中英

Joda parse ISO8601 date in GMT timezone

I have a ISO 8601 date, lets say: 2012-01-19T19:00-05:00

My machine timezone is GMT+1

I'm trying to use joda to parse this and convert it to the respective GMT date and time:

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

Instead I'm getting: Fri Jan 20 01:00:00 CET 2012

I believe this is because I'm in timezone 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. The method converts the DateTime into a Date as I need to do but I transforms it in local time.

Do someone know a conversion method which doesn't impose this limitation?

Here's a working groovy testcase. 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. Still the same point in time, just displayed with a different offset.

java.time

The Joda-Time team has told us to migrate to the java.time framework built into Java 8 and later. The java.time framework is defined by JSR 310 . Much of the java.time functionality has been back- ported to Java 6 & 7 and further adapted for 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.

The java.time classes use the standard ISO 8601 formats by default when parsing or generating strings. 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). A proper time zone name uses a continent/region format. You can assign a time zone ( ZoneId ) to an OffsetDateTime to get a ZonedDateTime .

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

EDIT

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 . Its easier to parse it with the following code. Code is in Kotlin. The iCalendar recur rule is an example of where this format might appear.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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