几年后,我正在采用Java编程。我注意到,在Java 8中有一些新的日期/时间对象。什么类型用于Java 8 bean日期属性 - Instant或ZoneDateTime?
对于使用Java 8的持久数据bean,我应该使用什么类型的日期/时间属性?它是Instant
,ZoneDateTime
或Date
?
几年后,我正在采用Java编程。我注意到,在Java 8中有一些新的日期/时间对象。什么类型用于Java 8 bean日期属性 - Instant或ZoneDateTime?
对于使用Java 8的持久数据bean,我应该使用什么类型的日期/时间属性?它是Instant
,ZoneDateTime
或Date
?
首先,你应该避免旧的类(Date
,Calendar
和SimpleDateFormat
)。他们有lots of problems和design issues,他们中的大多数都是由新API修复的(这就是为什么新类创建的原因,顺便说一下)。
IMO,它总是更好的日期/时间对象UTC内部工作 - 为最佳的类是Instant
,它总是在UTC。因此,为了坚持数据库并进行内部操作,我总是倾向于使用UTC日期/时间,因为它可以减少混淆并避免不必要的转换。
当/如果你需要显示此日期/时间 - 给用户,或者在其他一些接口 - 你希望它是在一个特定的时区,那么你转换这个Instant
为ZonedDateTime
。
例子:
// create current instant in UTC - Instant is **always** in UTC
Instant now = Instant.now();
System.out.println(now); // 2017-06-20T13:28:39.075Z
// converting to some timezone
ZonedDateTime z = now.atZone(ZoneId.of("America/Sao_Paulo"));
System.out.println(z); // 2017-06-20T10:28:39.075-03:00[America/Sao_Paulo]
// converting to another timezone
z = now.atZone(ZoneId.of("Europe/London"));
System.out.println(z); // 2017-06-20T14:28:39.075+01:00[Europe/London]
// converting back to Instant
System.out.println(z.toInstant()); // 2017-06-20T13:28:39.075Z
因此,UTC瞬间是2017-06-20T13:28:39.075Z
,这对应于圣保罗2017-06-20T10:28:39.075-03:00
和2017-06-20T14:28:39.075+01:00
在伦敦(注意:ZoneId
已经采取的夏时制护理)。
另请注意,我使用了完整的时区名称(America/Sao_Paulo
和Europe/London
)。格式为Continent/City
的这些名称由IANA database定义,并由新API使用。
你应该避免使用3个字母的时区的名称(如ECT
或CST
),因为他们是ambiguous and not standard。始终倾向于使用全名 - 您可以通过致电ZoneId.getAvailableZoneIds()
获取所有可用名称。
您还可以使用ZoneId.systemDefault()
- 这将获得系统中配置的默认时区。但是这可以在运行时改变,导致不可预知的结果,所以最好使用明确的时区。
上面的输出是每个对象的toString()
方法的结果。但是,如果你想有一个不同的格式,你可以使用DateTimeFormatter
类:
ZonedDateTime z = now.atZone(ZoneId.of("America/Sao_Paulo"));
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss xxx");
System.out.println(fmt.format(z)); // 20/06/2017 10:28:39 -03:00
请参考javadoc看到所有可能的格式。
非常感谢您考虑的答案。关于如何将时间戳与发起代理的时区关联的另一个相关问题。假设我有一个接受订单的系统,并且我想使用“即时”存储订单的时间戳,如何最好地记录下订单的代理的时区?换句话说,他们是在圣保罗还是伦敦? – user2868835
如果这是一个要求,@ user2868835也会存储一个'ZoneId'('ZoneId.systemDefault()'会给你JVM的设置)或者创建一个异常并存储'ZonedDateTime'而不是'Instant',这个会给你两个,你仍然可以根据需要随时转换。 –
国际海事组织,最好在内部使用'Instant'工作,并将'ZoneId'存储在一个单独的字段中(所以,只在向用户显示日期时使用它(atZone(zoneid)'))。 – 2017-06-21 13:39:35
我希望bean中的属性为Instant
,因为它在UTC中,无论它需要呈现给客户端,它都可以转换为合适的ZonedDateTime
。
Instant instant = Instant.now() ; // gives current instant of time in UTC.
//Can be converted to ZonedDateTime
ZoneId zone = ZoneId.of("Asia/Kolkata")) ;
ZonedDateTime zdt = instant.atZone(zone) ;
如果您需要知道时区,请使用'ZonedDateTime'。如果您只需要及时,“Instant”是首选。正如你可能知道的那样,你总是可以将它转换为'ZonedDateTime'来在某个时区显示给用户。 –
如果有什么方法可以避免过时的'Date'类,那么您会希望。我收集在那里。 “即时”通常被认为是它的现代替代品。 –