0

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?

sontd
  • 397
  • 2
  • 4
  • 15
  • 1
    Why are you using an outdated API for date and time operations? Can't you use `java.time` for this? It's obvious that your target time zone does not get applied, but this troublesome API you are using doesn't make it obvious why it isn't applied. – deHaar Jul 16 '20 at 07:53
  • Related/similar: [Getting the current time millis from device and converting it into a new date with different timezone \[duplicate\]](https://stackoverflow.com/questions/52475409/getting-the-current-time-millis-from-device-and-converting-it-into-a-new-date-wi). – Ole V.V. Jul 16 '20 at 16:35

1 Answers1

5

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
deHaar
  • 17,687
  • 10
  • 38
  • 51
  • great, thanks @deHaarbut the question is: does it support for android > 5.0 or API level > 21? – sontd Jul 16 '20 at 08:43
  • 1
    @sontd It was introduced with Java 8 and was supported from Android API level 26, for supporting lower API levels, you had to import a [backport library](https://www.google.com/search?channel=crow2&client=firefox-b-d&q=threeten+abp), but that doesn't seem to be necessary anymore since there's [Android's API Desugaring](https://developer.android.com/studio/write/java8-support) now. – deHaar Jul 16 '20 at 08:47