我们需要将 Google Proto 缓冲区时间戳转换为正常日期。在这种情况下,有没有办法将 Google Proto 缓冲区时间戳LocalDate
直接转换为 Java?
4 回答
首先请注意:Protobuf 的TimeStamp
分辨率(秒和几分之一秒)比 Java 的LocalDate
(天)更高,因此您将通过从转换TimeStamp
为LocalDate
请参阅 TimeStamp 的JavaDoc的摘录:
时间戳表示独立于任何时区或日历的时间点,以 UTC 纪元时间的纳秒分辨率表示为秒和秒的分数。
同一个 JavaDoc 告诉我们,该值是基于 Epoch 时间的表示,这意味着我们可以使用 Java 的LocalDateTime#ofEpochSeconds进行无损失转换(因为LocalDateTime
也存储时间),然后从那里剥离时间以获得LocalDate
.
通过使用LocalDateTime
(em: Local),我们可以确保我们使用与TimeStamp
Class 相同的 TimeZone 偏移量,即 UTC(同样来自 JavaDoc):
final Timestamp ts1 = Timestamp.newBuilder().setSeconds((60 * 60 * 24) - 1).build();
final Timestamp ts2 = Timestamp.newBuilder().setSeconds((60 * 60 * 24)).build();
final LocalDate ld1 = LocalDateTime.ofEpochSecond(ts1.getSeconds(), ts1.getNanos(), ZoneOffset.UTC).toLocalDate();
final LocalDate ld2 = LocalDateTime.ofEpochSecond(ts2.getSeconds(), ts2.getNanos(), ZoneOffset.UTC).toLocalDate();
System.out.println(ts1 + " = " + ld1);
System.out.println(ts2 + " = " + ld2);
输出
秒:86399 = 1970-01-01
秒:86400 = 1970-01-02
要求转换为后编辑java.util.Date
查看可能的构造函数Date
及其JavaDoc,我们发现:
分配一个 Date 对象并将其初始化以表示自称为“纪元”的标准基准时间(即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。
并且因为 GMT 是分区时间表示的较旧标准,并且它基本上是 UTC +/- 0,所以这个构造函数符合我们的需要:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
// making sure the Date objects use UTC as timezone
final Timestamp ts1 = Timestamp.newBuilder().setSeconds((60 * 60 * 24) - 1).build();
final Timestamp ts2 = Timestamp.newBuilder().setSeconds((60 * 60 * 24)).build();
final Date d1 = new Date(ts1.getSeconds() * 1000);
final Date d2 = new Date(ts2.getSeconds() * 1000);
System.out.println(ts1 + " = " + d1);
System.out.println(ts2 + " = " + d2);
输出:
秒:86399 = 1970 年 1 月 1 日星期四 23:59:59 CET
秒:86400 = 1970 年 1 月 2 日星期五 00:00:00 CET
最简单的方法是将缓冲区 Timestamp 中的日期提取到一个字符串中,以便它可以被多次使用,然后:
Timestamp timestamp;
String sDate1 = timestamp.toString();
Date date1 = new SimpleDateFormat("dd/MM/yyyy").parse(sDate1);
如果您想将其设为 LocalDate,请执行以下操作:
Timestamp timestamp;
String sDate1 = timestamp.toString();
LocalDate localDate = LocalDate.parse(sDate1);
如果您无法提取字符串时间戳并且您有毫秒,您也可以从中创建 LocalDate 和 Date 对象,因为它们都有它的承包商。
Timestamp timestamp;
long timeInMilliSeconds = Timestamp.toMillis(timestamp);
Date currentDate = new Date(timeInMilliSeconds);
LocalDate date = Instant.ofEpochMilli(timeInMilliSeconds).atZone(ZoneId.systemDefault()).toLocalDate();
PubsubMessage pubsubMessage = message.getPubsubMessage();
String data = pubsubMessage.getData().toStringUtf8();
//System.out.println(pubsubMessage.getMessageId());
Timestamp timestamp = pubsubMessage.getPublishTime();
//System.out.println(timestamp);
Instant instant = Instant.ofEpochSecond(timestamp.getSeconds() ,
timestamp.getNanos());
ZoneId z = ZoneId.of("America/Montreal");
ZonedDateTime zdt = instant.atZone(z);
LocalDateTime ldt = zdt.toLocalDateTime();
System.out.println("today's date==> "+ldt.getDayOfMonth());
上面的代码肯定会工作。