バイナリ中の 8 byteの ASCII Hex を日付に変換するには?

解決


素人さん  2006-02-24 23:30:55  No: 130412

バイナリファイル中に格納されている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;
}


素人さん  2006-02-24 23:44:41  No: 130413

参考となるソース中の 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;
}


特攻隊長まるるう  2006-02-25 03:58:04  No: 130414

Cの入門本買ってきて2日間真面目に勉強すれば済む話では?

プログラミングの構造として共通する部分は多々あるから、
VBの知識しかない人でも動作が想像できるコードに思えますが?
既にそんなコードを手に入れてて、なんで何もしないのか理解
できません。


魔界の仮面弁士  2006-02-25 06:17:14  No: 130415

'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")


素人さん  2006-02-28 22:33:51  No: 130416

魔界の仮面弁士様ありがとうございました。できました。
ただし,CのソースをVB化という面では
dbl -= 11644473600の行と同等なコードで
値が 683790931698.0852225 と計算できましたが,それが何を意味する数値で,いかに日付型に変換するかというところで行き詰まっています。
dbl *= 1.0e-7;は,100ナノ秒単位を秒単位に変換しているようにも思えるのですが,仕組み自体が分からないのでお手上げです。


魔界の仮面弁士  2006-03-01 00:08:32  No: 130417

日付型の内部実装という意味に関していうと。

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 と計算できましたが
なんの値が?


魔界の仮面弁士  2006-03-01 00:19:48  No: 130418

> [(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


素人さん  2006-03-01 01:04:05  No: 130419

↑は間違っていました。
  dbl = ((double)high)*(pow(2,32));
  dbl += (double)(low);
まで実行すると
Windows ファイル時刻  127851599343420000が得られることが分かりました。
これは、魔界の仮面弁士様の
System.BitConverter.ToInt64(B, 0)の値と同じとわかりました。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加