Java / Android:客户端和服务器之间的时区差异

时间:2020-03-22 15:01:06

标签: java android timezone

我有一个为Android编写的客户端和一个以Java编写的服务器。服务器存储信息,例如:

[{daysEpoch: ... , amount: 1}, {daysEpoch: ... , amount: 34},{daysEpoch: ... , amount: 76}]等... 其中daysEpoch是1970年1月1日的天。

每天的午夜(+ 5秒),客户都从epochDays=x那里请求项的总和,其中x是今天。问题是客户端上的“今天”是(例如)服务器UTC之后的一天。

很明显,返回值是错误的。我的第一个想法是将客户端的毫秒数发送到服务器,并且可以正常工作,但我想知道是否有更适当的方法来处理此问题。

更多信息:物品/数量很久以前就存在了,每天午夜,客户要求“ today”的总和。例如,如果客户端是gmt + 1,则移动设备上的午夜是服务器上的昨天晚上11点。仅在凌晨1点在服务器上是“今天”。我希望现在更清楚。

1 个答案:

答案 0 :(得分:4)

ISO 8601

我提出两个建议。我不确定哪个人最能实现您的目标。两项建议均涉及日期和时间的国际标准ISO 8601。

1。以UTC发送日期和时间:由于它可以发送与时区无关的时间点,因此建议您以UTC发送日期和时间来实现。例如:

 2020-03-22T19:04:57.110540Z

比从纪元开始的数秒或数毫秒的可读性更高,但也完全可以机读。尾随Z表示UTC。

2。仅以UTC发送日期:据我了解,问题在于日期因时区不同而不一致。但是,客户端知道自己的时区,并且可以很容易地在UTC中找到日期并将其发送到服务器,然后服务器就会理解。

2020-03-22

同样,如果您愿意,也可以附加Z以明确指出日期为UTC。尽管偶尔使用,但使用率并不高。同样,这种格式对人和机器都可读,这就是为什么自大纪元以来的几天里我更喜欢这种格式。

编辑:在聊天中:

我想要客户“今天”的数据。

从问题中来:

问题是客户端上的“今天”是一天之后(对于 例如)UTC服务器。

那我不明白那是个问题。据我所知,您正在得到想要的内容。

我仍然建议您以ISO 8601发送日期,而不是自该时期算起的天数。

如何用Java编写和读取ISO 8601?

java.time(现代的Java日期和时间API)经过精心设计,可与ISO 8601完美配合。要在任意时区从设备以UTC格式写入日期和时间,

    String dateTimeUtcString = Instant.now().toString();
    System.out.println(dateTimeUtcString);

刚刚运行的示例输出:

2020-03-22T19:34:48.034Z

如果您想知道为什么我在前几秒显示了六位小数,而这次只打印了三位小数:在标准范围内小数位数是免费的,如果您不这样做,您甚至可以完全忽略秒数的小数部分不需要它。都可以。

要在服务器上读取此字符串,请解析回Instant

    Instant i = Instant.parse(dateTimeUtcString);

如果仅需要日期,请从设备写入UTC日期:

    String dateString = LocalDate.now(ZoneOffset.UTC).toString();
    System.out.println(dateString);

2020-03-22

编辑:由于您想要客户的“今天”,因此在上述ZoneId.systemDefault()的呼叫中,您应该使用ZoneOffset.UTC而不是LocalDate.now()

并在服务器上进行解析;

    LocalDate date = LocalDate.parse(dateString);

如果您希望Z表示UTC,则它会稍长一些:

    String dateUtcString = OffsetDateTime.now(ZoneOffset.UTC)
            .format(DateTimeFormatter.ISO_OFFSET_DATE);
    System.out.println(dateUtcString);

2020-03-22Z

要解析,请在服务器中使用相同的格式化程序:

    LocalDate date = LocalDate.parse(
            dateUtcString, DateTimeFormatter.ISO_OFFSET_DATE);

问题:java.time是否不需要Android API级别26?

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

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

链接