sontd
sontd

Reputation: 435

Kotlin SimpleDateFormat parse wrong timezone

My mobile timezone was GMT+7, I have a code to convert a specific date time(GMT+0) to a specific timezone(GMT+3):

var strDate = "2020-07-10 04:00:00+0000"
var result: Date?
var dateFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ")
dateFormatter.timeZone = TimeZone.getTimeZone("Asia/Jerusalem")
result = dateFormatter.parse(strDate)

The problem is result always return "Fri Jul 10 11:00:00 GMT+07:00 2020"
But I expected it will return date object "Fri Jul 10 07:00:00 GMT+03:00 2020", any idea what's wrong with my code?

Upvotes: -1

Views: 12557

Answers (1)

deHaar
deHaar

Reputation: 18578

It's recommended to use java.time and stop using java.util.Date, java.util.Calendar along with java.text.SimpleDateFormat because of problems like this one.

In your code, the target time zone is obviously not applied to the date but it isn't obvious why it isn't.

A different problem might be pattern you are using because your example String does not contain any unit of time smaller than seconds but the pattern tries to consider .SSS (which made the code fail in the Kotlin Playground).

Switch to java.time and handle this with modern classes, such as OffsetDateTime for parsing this String (it doesn't contain information about a specific time zone, just an offset of zero hours) and ZonedDateTime as the target object (this considers a real time zone which may have different offsets depending things like Daylight Saving Time).

You could do it like this:

import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter

fun main() {
    // this example is in UTC (+0000 --> no offset / offset of 0 hours)
    var strDate = "2020-07-10 04:00:00+0000"
    // create a formatter that can parse Strings of this pattern
    // ([] represents optional units to be parsed)
    var dateFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss[.SSS]Z")
    // and parse the String to an OffsetDateTime using this formatter
    var resultOfParsing = OffsetDateTime.parse(strDate, dateFormatter)
    // then print the parsed result
    println(resultOfParsing)
    
    // create the target time zone
    var timeZone = ZoneId.of("Asia/Jerusalem")
    // then use the target zone for a zone shift
    var jerusalemTime: ZonedDateTime = resultOfParsing.atZoneSameInstant(timeZone)
    // and print the result
    println(jerusalemTime)
    // you could use your formatter defined above for a differently formatted output, too
    println(jerusalemTime.format(dateFormatter))
}

which outputs (including all intermediate results):

2020-07-10T04:00Z
2020-07-10T07:00+03:00[Asia/Jerusalem]
2020-07-10 07:00:00.000+0300

Upvotes: 4

Related Questions