16

我们需要将 Google Proto 缓冲区时间戳转换为正常日期。在这种情况下,有没有办法将 Google Proto 缓冲区时间戳LocalDate直接转换为 Java?

4

4 回答 4

24
于 2018-10-04T16:26:12.683 回答
1

首先请注意:Protobuf 的TimeStamp分辨率(秒和几分之一秒)比 Java 的LocalDate(天)更高,因此您将通过从转换TimeStampLocalDate

请参阅 TimeStamp 的JavaDoc的摘录:

时间戳表示独立于任何时区或日历的时间点,以 UTC 纪元时间的纳秒分辨率表示为秒和秒的分数。


同一个 JavaDoc 告诉我们,该值是基于 Epoch 时间的表示,这意味着我们可以使用 Java 的LocalDateTime#ofEpochSeconds进行无损失转换(因为LocalDateTime也存储时间),然后从那里剥离时间以获得LocalDate.

通过使用LocalDateTime(em: Local),我们可以确保我们使用与TimeStampClass 相同的 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

于 2018-10-04T12:05:37.770 回答
0

最简单的方法是将缓冲区 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();
于 2018-10-04T11:27:54.747 回答
-1
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()); 

上面的代码肯定会工作。

于 2020-03-26T04:59:03.853 回答