時間を取得するには


もうすぐ中級者  2009-08-31 20:11:09  No: 35551

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」)を得る方法を
教えてください。


igy  2009-08-31 20:47:32  No: 35552

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  2009-08-31 21:19:42  No: 35553

こんには.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


宿命  2009-08-31 21:20:00  No: 35554

パソコンの実数演算は最後の桁が切り捨てられるので、
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ミリ秒だけ調整して差を計算すれば実用的には十分じゃないの?


もうすぐ中級者  2009-09-01 00:19:06  No: 35555

--------------------------------------------------------------------
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;


もうすぐ中級者  2009-09-02 19:35:55  No: 35556

いろいろ試してみたところ、
DateTimeToStr を使って日付を表示してみると以下のようになりました。
小数点以下の部分は同じなのに結果が変わるのはどうしてでしょう?

32768.041666660876216 → 1989/09/17 1:00:00
32767.041666660876216 → 1989/09/16 0:59:59


TS  2009-09-02 19:57:29  No: 35557

憶測ですが、少数点15以下の数値が使用されていると
言う事になると思われます。
宿命 さんの表示されている様な感じです。
>0.9999999999999999999999999999999999999…

>この結果を1にしたいなら、
>Dt3 := HoursBetween(Dt1, IncMilliSecond(Dt2));
>と、1ミリ秒だけ調整して差を計算すれば実用的には十分じゃないの?

>宿命さん やはり調整してごまかすしかないのでしょうか?
これはごまかしではありません、この方法が正しい処理の仕方だと思います。


TS  2009-09-03 00:58:28  No: 35558

ソースを見ればいいのかもしれませんが、テストして見ました。
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


TS  2009-09-03 02:58:02  No: 35559

>憶測ですが、少数点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


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

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






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