我需要在运行时更改DTO的每个时区。 今天,当用户在我的网络服务上执行请求时,时区由参数通知,我想知道是否可以为所有日期属性应用新时区。 我唯一不能用的是" TimeZone.setDefault(myTimeZone)"因为这种方式适用于所有JVM以及不同时区的用户如何存在这种解决方案是不可行的。
我正在尝试这样的事情:
Query query = em.createNativeQuery(SQL.toString(), AgendamentoDTO.class);
collection = query.setParameter(1, idEmpresa).getResultList();
for (Field atributo : AgendamentoDTO.class.getDeclaredFields()) {
if (atributo.getType().isAssignableFrom(Date.class)) {
//Change time zone here
}
}
韩国社交协会
答案 0 :(得分:0)
正如在问题中明智地建议的那样,您应该将JVM的当前默认时区设置为最绝望的情况下的最后手段。设置默认值会影响在该JVM中运行的所有应用程序的所有线程中的所有代码,并在执行时立即影响它们(!)。
相反,在所有日期时间工作中,始终将可选的时区参数传递给各种方法。永远不要隐式依赖JVM的当前默认区域。
与最早版本的Java捆绑在一起的旧的旧日期时间类已被证明设计糟糕,麻烦且令人困惑。避免他们。现在取代了java.time类。
因此,请使用java.util.Date
而不是java.time.Instant
。 Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds。这个Instant
类是日期时间处理的基本构建块。经常使用此类,因为您的业务逻辑,数据存储,数据交换和数据库工作都应该在UTC。不要将UTC视为时区的另一种变体,而是将UTC视为唯一的真实时间。在编程时,忘记你自己的当地时区,因为狭隘的思维会混淆你的编程。
Instant
一般来说,您的网络服务应该采用并给出UTC值。 Instant
类可以直接解析并生成字符串,以标准ISO 8601格式表示这些值。
Instant instant = Instant.parse( "2016-09-09T22:34:08Z" );
String output = instant.toString(); // Generates: 2016-09-09T22:34:08Z
因此无需操纵这些UTC值。把它们放在一边。数据提供服务应该在大多数情况下坚持使用UTC。
在你的情况下,作为DTOs的DTO应该坚持存储UTC值(Instant
对象或ISO 8601格式的字符串,UTC结尾为Z
。 。 By definition,DTO应该在缺乏业务对象的意义上“愚蠢”,而应该只是传输基本数据元素。使用这些DTO的其他对象应该处理任何所需的时区分配。
ZonedDateTime
仅在其他时区生成字符串以便向用户显示。在这里,我们指定一个魁北克时区来通过不同wall-clock time的镜头观察时刻。应用ZoneId
获取ZonedDateTime
。 ZonedDateTime
和Instant
都代表历史中同一时刻,时间轴上的相同点。
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
请注意,我们在业务对象中保留Instant
对象,未经修改。我们生成一个独特的单独对象ZonedDateTime
,用于不同的挂钟时间。
ZoneId
个对象。 continent/region
格式的proper IANA ‘tz’ time zone names,例如America/Montreal
或Pacific/Auckland
。切勿使用诸如EST
或IST
之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。 当您的网络服务提供数据作为数据而不是演示文稿时,请生成ISO 8601格式的字符串。默认情况下,java.time类使用这些标准格式来解析和生成字符串。只需调用toString
即可生成标准格式的字符串。请注意,ZonedDateTime
通过在方括号中附加时区名称来扩展标准格式。
String output = instant.toString(); // 2016-09-09T22:34:08Z
String output = zdt.toString(); // 2016-09-09T19:34:08-03:00[America/Montreal]
当您的网络服务向用户提供展示的信息而非作为数据消费时,请以适合用户的人类语言和文化规范的格式生成字符串。您可以指定特定格式。但通常最好让java.time自动为您定位。
Locale locale = Locale.CANADA_FRENCH;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l );
String output = zdt.format( f );