Java 时区中性应用程序

Java 时区中性应用程序,java,postgresql,datetime,timezone,Java,Postgresql,Datetime,Timezone,我们在JAVA和J2EE产品上运行应用程序,并使用postgres作为数据库服务器,在设计过程中,架构师犯了一个错误,将所有日期和时间列存储在本地时区(IST)中。现在应用程序的用户要求在本地区显示所有时间。来自伦敦的用户希望应用程序以格林尼治标准时间显示所有日期和时间。是否有任何解决方案或方法最适合在这里进行最小更改。另外,我认为在这里使用Java时间或JODA时间将不会有帮助,因为我需要做更多的工作 1) 正在考虑将所有现有日期和时间转换为UTC(简单、可行且更易于实施) 2) 我将如何处理


我们在JAVA和J2EE产品上运行应用程序,并使用postgres作为数据库服务器,在设计过程中,架构师犯了一个错误,将所有日期和时间列存储在本地时区(IST)中。现在应用程序的用户要求在本地区显示所有时间。来自伦敦的用户希望应用程序以格林尼治标准时间显示所有日期和时间。
是否有任何解决方案或方法最适合在这里进行最小更改。另外,我认为在这里使用Java时间或JODA时间将不会有帮助,因为我需要做更多的工作
1) 正在考虑将所有现有日期和时间转换为UTC(简单、可行且更易于实施)
2) 我将如何处理显示部分,因为在搜索屏幕中,我们不仅允许用户选择日期,还允许用户选择时间来查找所有匹配的事务,并且这里的时间假定为用户的本地时间。

Background 在Postgres中,
TIMESTAMP
TIMESTAMP WITH TIMEZONE
以相同的方式存储-自Postgres epoch(2000-01-01)以来的秒数。主要区别在于Postgres在保存时间戳值时所做的操作,例如
2004-10-19 10:23:54+02

  • 没有TZ,
    +02
    就被剥离了
  • 对于TZ,执行
    -02
    校正,使其成为UTC
现在有趣的是,当JDBC驱动程序加载值时:

  • 如果没有TZ,存储值将由用户的(JVM/OS)TZ移位
  • 对于TZ,该值被视为UTC
在这两种情况下,最终都会得到带有用户默认TZ的
java.sql.Timestamp
对象

时区 没有TZ的时间戳非常有限。如果有两个系统连接到数据库,它们都具有不同的TZ,那么它们对时间戳的解释将不同

您可以通过读取时间戳时使用什么类型的TZ。摘自JavaDoc:

如果基础数据库不存储时区信息,此方法使用给定的日历为时间戳构造适当的毫秒值

一旦有了时间戳(在没有TZ的情况下),现在就可以可靠地使用Joda Time。Joda Time提供各种内置格式化程序,您也可以定义自己的格式化程序。但对于编写日志或报告,最好的选择可能是ISO 8601格式。这种格式恰好是Joda Time和java.Time使用的默认格式

示例代码

背景 在Postgres中,
TIMESTAMP
TIMESTAMP WITH TIMEZONE
以相同的方式存储-自Postgres epoch(2000-01-01)以来的秒数。主要区别在于Postgres在保存时间戳值时所做的操作,例如
2004-10-19 10:23:54+02

  • 没有TZ,
    +02
    就被剥离了
  • 对于TZ,执行
    -02
    校正,使其成为UTC
现在有趣的是,当JDBC驱动程序加载值时:

  • 如果没有TZ,存储值将由用户的(JVM/OS)TZ移位
  • 对于TZ,该值被视为UTC
在这两种情况下,最终都会得到带有用户默认TZ的
java.sql.Timestamp
对象

时区 没有TZ的时间戳非常有限。如果有两个系统连接到数据库,它们都具有不同的TZ,那么它们对时间戳的解释将不同

您可以通过读取时间戳时使用什么类型的TZ。摘自JavaDoc:

如果基础数据库不存储时区信息,此方法使用给定的日历为时间戳构造适当的毫秒值

一旦有了时间戳(在没有TZ的情况下),现在就可以可靠地使用Joda Time。Joda Time提供各种内置格式化程序,您也可以定义自己的格式化程序。但对于编写日志或报告,最好的选择可能是ISO 8601格式。这种格式恰好是Joda Time和java.Time使用的默认格式

示例代码


您在数据库中使用的数据类型是什么?没有时区的时间戳?带时区的时间戳?我们使用带时区的时间戳。那么这不重要-假设您的数据库中有一个时间戳,例如
02-March-2016 17:51 IST
,使用JDBC,您将得到一个Java
时间戳
对象,它没有时区信息。然后,你可以创建一个日历(如果你真的想坚持使用传统的api,我不推荐),使用你喜欢的任何时区,例如
2016-03-02T12:21Z
…明白你的意思了,但它将解决仅对一个时区用户显示的问题,如果我从不同的时区获取用户,该怎么办?在系统中,我们还允许用户根据日期和时间搜索事务,系统将如何处理它。我不明白你在说什么-你可以在java代码中使用你想要的任何时区,而不管数据库中使用的时区。我建议您展示一个示例,其中包含数据库中存储的日期以及用于检索和显示该日期的代码。您在数据库中使用的数据类型是什么?没有时区的时间戳?带时区的时间戳?我们使用带时区的时间戳。那么这不重要-假设您的数据库中有一个时间戳,例如
02-March-2016 17:51 IST
,使用JDBC,您将得到一个Java
时间戳
对象,它没有时区信息。然后,你可以创建一个日历(如果你真的想坚持使用传统的api,我不推荐),使用你喜欢的任何时区,例如
2016-03-02T12:21Z
…明白你的意思了,但它将解决仅对一个时区用户显示的问题,如果我从不同的时区获取用户,该怎么办?在系统中,我们还允许用户根据日期和时间搜索事务,系统将如何处理它。我不明白你在说什么-你可以在java代码中使用你想要的任何时区,而不管数据库中使用的时区。我建议您展示一个带有日期的示例
java.sql.Timestamp timestamp = resultSet.getTimestamp(i);

DateTime dateTimeUtc = new DateTime( DateTimeZone.UTC ); // Defaults to now, this moment.

// Convert as needed for presentation to user in local time zone.
DateTimeZone timeZone = DateTimeZone.forID("Europe/Paris");
DateTime dateTimeZoned = dateTimeUtc.toDateTime( timeZone );