时区中立的应用程序




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

背景

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

  • 没有 TZ,+02就被剥离
  • 使用 TZ 执行-02校正以使其 UTC

现在有趣的是,当 JDBC 驱动程序加载值时:

  • 如果没有 TZ,存储的值由用户的 (JVM/OS) TZ 移动
  • 使用 TZ 时,该值被视为 UTC

在这两种情况下,您最终都会得到java.sql.Timestamp具有用户默认 TZ 的对象。

时区

没有 TZ 的时间戳非常有限。如果将两个系统连接到数据库,并且它们都具有不同的 TZ,则它们将以不同的方式解释时间戳。

您可以告诉 JDBC 在通过 ResultSet#getTimestamp(String, Calendar) 读取时间戳时应该使用哪种 TZ。摘自JavaDoc:

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

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

示例代码

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 );

相关内容

  • 没有找到相关文章

最新更新