我有一个为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点在服务器上是“今天”。我希望现在更清楚。
答案 0 :(得分:4)
我提出两个建议。我不确定哪个人最能实现您的目标。两项建议均涉及日期和时间的国际标准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.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设备上均可正常运行。它只需要至少 Java 6 。
org.threeten.bp
导入日期和时间类。java.time
。java.time
向Java 6和7(JSR-310的ThreeTen)的反向端口。