【问题标题】:How to convert time from server to local zone with kotlin?如何使用 kotlin 将时间从服务器转换为本地区域?
【发布时间】:2020-12-20 10:59:48
【问题描述】:

我从服务器获取时间,我想将其更改为本地区域如何使用 Kotlin 做到这一点?
来自服务器的时间就像“2020-09-01T13:16:33.114Z”
这是我的代码:

  

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 : 来自服务器的时间

【问题讨论】:

  • 你能举个例子String/order.creationDate值吗?
  • 如下:2020-09-01T13:16:33.114Z
  • 您当地的时区是多少?目前,在示例String 中,您只有一个Z,它分别表示带有+00:00 偏移量的UTC 时间。
  • 您在运行您提到的代码时是否遇到任何异常?你得到什么输出?
  • @deHaar 我的当地时间是 11:16

标签: android kotlin timezone


【解决方案1】:

tl;博士

这会将示例String 转换为系统默认时区:

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

输出取决于系统默认时区,在 Kotlin Playground 中,它产生以下行:

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

这显然意味着 Kotlin Playground 正在以 UTC 运行。


还有一点……

强烈建议现在使用java.time,并停止使用过时的库进行日期时间操作(java.util.Datejava.util.Calendar 以及java.text.SimpleDateFormat)。

如果您这样做,您可以在不指定输入格式的情况下解析此示例 String,因为它是按照 ISO 标准进行格式化的。

您可以创建一个偏移感知 (java.time.OffsetDateTime) 对象或区域感知对象 (java.time.ZonedDateTime),这取决于你。以下示例展示了如何解析您的 String、如何调整区域或偏移量以及如何以不同的格式打印:

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")
            )
    )
}

输出是

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

要转换到系统区域或偏移量,请使用 ZoneId.systemDefault()ZoneOffset.systemDefault() 而不是硬编码的。注意ZoneOffset,因为它不一定给出正确的,因为只有ZoneId 考虑夏令时。 如需更多信息,请参阅this question and its answer

有关为解析或格式化输出定义的格式的更多和更准确信息,您应该阅读the JavaDocs of DateTimeFormatter

【讨论】:

  • 谢谢你的回复,但为什么你放一个静态值,我想将时间从服务器转换为世界上任何地方的本地时区
  • @Lina 查看我的编辑... 您必须使用systemDefault() 方法来获取运行客户端代码的系统的时区。请注意,这样的系统时间不一定是设备当前所在的时区,而是设备的配置。
  • 我尝试你的代码,我得到以下结果: zonedDateTime : 2020-09-01T14:27:30.057Z localZonedDateTime : 2020-09-01T15:27:30.057+01:00[... ] 或者应该是 12:27
  • @Lina 有什么问题?我的示例代码无法输出这些结果......它使用修复输入。 println(ZoneId.systemDefault()) 在您的系统上打印什么?
  • @Lina 然后您可以安全地使用val localZdt = ZonedDateTime.parse(order.creationDate).withZoneSameInstant(ZoneId.systemDefault()),它会解析您的订单的创建日期并将其调整为您当地的时区(这意味着它会向上或向下计数小时,因为order.creationDate 在时区 UTC,偏移量为 0 小时)。
猜你喜欢
  • 2013-04-26
  • 2010-09-24
  • 2011-02-12
  • 2023-03-31
  • 1970-01-01
  • 2016-01-19
  • 1970-01-01
  • 1970-01-01
  • 2016-07-08
相关资源
最近更新 更多