选择显示字体大小

在db2 universal database中转换utc时间戳

简介

本文展示了一个 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">

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

背景

时间连续区间(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 语句就必须像下面这样简单:

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 编写转换函数,并在 db2java jdk 上运行该函数。

为了便于使用,我们将 java 类包装在了另一个 db2 udf 中。

解决方案细节

java 类有一个用来存储查找字典的类变量,其中包含了可能作为输入的每个地区所有可能的拼写和命名。

tz_map = new hashtable();… tz_map.put("eastern daylight", "est");tz_map.put("eastern standard time", "est");tz_map.put("america/new_york", "est");… 

例如,上面所有的键都对应于值 “est"。这就是类方法为了进行时间戳转换而在内部使用的值。

注意:这里鼓励为时区使用长名,例如 "america/new_york"。但是在这个特定的实现中,我们使用了短名称,因为 udb db2 version 7.2 使用的是 jdk 1.1.8,该版本只能使用短名称。

查找表的填充是手动完成的。我们花了很大的精力查找每个地区的内部 java 设置,并将具有相同 dst 规则和时区的长名与短名进行组对。

我们这样映射了 250 多个地区。如果需要的话,还可以添加新的映射。这样,在将新数据源与新的地区一起添加到数据仓库时,我们便有了所需的灵活性。

对于实际的时间戳转换,我们使用了下面的类方法:

public static java.lang.string j_convert_timezone(java.lang.string ivc_utctimestamp, java.lang.string ivc_timezone)

首先将输入的时间戳字符串解析成它的各个组成部分,并从那些值例化出一个 java 日历,然后通过格式转换器(formatter)产生一个新的转换后的时间戳。细微部分没有进行转换,直接变成输出,因为 java calendar 没有精确到那个程度。

可以用下面的语句将该 java 类方法注册成一个 udf 函数:

  public static java.lang.string j_convert_timezone(java.lang.string ivc_utctimestamp,  java.lang.string ivc_timezone) throws exception    {        // get the short name equivalent of the input        ivc_timezone = (string)tz_map.get(ivc_timezone);        if (ivc_timezone == null)            ivc_timezone = "gmt"; // default to utc if entry not found        // replace the . with - so that we only have one token separator instead of two        string ivc_utctimestamp_new = ivc_utctimestamp.replace('.', '-' );        // parse, validate and convert the ts string to integers, based on the one separator        stringtokenizer st = new stringtokenizer(ivc_utctimestamp_new, "-");        int year = integer.parseint(st.nexttoken());        int month = integer.parseint(st.nexttoken());        int day = integer.parseint(st.nexttoken());        int hour = integer.parseint(st.nexttoken());        int min = integer.parseint(st.nexttoken());        int sec = integer.parseint(st.nexttoken());        string micro = st.nexttoken(); // just carried over from the input        // create with the above a calendar in utc        calendar calutc = calendar.getinstance();        calutc.clear();        calutc.settimezone(timezone.gettimezone("gmt"));        calutc.set(year, month-1, day, hour, min, sec );        // prepare the formatter for the specified timezone        dateformat formatter = new simpledateformat("yyyy'-'mm'-'dd'-'hh.mm.ss", locale.us);        timezone tz = timezone.gettimezone(ivc_timezone);        formatter.settimezone(tz);        // return the new value        return formatter.format(calutc.gettime()) + "." + micro;    }

可以从 sql 中调用上面的 db2 udf,但是为了方便起见,我们创建另一个 db2 udf,将输入从 db2 时间戳转换成字符串,将输出从字符串转换回 db2 时间戳,这样输入和输出都是与 db2 兼容的时间戳。使用的代码如下:

create function acme.f_convert_timezone (        ipts_timestamp  timestamp,        ipch_timezone   varchar(30))returns timestampbegin atomic   declare vvch_result varchar(30);   set vvch_result = j_convert_timezone(char(ipts_timestamp), rtrim(ipch_timezone));   return case vvch_result      when 'null' then null      else timestamp(vvch_result)   end;end

最后,我们可以在下面这样简单的 sql 语句中调用该函数:

select acme.f_convert_timezone(transaction_timestamp, "america/nassau")from acme.transaction_table;

将来的改进和变化

我们可以很容易地添加下面这些更改,以增强这个解决方案:

注意: 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   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons