如何将Google原型时间戳转换为Java LocalDate?tl;博士转换转换关于 java.time
我们需要将Google Proto缓冲区时间戳转换为正常日期。在这种情况下,有没有办法将Google Proto缓冲区时间戳直接转换为Java?LocalDate
我们需要将Google Proto缓冲区时间戳转换为正常日期。在这种情况下,有没有办法将Google Proto缓冲区时间戳直接转换为Java?LocalDate
作为 UTC 中的某个时刻,转换为 。然后应用时区以获取 .将仅日期部分解压缩为 .java.time.Instant
ZonedDateTime
LocalDate
单行:
Instant
.ofEpochSecond( ts.getSeconds() , ts.getNanos() )
.atZone( ZoneId.of( "America/Montreal" ) )
.toLocalDate()
第一步是将 Timestamp
对象的秒数和秒的小数部分(纳秒)计数转换为 java.time 类。具体来说,java.time.Instant
。就像 一样,an 表示 UTC 中的一个时刻,分辨率为纳秒。Timestamp
Instant
Instant instant = Instant.ofEpochSecond( ts.getSeconds() , ts.getNanos() ) ;
确定日期需要时区。在任何给定的时刻,日期在全球范围内因区域而异。
将 a 应用于我们的 ,以获得 .相同的时刻,时间轴上的相同点,不同的挂钟时间。ZoneId
Instant
ZonedDateTime
ZoneId z = ZoneId( "Pacific/Auckland" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
将仅日期部分解压缩为 .A 没有时间,也没有时区。LocalDate
LocalDate
LocalDate ld = zdt.toLocalDate() ;
警告: 不要将类用于此目的,不幸的是,如另一个答案所示。该类故意缺少时区或与 UTC 的偏移量的任何概念。因此,它不能代表一个时刻,不是时间轴上的一个点。请参阅类文档。LocalDateTime
最好完全避免非常麻烦的遗留日期时间类,包括 , 、 .但是,如果您必须与尚未更新为java.time的旧代码进行互操作,则可以来回转换。调用添加到旧类的新转换方法。Date
Calendar
SimpleDateFormat
GregorianCalendar gc = GregorianCalendar.from( zdt ) ;
要将仅日期值表示为,我们必须指定一天中的时间和时区。您可能希望将一天中的第一个时刻用作一天中的时间组件。永远不要假设第一刻是 00:00:00。异常(如夏令时)意味着第一个时刻可能是另一个时间,如 01:00:00。让 java.time 决定第一个时刻。GregorianCalendar
ZonedDateTime firstMomentOfDay = ld.atZone( z ) ;
GregorianCalendar gc = GregorianCalendar.from( firstMomentOfDay ) ;
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧旧日期时间类,如java.util.Date
,Calendar
和SimpleDateFormat
。
Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。
要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
从哪里获取 java.time 类?
ThreeTen-Extra 项目通过其他类扩展了 java.time。这个项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
等。
首先要注意:Protobuf的分辨率(秒和秒的分数)比Java的(Days)更高,因此您将通过从转换为TimeStamp
LocalDate
TimeStamp
LocalDate
请参阅 TimeStamp 的 JavaDoc 摘录:
时间戳表示独立于任何时区或日历的时间点,在 UTC 纪元时间中以纳秒分辨率表示秒和秒的分数。
这个相同的JavaDoc告诉我们,该值是基于Epoch时间的表示,这意味着我们可以使用Java的LocalDateTime#ofEpochSeconds进行转换而不会丢失(因为还可以存储时间),并从那里剥离时间以获得.LocalDateTime
LocalDate
通过使用(em:Local),我们可以确保使用与类相同的时区偏移量,即UTC(这再次来自JavaDoc):LocalDateTime
TimeStamp
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
看看可能的构造函数和它们的JavaDoc,我们发现: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 = 星期四 一月 01 23:59:59 CET 1970
秒: 86400 = 星期五 一月 02 00:00:00 CET 1970