2017-06-20 123 views
2

几年后,我正在采用Java编程。我注意到,在Java 8中有一些新的日期/时间对象。什么类型用于Java 8 bean日期属性 - Instant或ZoneDateTime?

对于使用Java 8的持久数据bean,我应该使用什么类型的日期/时间属性?它是Instant,ZoneDateTimeDate

+0

如果您需要知道时区,请使用'ZonedDateTime'。如果您只需要及时,“Instant”是首选。正如你可能知道的那样,你总是可以将它转换为'ZonedDateTime'来在某个时区显示给用户。 –

+0

如果有什么方法可以避免过时的'Date'类,那么您会希望。我收集在那里。 “即时”通常被认为是它的现代替代品。 –

回答

1

首先,你应该避免旧的类(DateCalendarSimpleDateFormat)。他们有lots of problemsdesign issues,他们中的大多数都是由新API修复的(这就是为什么新类创建的原因,顺便说一下)。


IMO,它总是更好的日期/时间对象UTC内部工作 - 为最佳的类是Instant,它总是在UTC。因此,为了坚持数据库并进行内部操作,我总是倾向于使用UTC日期/时间,因为它可以减少混淆并避免不必要的转换。

当/如果你需要显示此日期/时间 - 给用户,或者在其他一些接口 - 你希望它是在一个特定的时区,那么你转换这个InstantZonedDateTime

例子:

// 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:002017-06-20T14:28:39.075+01:00在伦敦(注意:ZoneId已经采取的夏时制护理)。

另请注意,我使用了完整的时区名称(America/Sao_PauloEurope/London)。格式为Continent/City的这些名称由IANA database定义,并由新API使用。

你应该避免使用3个字母的时区的名称(如ECTCST),因为他们是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看到所有可能的格式。

+0

非常感谢您考虑的答案。关于如何将时间戳与发起代理的时区关联的另一个相关问题。假设我有一个接受订单的系统,并且我想使用“即时”存储订单的时间戳,如何最好地记录下订单的代理的时区?换句话说,他们是在圣保罗还是伦敦? – user2868835

+0

如果这是一个要求,@ user2868835也会存储一个'ZoneId'('ZoneId.systemDefault()'会给你JVM的设置)或者创建一个异常并存储'ZonedDateTime'而不是'Instant',这个会给你两个,你仍然可以根据需要随时转换。 –

+0

国际海事组织,最好在内部使用'Instant'工作,并将'ZoneId'存储在一个单独的字段中(所以,只在向用户显示日期时使用它(atZone(zoneid)'))。 – 2017-06-21 13:39:35

1

我希望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) ;