2

I get a time from server and I want to change it to Local zone How can I do that with Kotlin ?
Time coming from the server is like "2020-09-01T13:16:33.114Z"
Here's my code:

  

val dateStr = order.creationDate
val df = SimpleDateFormat("dd-MM-yyyy HH:mm aa", Locale.getDefault())
df.timeZone = TimeZone.getDefault()
val date = df.parse(dateStr)
val formattedDate = df.format(date)
textViewDateOrderDetail.text = formattedDate

order.creationDate : Time from server

Lina
  • 553
  • 10
  • 34
  • Can you show an example `String` / `order.creationDate` value? – deHaar Sep 01 '20 at 10:26
  • as follows : 2020-09-01T13:16:33.114Z – Lina Sep 01 '20 at 10:27
  • What is your local time zone? At the moment, you only have a `Z` in the example `String`, which indicates a time in UTC respectively with `+00:00` offset. – deHaar Sep 01 '20 at 10:34
  • are you getting any exceptions while running the code you mentioned? what output you are getting? – Ichigo Kurosaki Sep 01 '20 at 10:34
  • @deHaar my local time is 11:16 – Lina Sep 01 '20 at 10:37
  • OK, so it's an offset of `-02:00` hours – deHaar Sep 01 '20 at 10:39
  • I change my code as follows, I update my question – Lina Sep 01 '20 at 10:44
  • Are you in Brazil? – deHaar Sep 01 '20 at 10:54
  • nn, my problem is not where am I, my problem is I want to convert Time from server to local timezone in any place in the world – Lina Sep 01 '20 at 10:57
  • @Lina Thank you for providing so much extra information. It’s always best to do that as edits to the question rather than in comments so that we have everything in one place and new readers can get the overview quickly. Many users don’t read through the comments. – Ole V.V. Sep 02 '20 at 03:07
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends. See if you either can use [desugaring](https://developer.android.com/studio/write/java8-support-table) or add [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project, in order to use java.time, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Sep 02 '20 at 03:08

1 Answers1

3

tl;dr

This will convert the example String to the system default time zone:

import java.time.ZonedDateTime
import java.time.ZoneId

fun main() {
    // example String
    val orderCreationDate = "2020-09-01T13:16:33.114Z"
    // parse it to a ZonedDateTime and adjust the zone to the system default
    val localZonedDateTime = ZonedDateTime.parse(orderCreationDate)
                                        .withZoneSameInstant(ZoneId.systemDefault())
    // print the adjusted values
    println(localZonedDateTime)
}

The output depends on the system default time zone, in the Kotlin Playground, it produces the following line:

2020-09-01T13:16:33.114Z[UTC]

which obviously means the Kotlin Playground is playing in UTC.


A little more...

It's strongly recommended to use java.time nowadays and to stop using the outdated libraries for datetime operations (java.util.Date, java.util.Calendar along with java.text.SimpleDateFormat).

If you do that, you can parse this example String without specifying an input format because it is formatted in an ISO standard.

You can create an offset-aware (java.time.OffsetDateTime) object or a zone-aware one (java.time.ZonedDateTime), that's up to you. The following example(s) show(s) how to parse your String, how to adjust a zone or an offset and how to print in a different format:

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

fun main() {
    // example String
    val orderCreationDate = "2020-09-01T13:16:33.114Z"
    // parse it to an OffsetDateTime (Z == UTC == +00:00 offset)
    val offsetDateTime = OffsetDateTime.parse(orderCreationDate)
    // or parse it to a ZonedDateTime
    val zonedDateTime = ZonedDateTime.parse(orderCreationDate)
    // print the default output format
    println(offsetDateTime)
    println(zonedDateTime)
    // adjust both to a different offset or zone
    val localZonedDateTime = zonedDateTime.withZoneSameInstant(ZoneId.of("Brazil/DeNoronha"))
    val localOffsetDateTime = offsetDateTime.withOffsetSameInstant(ZoneOffset.ofHours(-2))
    // print the adjusted values
    println(localOffsetDateTime)
    println(localZonedDateTime)
    // and print your desired output format (which doesn't show a zone or offset)
    println(localOffsetDateTime.format(
                DateTimeFormatter.ofPattern("dd-MM-uuuu hh:mm a")
            )
    )
    println(localZonedDateTime.format(
                DateTimeFormatter.ofPattern("dd-MM-uuuu hh:mm a")
            )
    )
}

The output is

2020-09-01T13:16:33.114Z
2020-09-01T13:16:33.114Z
2020-09-01T11:16:33.114-02:00
2020-09-01T11:16:33.114-02:00[Brazil/DeNoronha]
01-09-2020 11:16 AM
01-09-2020 11:16 AM

For a conversion to the system zone or offset, use ZoneId.systemDefault() or ZoneOffset.systemDefault() instead of hard coded ones. Pay attention to the ZoneOffset since it does not necessarily give the correct one because only a ZoneId considers daylight saving time. For more information, see this question and its answer

For further and more accurate information about formats to be defined for parsing or formatting output, you should read the JavaDocs of DateTimeFormatter.

deHaar
  • 17,687
  • 10
  • 38
  • 51
  • Thank u for ur reply, but why you put a static value, I want to convert Time from server to local timezone in any place in the world – Lina Sep 01 '20 at 10:58
  • @Lina See my edit... You would have to use the `systemDefault()` method to get the time zone of the system the client code is running on. Please not that such a system time is not necessarily the time zone of the place where the device is currently , it's the configuration of the device. – deHaar Sep 01 '20 at 11:10
  • I try ur code and I get the following result : zonedDateTime : 2020-09-01T14:27:30.057Z localZonedDateTime : 2020-09-01T15:27:30.057+01:00[...] or It should Be 12:27 – Lina Sep 01 '20 at 11:32
  • @Lina What's the problem? Those results cannot be output by my example code... It uses a fix input. What does `println(ZoneId.systemDefault())` print on your system? – deHaar Sep 01 '20 at 11:39
  • ZoneId.systemDefault() : it give my default zone – Lina Sep 01 '20 at 12:07
  • 1
    @Lina Then you can safely use `val localZdt = ZonedDateTime.parse(order.creationDate).withZoneSameInstant(ZoneId.systemDefault())` which parses the creation date of your order and adjusts it to your local time zone (that means it counts hours up or down because the `order.creationDate` is in time zone UTC and has an offset of 0 hours). – deHaar Sep 01 '20 at 12:12