procedure TForm1.Button1Click(Sender: TObject);
var
Dt1: TDateTime;
Dt2: TDateTime;
Dt3: DWord;
begin
Dt1 := StrToDateTime('2009/08/31 00:00:00');
Dt2 := StrToDateTime('2009/08/31 01:00:00');
Dt3 := HoursBetween(Dt1, Dt2);
ShowMessage('Dt3 = ' + IntToStr(Dt3));
end;
この場合1という値が欲しいのですが、得られません。ヘルプには以下の説明があります
「説明
HoursBetween 関数を呼び出すと,2 つの TDateTime 値の差(時間数)を取得できます。
HoursBetween は,完全な時間(60 分)だけを数に入れます。
したがって,HoursBetween は午前 9 時と午前 9 時 59 分 59 秒の差を 0 として報告します。
この場合,1 としてカウントされるには 1 秒足りません。」
確かに動きとしてはTDateTime値の差を求めて切り捨てみたいなことしていますが、
この関数の使い方にとってこの仕様って何の役にも立たないんじゃないですか?
この関数の使い道を教えてください。
それから、欲しい結果(Dt1,Dt2の差を上記で「1」)を得る方法を
教えてください。
1:00と2:00の差は1ですが、0:00と1:00の差は0みたいですね。(Delphi7で確認しました。)
procedure TForm1.Button3Click(Sender: TObject);
var
d1, d2: TDateTime;
begin
d1 := IncHour(DateOf(Now()), 1); // 今日のAM1:00
d2 := IncHour(DateOf(Now()), 2); // 今日のAM2:00
ShowMessage('d1:' + DateTimeToStr(d1) + #13#10 +
'd2:' + DateTimeToStr(d2) + #13#10 +
'差:' + IntToStr(HoursBetween(d1, d2)));
d1 := DateOf(Now()); // 今日のAM0:00
d2 := IncHour(DateOf(Now()), 1); // 今日のAM1:00
ShowMessage('d1:' + DateTimeToStr(d1) + #13#10 +
'd2:' + DateTimeToStr(d2) + #13#10 +
'差:' + IntToStr(HoursBetween(d1, d2)));
end;
こんには.Mr.XRAYです.
既にレスがありますが,以下でもいけそうです.
テスト環境は,Windows XP(SP3) + Delphi 7 Pro です.
TDateTime型がDoubleのために生じる誤差ではないかと思われます.
そこで,DaySpan関数で計算した結果を用いるようにしてみました.
procedure TForm1.Button1Click(Sender: TObject);
var
Dt1 : TDateTime;
Dt2 : TDateTime;
SpanDay : Double;
Dt3 : Word;
begin
Dt1 := StrToDateTime('2009/08/31 00:00:00');
Dt2 := StrToDateTime('2009/08/31 01:00:00');
SpanDay := DaySpan(Dt1,Dt2);
Dt3 := HourOf(SpanDay);
ShowMessage('Dt3 = ' + IntToStr(Dt3));
end;
参考URL
http://mrxray.on.coocan.jp/bbs/DelphiBBS/mrxray_delphifan_coffe.cgi?tree=s1063#1063
パソコンの実数演算は最後の桁が切り捨てられるので、
0.9999999999999999999999999999999999999…
の無限小数を整数にする時に1ではなくて0になってしまうのは仕方ないね。
>Dt1 := StrToDateTime('2009/08/31 00:00:00');
>Dt2 := StrToDateTime('2009/08/31 01:00:00');
>Dt3 := HoursBetween(Dt1, Dt2);
>ShowMessage('Dt3 = ' + IntToStr(Dt3));
この結果を1にしたいなら、
Dt3 := HoursBetween(Dt1, IncMilliSecond(Dt2));
と、1ミリ秒だけ調整して差を計算すれば実用的には十分じゃないの?
--------------------------------------------------------------------
igy さん確認ありがとうございました。
--------------------------------------------------------------------
Mr.XRAY さんありがとうございます。
DaySpanは試してみました。
その結果から OneSecond の 1/2 を加えて判別しようとしていました。
HourOf は 0〜23 なので 2日だと48 という値が返ってきませんよね。
Date と Time 部に分けて計算しないといけないのでしょうか?
--------------------------------------------------------------------
宿命さん やはり調整してごまかすしかないのでしょうか?
--------------------------------------------------------------------
それから、いろいろ試してみて、
以下のコードで結果は[1]になったのですが
ある値のときはおかしくなるとか
これだとそのような問題はありますか?
var
Dt1: TDateTime;
Dt2: TDateTime;
Dt3: TDateTime;
Dt4: TDateTime;
Dt5: TDateTime;
begin
Dt1 := StrToDateTime('2009/08/31 00:00:00');
Dt2 := StrToDateTime('2009/09/01 01:00:00');
Dt3 := Dt1 * 24;
Dt4 := Dt2 * 24;
Dt5 := abs(Dt3 - Dt4);
ShowMessage('Dt5 = ' + FloatToStr(Dt5)); // [1]
end;
いろいろ試してみたところ、
DateTimeToStr を使って日付を表示してみると以下のようになりました。
小数点以下の部分は同じなのに結果が変わるのはどうしてでしょう?
32768.041666660876216 → 1989/09/17 1:00:00
32767.041666660876216 → 1989/09/16 0:59:59
憶測ですが、少数点15以下の数値が使用されていると
言う事になると思われます。
宿命 さんの表示されている様な感じです。
>0.9999999999999999999999999999999999999…
>この結果を1にしたいなら、
>Dt3 := HoursBetween(Dt1, IncMilliSecond(Dt2));
>と、1ミリ秒だけ調整して差を計算すれば実用的には十分じゃないの?
>宿命さん やはり調整してごまかすしかないのでしょうか?
これはごまかしではありません、この方法が正しい処理の仕方だと思います。
ソースを見ればいいのかもしれませんが、テストして見ました。
procedure TForm1.BitBtn2Click(Sender: TObject);
var Dt1:TDateTime;
begin
Dt1 := StrToDateTime(Edit1.text);
Edit2.Text:=Format ('%8.15f', [Dt1]);
end;
Edit1.text Edit2.text
1989/09/17 1:00:00 32768.041666666664200
1989/09/17 1:00:00.01 32768.041666678240300
1989/09/17 1:00:00.02 32768.041666689816300
1989/09/16 0:59:59 32767.041655092591100
1989/09/16 0:59:59.01 32767.041655104167100
>憶測ですが、少数点15以下の数値が使用されていると
>言う事になると思われます。
憶測は誤りでした。
テスト2
procedure TForm1.BitBtn3Click(Sender: TObject);
var i:Extended;
begin
Edit4.Text:=FormatDateTime('yyyy/mm/dd/hh:nn:ss:zzz',StrToFloat(Edit3.Text));
end;
Edit1.text Edit2.text
1989/09/16/ 00:59:59.000 -> 32767.041655092591100
1989/09/16/ 00:59:59.999 -> 32767.041666655091800
1989/09/16/ 01:00:00.000 -> 32767.041666666667900
Edit3.text Edit4.text
32767.041666660876216 -> 1989/09/16/00:59:59:999
32767.041666660876217 -> 1989/09/16/00:59:59:999
ツイート | ![]() |