2

ETL を介してメインフレームからのデータで満たされたデータベース テーブルがあります。そのテーブルの 1 つの列は、Time-Of-Day のように「TOD」と呼ばれます。

この列には、「CAE7631DC43DC686」「CAE7631C4AC6DC0B」「CAE6216DF2BC0D04」「CAE621D8F9916E8E」などの値が格納されます。

これらの値はすべて、2013 年 2 月 10 日と 2013 年 2 月 11 日の前後です。現在、メインフレームでは、これは日時表現 (TOD クロック) です。

1900 年 1 月 1 日から経過した時間をマクロ秒 (1/1 000 000 秒) で表します。

私が必要としているのは、これらの文字列を java.util.Date のものに変換できる Java ライブラリ / メソッド / アルゴリズムの実装です。

Web でこれらのサイトを見つけました: http://paul.saers.com/Tod_howto.html http://www.longpelaexpertise.com.au/toolsTOD.php

このページでは計算方法を説明していますが、私には少し多すぎます。どこかで間違いを犯すと思います。

だから、私の質問は; 私が使用できるライブラリ (Joda Time ?) について知っていますか? これらの値を java.util.Date に変換し、Date オブジェクトを文字列表現 (「CAE621D8F9916E8E」など) に変換する必要があります。

前もって感謝します。

4

3 に答える 3

4

私の使用例では、8 バイトの TOD をバイト配列として直接読み取り、それを long に変換する getter メソッドがありますが、ここではポスターに準拠しています。

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

10.02.2013

于 2015-09-24T07:10:21.040 に答える
2

Joda を使用して段階的に:

計算に使用されたデータは、あなたが参照したウェブサイトで見つけることができます。

// 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 ビットはスキップします (通常、これらのビットの一部は、TOD クロックの読み取りにどのプロセッサーが使用され、どの LPAR がアクティブであったかを知るために MVS によって使用されます)。

もちろん、これらのバイトを文字列から残酷に切り取る代わりに、次のこともできます。

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

16 進数の 1000 で割ると、最後の 12 ビットも取り除かれます。

編集: Mehmet がコメントで指摘したように、TOD は UTC であり、これは、結果の DateTime がそのように伝えられる必要があることを意味します。便宜上、その DateTime を別のタイム ゾーンに転置する方法も示しましEETた (例として使用)。

于 2013-02-11T18:08:22.280 に答える
1

BigInteger を使用して 16 進数の日付を解析します。

new BigInteger("CAE7631DC43DC686", 16);

次に、BigInteger が提供するさまざまなメソッド (乗算など) を使用して、必要な Unix エポックへの変換を行います。

于 2013-02-11T17:31:34.127 に答える