3 回答
TA贡献1887条经验 获得超5个赞
地球上的每个人同时经历的时间线只有一个(忽略爱因斯坦等人)。按照惯例,我们以 UTC 跟踪该时间。
学会将 UTC 视为唯一的真实时间。所有其他偏移量和区域只是 UTC 的一种变体。在作为程序员或系统管理员工作时,忘记你自己狭隘的时区。在您的桌面或墙上保持第二次点击以 UTC 跟踪时间。在 UTC 中完成所有日志记录、跟踪、数据存储和数据交换。
在 UTC 中跟踪时刻的基本类是java.time.Instant
. 根据定义,此类的对象始终采用 UTC。这个类取代了java.util.Date
,它也代表 UTC 中的一个时刻,但有很多设计缺陷,永远不应该使用。Instant
具有纳秒级的分辨率,比 的毫秒级更精细Date
。
为了获得更大的灵活性,请使用OffsetDateTime
类。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
然后再回来。
Instant instant = odt.toInstant() ;
UTC 的偏移量只是一些小时-分钟-秒。时区要多得多。时区是特定地区人民使用的偏移量的过去、现在和未来变化的历史。
要使用时区,请应用 aZoneId
以获取ZonedDateTime
. 该类取代了可怕Calendar
和GregorianCalendar
类。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ; ZonedDateTime zdt = instant.atZoneId( z ) ;
又要回去了。
Instant instant = zdt.toInstant() ;
这zdt
, odt
, 和instant
都代表了同一时刻,时间线上的同一点。
最后,停止使用Date
andCalendar
。Sun、Oracle 和 JCP 社区在采用 JSR 310 时都放弃了这些类,您也应该如此。那些遗留课程真的是一团糟。
TA贡献1921条经验 获得超9个赞
第一个建议:
Instant transactionTime = Instant.now();
您是正确的,在您的时区中浏览时间是没有意义的,无论是在 aZonedDateTime还是 a 中Calendar,当您需要的是时间戳,时间片刻。java.time.Instant就是这样,一个没有时区的时间点(因此是 a 的最直接替代品Date)。您可能应该尽可能使用 java.time,现代 Java 日期和时间 API。Date,Calendar并且TimeZone不仅已经过时,而且还存在一系列设计问题。现代课程更适合使用。
如果您的事务入口类在内部使用java.util.Date并且您现在不想升级其内部逻辑,您仍然可以添加一个setTime接受Instant.
public void setTime(Instant time) {
// Delegate to the old method that accepts a java.util.Date
setTime(Date.from(time));
}
下一步可能是标记接受Date已弃用的方法。
第二个建议,如果你坚持Date我仍然喜欢:
Date transactionTime = Date.from(Instant.now());
它的作用与 相同new Date(),但更直接地告诉读者您获得了当前时刻。我看不出这怎么可能不是优势。
顺便说一句,如果您确实想使用时区,则应该使用正确的时区 ID,Antarctica/Davis而不是偏移量。同样,它会告诉您的读者更多有关您的意图的信息,并且在某些时候引入夏令时 (DST) 或偏移量因其他原因发生变化时是面向未来的。
TA贡献1848条经验 获得超6个赞
但我只能将时间存储为 java.util.Date。
那么时区无所谓,
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
Date america = calendar.getTime();
calendar.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
Date shanghai = calendar.getTime();
System.out.println(america.equals(shanghai)); // true
你可以只使用:
transactionEntry.setTime(new Date());
此页面将帮助您了解Instant/Date, LocalDateTime, ZonedDateTime。
我想你可能会重新考虑设计。为什么只java.util.Date允许?
从描述来看,您似乎确实关心事务发生的时区。虽然java.util.Date只是不支持它。这意味着您可以将准确的值(自纪元以来的毫秒数)存储到java.util.Date,但该值不能用准确的日期时间表示,因为时区已丢失。
您可能需要使用 java.time.ZonedDateTime来实现它。
添加回答
举报