2013-02-11 288 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日