怎么把GMT +09:00转换成当地时间?

时间:2019-06-24 09:04:10

标签: java android datetime kotlin android-jodatime

当我打印从服务器获取的日期时,它显示Mon Jun 24 16:15:31 GMT+09:00 2019

val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val date: Date? = formatter.parse(checkedDate) // date from server
val transformedDate = ("${String.format("%02d", date!!.month + 1)}.${String.format("%02d", date!!.date)}.${date.year + 1900}")
val title: String? = ("$transformedDate")

val longGmtTime = date.time
val mZone = TimeZone.getDefault()
val offset = mZone.getOffset(longGmtTime)
val longLocalTime = longGmtTime + offset - (9 * HOUR)

val localDate = Date() // local date
localDate.time = longLocalTime
val localFormatTime = formatter.format(localDate)
val transformedLocalDate = ("${String.format("%02d", localDate!!.month + 1)}.${String.format("%02d", localDate!!.date)}.${localDate.year + 1900}")

结果给我server time: 2019-06-24 16:15:31 -> 06.24.2019, local time(Asia/Seoul)-> 2019-06-25 01:15:30 ->06.25.2019

服务器时间和本地时间必须相同。但是当地时间显示在其他地方。

出什么问题了?

2 个答案:

答案 0 :(得分:3)

  

出什么问题了?

总问题列表包括:

  • 您正在使用设计欠佳且过时的Java日期和时间类DateTimeZoneSimpleDateFormat
  • 您正在使用getMonth类的不赞成使用的方法getDategetYearDate。这些方法在时区工作不可靠,这是不建议使用它们的主要原因。
  • 您正在使用加法,减法和乘法手动进行时区转换。日期和时间数学容易出错,应始终将其留给经过验证的库方法。
  • 您从Date.getTime获得的毫秒计数是从UTC 1970-01-01T00:00:00的时代开始。这是一个独特的时间点,与时区无关,因此对时区转换添加或减去毫秒计数是没有道理的。
  • 当我将JVM的默认时区设置为Asia / Seoul并假定HOUR为0(或介于0到111之间的某个值)时,我可以重现您的结果。我假设您曾经想HOUR表示一个小时中的毫秒数,即3,600,000(至少通常存在例外)。
  • 您正在通过串联对Strirg.format的调用结果来格式化日期。最好将格式化留给专门的日期格式化程序。

修复:java.time

    ZoneId serverTimeZone = ZoneId.of("Asia/Seoul");
    DateTimeFormatter serverFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
    ZoneId clientTimeZone = ZoneId.systemDefault();

    String checkedDate = "2019-06-24 16:15:31";
    ZonedDateTime serverDateTime = LocalDateTime.parse(checkedDate, serverFormatter)
            .atZone(serverTimeZone);
    ZonedDateTime clientDateTime = serverDateTime.withZoneSameInstant(clientTimeZone);
    System.out.println("clientDateTime: " + clientDateTime);

对不起,我只能编写和运行Java代码,我相信您可以翻译。在我的JVM时区仍然设置为亚洲/首尔的情况下,我得到:

  

clientDateTime:2019-06-24T16:15:31 + 09:00 [亚洲/首尔]

服务器时间和客户端时间相同。相反,如果我保留自己的时区,则会得到:

  

clientDateTime:2019-06-24T09:15:31 + 02:00 [欧洲/哥本哈根]

因此发生了转换。

格式化日期:

    DateTimeFormatter displayFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
            .withLocale(Locale.forLanguageTag("ko-KR"));
    String transformedLocalDate = clientDateTime.format(displayFormatter);
    System.out.println("transformedLocalDate: " + transformedLocalDate);
  

transformedLocalDate:2019. 6. 24。

或者,如果您坚持使用month.date.year:

    DateTimeFormatter displayFormatter = DateTimeFormatter.ofPattern("MM.dd.u");
  

transformedLocalDate:06.24.2019

进一步的建议是让您的服务器以UTC格式提供ISO 8601格式的日期时间字符串。在示例中使用的那一刻就像2019-06-24T07:15:31Z

问题:我可以在Android上将Java.time与minSdk API级别23配合使用吗?

是的,java.time在较新和较旧的Android设备上均可正常运行。它只需要至少 Java 6

  • 在Java 8和更高版本以及更新的Android设备(API级别26以上)中,内置了现代API。
  • 在Java 6和7中,获得了ThreeTen反向端口,这是现代类的反向端口(JSR 310的ThreeTen;请参见底部的链接)。
  • 在(较旧的)Android上,使用Android版本的ThreeTen Backport。叫做ThreeTenABP。并确保您使用子包从org.threeten.bp导入日期和时间类。

链接

答案 1 :(得分:0)

您应指定安装服务器时区而不是设备(默认)