不解:日期時間的相減 |
尚未結案
|
chuanchuan
一般會員 ![]() ![]() 發表:11 回覆:15 積分:5 註冊:2004-05-18 發送簡訊給我 |
|
l630521
資深會員 ![]() ![]() ![]() ![]() ![]() 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
function YearsBetween(const ANow, AThen: TDateTime): Integer;
function MonthsBetween(const ANow, AThen: TDateTime): Integer;
function WeeksBetween(const ANow, AThen: TDateTime): Integer;
function DaysBetween(const ANow, AThen: TDateTime): Integer;
function HoursBetween(const ANow, AThen: TDateTime): Int64;
function MinutesBetween(const ANow, AThen: TDateTime): Int64;
function SecondsBetween(const ANow, AThen: TDateTime): Int64;
function MilliSecondsBetween(const ANow, AThen: TDateTime): Int64;
如果你要算小時,請用HoursBetween... Ian
|
change.jian
版主 ![]() ![]() ![]() ![]() ![]() 發表:29 回覆:620 積分:439 註冊:2003-06-02 發送簡訊給我 |
剛好今天有用到HoursBetwee函數,順便提一下心得,發現這個函數會有bug,當傳入的兩個日期剛好跨一天時,會回傳錯誤的小時數目,如'093/06/06 21:30'與'093/06/07 22:30'時,回傳的竟是24,應該是25才是. 所以,最後乾脆自己寫,將時間轉以DateTimeToTimeStamp函數轉成TTimeStamp後,再去做自己要的計算. 底下是TTimeStamp的說明:
type TTimeStamp = record Time: Integer; { Number of milliseconds since midnight } Date: Integer; { One plus number of days since 1/1/0001 } end; |
Chance36
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
chuanchuan 你好
我用以下程式不會有你說的問題 procedure TForm1.BitBtn2Click(Sender: TObject); Var Str : String ; i, j : Integer; D1,D2 : TDateTime ; begin D2 := strToDateTime('2004/06/08 12:00'); D1 := strToDateTime('2004/06/07 12:00'); // D1 := strToDateTime('2004/06/07 12:00:01'); Label1.Caption := FloatToStr(D2-D1); // ====> 1 Label2.Caption := IntToStr(Trunc((D2-D1)*24));// ====> 24 Label3.Caption := IntToStr(HoursBetween(D1,D2));// ==== > 24 end; 但如上紅色部份就會得到你所述的答案 23 了,因為有了1秒的誤差所以日數為0.999998...是正常的。引言: 小弟想不出解決之道,土法加上 0.00001 先能用再說~~萬一兩個時間差不是1秒呢?加上0.00001還是不够,我覺得應該要有個容許誤差才對,最常用的就是四捨五入法 Label2.Caption := IntToStr(Trunc((D2-D1)*24 0.5));// 四捨五入====> 24 |
chuanchuan
一般會員 ![]() ![]() 發表:11 回覆:15 積分:5 註冊:2004-05-18 發送簡訊給我 |
感謝大家~~
(d2-d1)*24 是小時數,因此不能四捨五入,因為算法是:
如果加班不滿一小時就不算,5.6小時還是算5小時,
而d2-d1是日數,我+0.000001再*24是因為,二時間差為
5小時59分時(使用者輸入精確度只到[分]),
即使加上0.00001也不會變成6小時,因此我才如此用
當然,這不是正統的方式. D2 := strToDateTime('2004/06/08 12:00');
D1 := strToDateTime('2004/06/07 12:00');
Label1.Caption := FloatToStr(D2-D1); // ====> 1
Label2.Caption := IntToStr(Trunc((D2-D1)*24));// ====> 24
以上是對的,但是請試
D2 := strToDateTime('2004/06/08 13:00');
D1 := strToDateTime('2004/06/07 12:00');
Label2.Caption := IntToStr(Trunc((D2-D1)*24));// ====> 24
多了一小時,但結果還是24 所以問題在此 至於HoursBetween 不讓我用,為何?搜尋HoursBetween也找不到任何資料
不會吧 ~~~
< >< >
|
l630521
資深會員 ![]() ![]() ![]() ![]() ![]() 發表:15 回覆:349 積分:372 註冊:2003-02-17 發送簡訊給我 |
|
Chance36
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
chuanchuan 你好
四捨五入不行改為58捨59入,總之還是有容許誤差(1分鐘的誤差) Var D1,D2 : TDateTime ; Dist : Double; begin Dist := 1/(24*60) ; // 誤差為1分鐘 D2 := strToDateTime('2004/06/08 13:00'); D1 := strToDateTime('2004/06/07 12:00'); ShowMessage(IntToStr(Trunc((D2-D1)*24 Dist)));// ====> 25 end; PS:HoursBetween於Delphi5沒有,Delphi7有, |
chuanchuan
一般會員 ![]() ![]() 發表:11 回覆:15 積分:5 註冊:2004-05-18 發送簡訊給我 |
1.感謝I630521 提醒用uses DateUtils; HoursBetween能用了
但是用起來,跟(D2-D1)*24結果是一樣,有BUG,所以放棄~~
2.版主chance36所提是可行的
Dist := 1/(24*60) ; // 誤差為1分鐘
D2 := strToDateTime('2004/06/08 13:00');
D1 := strToDateTime('2004/06/07 12:00');
ShowMessage(IntToStr(Trunc((D2-D1)*24 Dist)));
相當等於(D2-D1)*24 0.00069 誤差一分鐘
跟本人所用土法(D2-D1 0.000001)*24 算法類似(約誤差一秒)
二者試了都可以,總算 0.000001找到了依據~謝謝~
3.至於版主change.jian的用法,小弟功力不夠,不懂,暫不追高.
4.最後小弟決定用(D2-D1)*24 0.00001 (誤差一秒),因為在此例
本人是以使用者輸入來計算,因為誤差分或秒結果一樣,若是
用抓系統日期時間來算,恐怕會有問題,為免生枝節,決定用
(D2-D1)*24 0.00001 ,謝謝大家~~
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |