技术开发 频道

在DB2数据库中转换UTC时间戳

【IT168 技术文档】

  简介

  本文展示了一个 DB2 用户定义函数(UDF)的 Java 实现的设计,该函数有两个输入参数:一个 UTC 时间戳(例如 2004-04-04-04.00.00.000000)和一个地区名(例如 "America/Guayaquil"),并返回新地区中对应的时间戳(在这里是 2004-04-03-23.00.00.000000)。

  执行这种转换时遇到的两个主要挑战是:

  要支持某个地区可能出现的所有不同名称,以及可能作为输入参数传入的所有不同地区。
对于每个地区,要计算出夏令时(daylight savings time)规则。

  对于包含来自很多不同应用程序和分布在几个洲的地区的数据的数据仓库项目,经验证明,在转换方面,该函数对于 Extract Transform Load (ETL) 在分析和处理数据时需要用到的过程极其有用。

  背景

  时间连续区间(time continuum)内的某个惟一时刻可以由那一刻的 日期、 时间来定义,为了更精确起见,还可以加上 秒后面的小数。这种定义叫做 时间戳,它在 DB2 中的 ISO 表示如下:

  2004-07-24-16.18.28.410002

  在这种情况下,精确度可以下调为 1 微秒。

  在一个与某个事务有关的事件发生时记录下时间戳,这一活动就叫做为该事务“记录时间戳(timestamping)”。在一个事务的整个生命周期内,需要多次记录时间戳,以便记下创建、最后一次修改、最后一次访问某一事务的时间。

  对于发生在多个地理位置和多个地区的集中存储事务,常见的设计是用与该地区时间对应的世界协调时间(Universal Time Coordinated,UTC)记下每个时间戳记录。通过同时记录下事务发生时所在的位置,例如存储事务发生时所在的客户号或业务部门号,可以重新构造该事务的本地时间。

  当必须处理、分析和报告来自大量不同来源的数据时,我们需要重新构造 UTC 时间戳在事务原始位置的本地时间。常被问到的问题有:

  我知道 UTC 时间,但是客户的本地时间是什么呢?
  是上午还是下午?
  是在我们的地理区域的工作时间之内,还是在该工作时间之外?
  其他问题。

  挑战

  表面上看起来既简单又容易完成的任务,事实上被证明是既不简单也不容易完成。

  从本地时间到 UTC 时间的实时转换通常是在应用程序中完成的。它只能用于当前时间(而不能用于过去或将来的任何时间点),并且只能用于应用程序运行时其服务器所在的地区(而不是任何其他地区)。

  我们遇到的一个挑战是理解我们所接收到的地区名:

  对于同一个地区,我们数据仓库的每个数据源都为我们提供了不同的名称,例如 Eastern Daylight、Eastern Standard Time、America/New_York、EST 等 —— 其实意思都是一样。
  每个数据源都处理一组不同的地区。例如,某个数据源只有 North American 地区,而其他数据源在欧洲也有办事处,因而就需要一个更大的地区列表。
  另一个挑战是实现我们处理的所有地区的夏令时(Daylight Savings Time,DST)规则 —— 这些规则我们还不能轻松地使用。

  还有一个需求就是能够很容易地使用用来调用转换函数的 API。

  例如,为了得到一个 UTC 时间戳在 "America/Nassau" 的本地时间,一家虚构的 Acme Intl. 公司使用的 SELECT 语句就必须像下面这样简单:

  SELECT ACME.F_CONVERT_TIMEZONE(TRANSACTION_TIMESTAMP, "America/Nassau")
  FROM ACME.TRANSACTION_TABLE;

  解决方案

  有些数据源是由 Java 应用程序填充的,因此每个应用程序用于这些数据源的名称可以是不同 Java JDK 版本(1.1.8、1.4 等)的名称。由于 Java JDK 已经为一组相当全面的地区的所有 DST 规则编写了代码,因此我们选择用 Java 编写转换函数,并在 DB2 的 Java JDK 上运行该函数。

  为了便于使用,我们将 Java 类包装在了另一个 DB2 UDF 中。

0
相关文章