2013-02-11 126 views
1

我有一个数据库表,它充满了来自ETL大型机的数据。 该表中的一列称为“TOD”,与时间一样。TOD时钟时间到java.util.Date或毫秒

此列存储的值,如: “CAE7631DC43DC686” “CAE7631C4AC6DC0B” “CAE6216DF2BC0D04” “CAE621D8F9916E8E”

所有这些值都是围绕2013年2月10日和2月11 2013年 现在,大型机,这是一个时间日期表示(TOD时钟)。

它表示从macintoshconds(1/1 000 000秒)中的01.01.1900过去的时间。

我需要的是一个可以将这些字符串转换为java.util.Date的java库/方法/算法实现。

在网上找到这些网站: http://paul.saers.com/Tod_howto.html http://www.longpelaexpertise.com.au/toolsTOD.php

本页说明如何计算的,但它是一个有点太适合我。 我敢肯定我会在某处做一些错误。

所以,我的问题是;你知道我可以使用的图书馆(乔达时间?)吗? 我需要将这些值转换为java.util.Date和Date对象以形成字符串(如“CAE621D8F9916E8E”)。

在此先感谢。

+0

是的,约达时间比Java的内置日期时间库更好:) – 2013-02-11 17:13:33

+2

我相信你的意思是 “微秒”。 – 2013-02-11 17:15:06

+0

像CAE7631DC43DC686这样的字符串代表什么? – 2013-02-11 17:16:24

回答

2

一步一步,使用约达:

在计算中使用的数据可以发现on the website you referred to该TOD以UTC表达的other reference you gave状态

// we start with your string minus the three last digits 
// which are some internal z/Series cruft 
BigInteger bi = new BigInteger ("CAE7631DC43DC", 16); // 686 stripped off 
// then, from tables the website we get the TOD value for start of epoch 
// here also, minus the three last digits         
BigInteger startOfEpoch70 = new BigInteger ("7D91048BCA000", 16); // 000 stripped off 
// using that we calculate the offset in microseconds in epoch 
BigInteger microsinepoch = bi.subtract(startOfEpoch70); 
// and reduce to millis 
BigInteger millisinepoch = microsinepoch.divide(new BigInteger("1000")); 
// which we convert to a long to feed to Joda 
long millisinepochLong = millisinepoch.longValue(); 
// Et voila, the result in UTC 
DateTime result = new DateTime(millisinepochLong).withZone(DateTimeZone.UTC); 
// Now, if you want a result in some other timezone, that's equally easy 
// with Joda: 
DateTime result2 = result.toDateTime(DateTimeZone.forID("EET")); 

System.out.println("The result is " + result + " or represented in timezone EET " 
        + result2); 

其中给出这个输出:

结果为2013-02-10T21:59:46.420Z或代表时区 EET 2013-02-10T23:59:46.420 + 02:00

的“克鲁夫特”我指的解释如下:

我们跳过最后12位(通常情况下,一些这些位都使用MVS告诉用来读取TOD什么处理器时钟和什么LPAR活动)。

当然,而不是粗暴剪断这些字节掉串,一个也可以做

bi = bi.divide(new BigInteger("1000", 16)); 

由十六进制1000分也将摆脱过去的12位。

编辑:正如穆罕默德在评论中指出的,TOD是UTC,这意味着应该告诉结果的DateTime。为了方便起见,我还展示了如何将DateTime转置到另一个时区(使用EET作为示例)

+0

谢谢!这真的有帮助。 – MehmetGunacti 2013-02-12 07:38:05

+0

太棒了!如果您可以验证我提供的信息是否正确,请通过接受答案来表明。这将有助于未来的游客。 – fvu 2013-02-12 08:45:26

+0

首先接受它,但后来发现在这里Java代码和IBM的Javascript页面之间有2小时的时差:http://www-01.ibm.com/support/docview.wss?uid=swg21240566。 Java代码输出:“结果是太阳2月10日23:59:46 EET 2013”​​Javascript输出:“2013年2月10日21:59:46.420700” – MehmetGunacti 2013-02-12 09:49:02

1

使用的BigInteger解析十六进制日期:

new BigInteger("CAE7631DC43DC686", 16); 

然后使用的BigInteger提供的各种方法(乘法,...)做必要的转换,以Unix纪元。

3

在我的使用案例中,我有一个getter方法,它直接读取8字节TOD作为字节数组,并将其转换为长整型,但在这里坚持海报:

BigInteger bi = new BigInteger ("CAE7631DC43DC686", 16); // no strip off of 686 
long tod = bi2.longValue(); 

我用下面避免BigDecimal的计算开销:

tod = tod >>> 12; // remove rightmost 3 bytes and replace with zeros 
tod = tod - 2208988800000000l; // substract 1970 
tod = tod/1000; // make millis out of micros 
// timeformatter and dateformatter without Joda 
SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm:ss.SS z Z", Locale.getDefault()); 
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()); 
// Display 
System.out.println(timeFormatter.format(new Date(tod))); 
System.out.println(dateFormatter.format(new Date(tod))); 

输出将是:

22:59:46.420 CET +0100

2013年2月10日