androidkotlinthreetenbp

Convert a UTC time to a local current time


I am using the followng library threetenbp

I am fetching a date/time from our API response which is in string format The time I am being sent is this Sep 30, 2023, 4:59:00 PM

So I need to convert that to the local time zone. Which for me is Asia/Bangkok.

However, if the time is in UTC and in Asia/Bangkok we are 7 hours ahead. After converting the time the time haven't changed

i.e. time from API Response: Sep 30, 2023, 4:59:00 PM

So after converting to local Bangkok time I would think it would plus 7 hours. But I am getting the result 2023-09-30 16:59:00 Which is the exactly same time.

Here is the code snippet

    val utcFormatter = DateTimeFormatter.ofPattern("MMM dd, yyyy, h:mm:ss a")

    // Parse the UTC time string to a LocalDateTime object.
    val utcDateTime = utcFormatter.parse("Sep 30, 2023, 4:59:00 PM")

    // Create a DateTimeFormatter object with the desired local time zone.
    val localFormatter = DateTimeFormatter
        .ofPattern("yyyy-MM-dd HH:mm:ss")
        .withZone(ZoneId.of("Asia/Bangkok"))
    val result = localFormatter.format(utcDateTime)


    // The result is the following: 2023-09-30 16:59:00

======

val utcFormatter = DateTimeFormatter.ofPattern("MMM dd, yyyy, h:mm:ss a")
    .withZone(ZoneOffset.UTC)

val utcDateTime = LocalDateTime.parse("Sep 30, 2023, 4:59:00 PM", utcFormatter)
    .atZone(ZoneId.of("Asia/Bangkok"))

println(utcDateTime)

The output is the following:

2023-09-30T16:59+07:00[Asia/Bangkok]

However, I thought that the output would have had the time adjusted to be 7 hours ahead. Basically, the time is still the same.

So for example if the UTC time is 12:00 PM then the time would be 7 PM in Bangkok.


Solution

  • Your code is almost correct, but your utcFormatter is not really a UTC formatter, because you didn't specify the timezone anywhere. You can fix your problem with the following code:

    val utcFormatter = DateTimeFormatter.ofPattern("MMM dd, yyyy, h:mm:ss a")
        .withZone(ZoneOffset.UTC)
    

    Or alternatively, leave the formatter as is and then specify the zone when parsing:

    val utcDateTime = LocalDateTime.parse("Sep 30, 2023, 4:59:00 PM", utcFormatter)
        .atZone(ZoneOffset.UTC)
    

    Full example using zoned formatters:

    val utcFormatter = DateTimeFormatter.ofPattern("MMM dd, yyyy, h:mm:ss a")
        .withZone(ZoneOffset.UTC)
    val localFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
        .withZone(ZoneId.of("Asia/Bangkok"))
    
    OffsetDateTime.parse("Sep 30, 2023, 4:59:00 PM", utcFormatter)
        .format(localFormatter)
    

    Full example by manipulating zones manually:

    val inputFormatter = DateTimeFormatter.ofPattern("MMM dd, yyyy, h:mm:ss a")
    val outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
    
    LocalDateTime.parse("Sep 30, 2023, 4:59:00 PM", inputFormatter)
        .atOffset(ZoneOffset.UTC)
        .atZoneSameInstant(ZoneId.of("Asia/Bangkok"))
        .format(outputFormatter)