Java - 更改我班级中所有属性的时区

时间:2016-09-09 03:50:36

标签: java date timezone

我需要在运行时更改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
    }
}

韩国社交协会

1 个答案:

答案 0 :(得分:0)

避免设置默认时区

正如在问题中明智地建议的那样,您应该将JVM的当前默认时区设置为最绝望的情况下的最后手段。设置默认值会影响在该JVM中运行的所有应用程序的所有线程中的所有代码,并在执行时立即影响它们(!)。

相反,在所有日期时间工作中,始终将可选的时区参数传递给各种方法。永远不要隐式依赖JVM的当前默认区域。

避免旧的日期时间类

与最早版本的Java捆绑在一起的旧的旧日期时间类已被证明设计糟糕,麻烦且令人困惑。避免他们。现在取代了java.time类。

因此,请使用java.util.Date而不是java.time.InstantInstant类代表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获取ZonedDateTimeZonedDateTimeInstant都代表历史中同一时刻,时间轴上的相同点。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

请注意,我们在业务对象中保留Instant对象,未经修改。我们生成一个独特的单独对象ZonedDateTime,用于不同的挂钟时间。

  • 在代码中进行这些时区分配时,请传递ZoneId个对象。
  • 通过Web服务API指定这些时区分配时,请将时区名称作为字符串传递。始终使用continent/region格式的proper IANA ‘tz’ time zone names,例如America/MontrealPacific/Auckland。切勿使用诸如ESTIST之类的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 );
相关问题