如何将Google proto时间戳转换为Java LocalDate?

如何将Google proto时间戳转换为Java LocalDate?,java,date,grpc,grpc-java,proto,Java,Date,Grpc,Grpc Java,Proto,我们需要将Google Proto缓冲区时间戳转换为正常日期。在这种情况下,有没有办法将Google Proto buffer时间戳直接转换为JavaLocalDate?最简单的方法是将缓冲区时间戳中的日期提取为字符串,这样它就可以被多次使用,然后: Timestamp timestamp; String sDate1 = timestamp.toString(); Date date1 = new SimpleDateFormat("dd/MM/yyyy").parse(sDate1);

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

最简单的方法是将缓冲区时间戳中的日期提取为字符串,这样它就可以被多次使用,然后:

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();

首先需要注意的是:Protobuf的
时间戳
比Java的
LocalDate
(天)具有更高的分辨率(秒和秒的分数),因此通过将
时间戳
转换为
LocalDate

请参阅此时间戳摘录:

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


同样的JavaDoc告诉我们,这个值是基于历元时间的表示,这意味着我们可以使用Java进行转换而不会丢失(因为
LocalDateTime
也存储时间),并从那里获取
LocalDate
的时间

通过使用
LocalDateTime
(em:Local),我们可以确保使用与
TimeStamp
类相同的时区偏移量,即UTC(这同样来自JavaDoc):

输出

秒数:86399=1970-01-01

秒数:86400=1970-01-02


请求转换为
java.util.Date后编辑

查看
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=周四一月一日23:59:59 CET 1970

秒数:86400=英国东部时间1970年1月2日星期五00:00:00

tl;博士 在UTC中,转换为
java.time.Instant
。然后应用时区以获取
ZonedDateTime
。将仅日期部分提取为
LocalDate

一艘班轮:

Instant
.ofEpochSecond( ts.getSeconds() , ts.getNanos() ) 
.atZone( ZoneId.of( "America/Montreal" ) ) 
.toLocalDate() 
转换 第一步是将对象的秒数和分数秒(纳秒)转换为java.time类。明确地与
时间戳
一样,
瞬间
表示UTC中分辨率为纳秒的时刻

Instant instant =  Instant.ofEpochSecond( ts.getSeconds() , ts.getNanos() ) ;
确定日期需要时区。在任何一个特定的时刻,世界各地的日期都因地区而异

ZoneId
应用到我们的
Instant
以获取
zoneDateTime
。同一时刻,时间线上的同一点,不同的挂钟时间

ZoneId z = ZoneId( "Pacific/Auckland" ) ; 
ZonedDateTime zdt = instant.atZone( z ) ;
将仅日期部分提取为
LocalDate
LocalDate
没有时间和时区

LocalDate ld = zdt.toLocalDate() ;
注意:不要为此使用
LocalDateTime
类,不幸的是,另一个答案中显示了这一点。该类故意缺乏时区或UTC偏移的概念。因此,它不能代表一个时刻,也不是时间线上的一个点。请参阅类文档

转换 最好完全避免非常麻烦的遗留日期时间类,包括
date
Calendar
SimpleDateFormat
。但是,如果必须与尚未更新为java.time的旧代码进行互操作,则可以来回转换。调用添加到旧类中的新转换方法

GregorianCalendar gc = GregorianCalendar.from( zdt ) ;
要将仅日期值表示为
GregoriaCalendar
,必须指定一天中的时间和时区。您可能希望使用一天中的第一个时刻作为一天中的时间组件。永远不要假设第一刻是00:00:00。夏时制等异常情况意味着第一个时刻可能是另一个时间,如01:00:00。让java.time确定第一个时刻

ZonedDateTime firstMomentOfDay = ld.atZone( z ) ;
GregorianCalendar gc = GregorianCalendar.from( firstMomentOfDay ) ;


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

您可以直接与数据库交换java.time对象。使用兼容的或更高版本。不需要字符串,也不需要
java.sql.*

从哪里获得java.time类

  • 、和更高版本-标准Java API的一部分,带有捆绑实现。
    • Java9添加了一些次要功能和修复
    • 大多数java.time功能都在中向后移植到Java6和Java7
    • 更高版本的Android捆绑包实现了java.time类
    • 对于早期的Android(
      上面的代码肯定能用。

      你是说Java8 Date
      LocalDate
      Date
      本身就是Java1:-)对不起,它的拼写错误。现在改变了问题@LuCio,实际上是返回com.Google.protobuf.Timestamp实例的googleproto缓冲区。在那个地方,我们需要将其转换为LocalDate或其他任何名称!使用
      Instant.ofepochssecond(yourtimstamp.getSeconds(),yourtimstamp.getNanos())
      并从您得到的
      Instant
      继续。如果有疑问,请搜索如何将
      Instant
      转换为
      LocalDate
      ,这在许多地方都有描述。亲爱的Down投票者,请在投票时留下批评,解释这个问题如何没有帮助、没有建设性或格式不正确。在我看来,对于堆栈溢出来说,这是一个非常好的问题
      ZonedDateTime firstMomentOfDay = ld.atZone( z ) ;
      GregorianCalendar gc = GregorianCalendar.from( firstMomentOfDay ) ;
      
      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());