ブログ カレンダー

« « 2024 4月 » »
31 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 1 2 3 4

カテゴリ一覧

アーカイブ

最新のエントリ

最新のコメント

最新のトラックバック

趣味のブログ - Zipper.pp のバグ

Zipper.pp のバグ

カテゴリ : 
Lazarus
執筆 : 
OhYeah! 2013.12.03 21:02
 Lazarus の Zipper ユニットは、実に簡単に ZIP アーカーブの圧縮/解凍ができる優れたクラスライブラリです。が、TUnZipper で解凍したときに、解凍されたファイルのタイムスタンプがおかしいことに気づきました。具体的には、日付と分秒は OK なんですが、時だけがオリジナルファイルのタイムスタンプと異なります。
 ソースを追ってみると、タイムスタンプは ZipDateTimeToDateTime 手続きで内部形式から TDateTime 形式に変換されています。んで、よくよく見ると、時を計算するときに 12 bit も右シフトしてるので、残り 4bit しかなく、これじゃあ 0~15 時までしか表現できません(1bit 余分に右シフトされているので、実際には時の半分の値になります)。正式には、秒 5bit (本来は 6bit 必要だが偶数秒のみ表現することで 5bit に圧縮)、分 6bit、時 5bit なので、11bit 右シフトするのが正解です。
 ついでに、H は最上位の 5bit なので、11bit 右シフトすれば、31 でマスクする必要はないですね。

Procedure ZipDateTimeToDateTime(ZD,ZT : Word;out DT : TDateTime);

Var
  Y,M,D,H,N,S,MS : Word;

begin
  MS:=0;
  S:=(ZT and 31) shl 1;
  N:=(ZT shr 5) and 63;
  H:=(ZT shr 12) and 31; // この行が間違い H:=ZT shr 11; が正しい
  D:=ZD and 31;
  M:=(ZD shr 5) and 15;
  Y:=((ZD shr 9) and 127)+1980;

  if M < 1 then M := 1;
  if D < 1 then D := 1;
  DT:=ComposeDateTime(EncodeDate(Y,M,D),EncodeTime(H,N,S,MS));
end;

トラックバック

トラックバックpingアドレス http://www.o-ya.net/modules/d3blog/tb.php/54

コメント一覧

OhYeah!  投稿日時 2015.02.16 22:51 | 最終変更
Lazarus 1.2.6 では、ここに書いたとおり、下記のように修正されていました。
  H:=ZT shr 11;