バイナリファイル中に格納されている8バイトの日付データ(16進)を日付(Date型)に変換する方法を教えてください。
例)"6082D42A5A38C601”を与えると 2006/02/23 09:18:54 を返す関数
参考となるソース(cのようです。)
time_t win_time_to_unix( char *val ) {
unsigned long low, high;
double dbl;
time_t total;
char fourbytes[4];
fourbytes[0] = val[0];
fourbytes[1] = val[1];
fourbytes[2] = val[2];
fourbytes[3] = val[3];
low = bah_to_i( fourbytes, 4 );
fourbytes[0] = val[4];
fourbytes[1] = val[5];
fourbytes[2] = val[6];
fourbytes[3] = val[7];
high = bah_to_i( fourbytes, 4 );
dbl = ((double)high)*(pow(2,32));
dbl += (double)(low);
if ( dbl==0 ) {
return 0;
}
dbl *= 1.0e-7;
dbl -= 11644473600;
total = (double)dbl;
return total;
}
参考となるソース中の bah_to_i は,ASCII Hex を int に変換するローカル関数のようです。
unsigned int bah_to_i( char *val, int size ) {
int total;
int i;
total = 0;
for ( i=0; i < size; i++ ) {
total += ((unsigned char)val[i] << 8*i);
}
return total;
}
Cの入門本買ってきて2日間真面目に勉強すれば済む話では?
プログラミングの構造として共通する部分は多々あるから、
VBの知識しかない人でも動作が想像できるコードに思えますが?
既にそんなコードを手に入れてて、なんで何もしないのか理解
できません。
'6082D42A5A38C601
Dim B() As Byte = {&H60, &H82, &HD4, &H2A, &H5A, &H38, &HC6, &H01}
Dim D As Date = Date.FromFileTimeUtc(System.BitConverter.ToInt64(B, 0))
'2006/02/23 09:18:54.3420000
TextBox1.Text = D.ToString("yyyy\/MM\/dd HH:mm:ss.fffffff")
魔界の仮面弁士様ありがとうございました。できました。
ただし,CのソースをVB化という面では
dbl -= 11644473600の行と同等なコードで
値が 683790931698.0852225 と計算できましたが,それが何を意味する数値で,いかに日付型に変換するかというところで行き詰まっています。
dbl *= 1.0e-7;は,100ナノ秒単位を秒単位に変換しているようにも思えるのですが,仕組み自体が分からないのでお手上げです。
日付型の内部実装という意味に関していうと。
Unix では、「1970年1月1日 00:00:00からの経過秒数」で管理されます。
Windowsは、「1601年1月1日 00:00:00からの100ナノ秒単位の経過数」です。
> dbl *= 1.0e-7;は,100ナノ秒単位を秒単位に変換しているように
正解。
> dbl -= 11644473600の行と同等なコードで
ちなみに、 11644473600 の意味は、両者の日付型の基準日時の差です。
グレゴリオ暦では、1年 = 365.2425日ですよね。
http://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AC%E3%82%B4%E3%83%AA%E3%82%AA%E6%9A%A6
# 0.2425 = (1/4) - (1/100) + (1/400)
# = (4年毎の閏年, 100年毎の閏年回避, 400年毎の閏年回避の回避)
すなわち、[]をガウス記号(VB でいうところの Int関数)として、
[(1970年 - 1601年) * 365.2425日] * 24時間 * 60分 * 60秒
= Int(369 * 365.2425) * 86400
= 134774 * 86400
= 11644473600
という換算式です。
> 値が 683790931698.0852225 と計算できましたが
なんの値が?
> [(1970年 - 1601年) * 365.2425日] * 24時間 * 60分 * 60秒
> = Int(369 * 365.2425) * 86400
> = 134774 * 86400
> = 11644473600
>
> という換算式です。
上記の数値は、下記のようにして求める事もできます。蛇足までに。
Dim Diff As Double = #1/1/1970#.Subtract(#1/1/1601#).TotalSeconds
↑は間違っていました。
dbl = ((double)high)*(pow(2,32));
dbl += (double)(low);
まで実行すると
Windows ファイル時刻 127851599343420000が得られることが分かりました。
これは、魔界の仮面弁士様の
System.BitConverter.ToInt64(B, 0)の値と同じとわかりました。
ツイート | ![]() |