简介 执行这种转换时遇到的两个主要挑战是: 对于包含来自很多不同应用程序和分布在几个洲的地区的数据的数据仓库项目,经验证明,在转换方面,该函数对于 extract transform load (etl) 在分析和处理数据时需要用到的过程极其有用。 背景
本文展示了一个 db2 用户定义函数(udf)的 java 实现的设计,该函数有两个输入参数:一个 utc 时间戳(例如 2004-04-04-04.00.00.000000)和一个地区名(例如 "america/guayaquil"),并返回新地区中对应的时间戳(在这里是 2004-04-03-23.00.00.000000)。
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">
时间连续区间(time continuum)内的某个惟一时刻可以由那一刻的 xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">日期、 xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">时间来定义,为了更精确起见,还可以加上 xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">秒后面的小数。这种定义叫做 xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">时间戳,它在 db2 中的 iso 表示如下: 2004-07-24-16.18.28.410002
在这种情况下,精确度可以下调为 1 微秒。
在一个与某个事务有关的事件发生时记录下时间戳,这一活动就叫做为该事务“记录时间戳(timestamping)”。在一个事务的整个生命周期内,需要多次记录时间戳,以便记下创建、最后一次修改、最后一次访问某一事务的时间。
对于发生在多个地理位置和多个地区的集中存储事务,常见的设计是用与该地区时间对应的世界协调时间(universal time coordinated,utc)记下每个时间戳记录。通过同时记录下事务发生时所在的位置,例如存储事务发生时所在的客户号或业务部门号,可以重新构造该事务的本地时间。
当必须处理、分析和报告来自大量不同来源的数据时,我们需要重新构造 utc 时间戳在事务原始位置的本地时间。常被问到的问题有:
xmlns:dw="http://www.ibm.com/developerworks/" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance">
挑战
表面上看起来既简单又容易完成的任务,事实上被证明是既不简单也不容易完成。
从本地时间到 utc 时间的实时转换通常是在应用程序中完成的。它只能用于当前时间(而不能用于过去或将来的任何时间点),并且只能用于应用程序运行时其服务器所在的地区(而不是任何其他地区)。
我们遇到的一个挑战是理解我们所接收到的地区名:
另一个挑战是实现我们处理的所有地区的夏令时(daylight savings time,dst)规则 —— 这些规则我们还不能轻松地使用。
还有一个需求就是能够很容易地使用用来调用转换函数的 api。
例如,为了得到一个 utc 时间戳在 "america/nassau" 的本地时间,一家虚构的 acme intl. 公司使用的 select 语句就必须像下面这样简单:
|
解决方案
有些数据源是由 java 应用程序填充的,因此每个应用程序用于这些数据源的名称可以是不同 java jdk 版本(1.1.8、1.4 等)的名称。由于 java jdk 已经为一组相当全面的地区的所有 dst 规则编写了代码,因此我们选择用 java 编写转换函数,并在 db2 的 java jdk 上运行该函数。
为了便于使用,我们将 java 类包装在了另一个 db2 udf 中。
解决方案细节
java 类有一个用来存储查找字典的类变量,其中包含了可能作为输入的每个地区所有可能的拼写和命名。
|
例如,上面所有的键都对应于值 “est"。这就是类方法为了进行时间戳转换而在内部使用的值。
注意:这里鼓励为时区使用长名,例如 "america/new_york"。但是在这个特定的实现中,我们使用了短名称,因为 udb db2 version 7.2 使用的是 jdk 1.1.8,该版本只能使用短名称。
查找表的填充是手动完成的。我们花了很大的精力查找每个地区的内部 java 设置,并将具有相同 dst 规则和时区的长名与短名进行组对。
我们这样映射了 250 多个地区。如果需要的话,还可以添加新的映射。这样,在将新数据源与新的地区一起添加到数据仓库时,我们便有了所需的灵活性。
对于实际的时间戳转换,我们使用了下面的类方法:
|
首先将输入的时间戳字符串解析成它的各个组成部分,并从那些值例化出一个 java 日历,然后通过格式转换器(formatter)产生一个新的转换后的时间戳。细微部分没有进行转换,直接变成输出,因为 java calendar 没有精确到那个程度。
可以用下面的语句将该 java 类方法注册成一个 udf 函数:
|
可以从 sql 中调用上面的 db2 udf,但是为了方便起见,我们创建另一个 db2 udf,将输入从 db2 时间戳转换成字符串,将输出从字符串转换回 db2 时间戳,这样输入和输出都是与 db2 兼容的时间戳。使用的代码如下:
|
最后,我们可以在下面这样简单的 sql 语句中调用该函数:
|
将来的改进和变化
我们可以很容易地添加下面这些更改,以增强这个解决方案:
注意: utc 正逐渐成为大家喜爱的 greenwich mean time (gmt) 的同义词。
结束语
在数据仓库项目的 etl 过程中,将时间戳从一个地区转换为另一个地区的函数被证明是转换方面的主力。本文提供了以 udb db2 udf 的形式运行的这类 java 函数的代码。
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器