2011-11-22 60 views
4

我正在建立一個倒計時到某個日期/時間的東西。我有它的工作 - 至少小時,分鐘和秒工作正常。我的問題是當我嘗試實施天時,它沒有給出正確的結果。我知道DateUtils的單元,但那裏有很多東西,我不知道該怎麼做,特別是因爲我數學很糟糕。日期/時間操縱友好的倒計時字符串

我有一個間隔爲100的計時器。然後我有一個全球的fDestDT爲目標日期/時間倒計時的基礎。在計時器中,我有一個名爲DT的本地TDateTime。然後,我打破它分爲多個字符串,並把他們重新走到一起進1「友好」串...

procedure TForm1.TmrTimer(Sender: TObject); 
var 
    DT: TDateTime; 
    D, H, N, S: String; 
    Str: String; 
begin 
    DT:= fDestDT - Now; //fDest = destination date/time of countdown 
    //Need to format only plural numbers with 's' 
    D:= FormatDateTime('d', DT)+' Days'; //Get number of days 
    H:= FormatDateTime('h', DT)+' Hours'; //Get number of hours 
    N:= FormatDateTime('n', DT)+' Minutes'; //Get number of minutes 
    S:= FormatDateTime('s', DT)+' Seconds'; //Get number of seconds 
    Str:= D+', '+H+', '+N+', '+S;   //Build friendly string 
    if lblTitle.Caption <> Str then 
    lblTitle.Caption:= Str;    //Update caption only if it's changed 
end; 

應該出來像...

0 Days, 3 Hours, 1 Minute, 12 Seconds

但相反的日子都出現了錯誤,當倒計時的日期/時間是今天的日期,它顯示30天......

30 Days, 3 Hours, 1 Minute, 12 Seconds

我想,如果我提前一個多月,它也不會正確顯示。我如何正確獲取天數? DateUtils單元中有沒有什麼能比我已經更好地自動化大部分工作?編輯: 固定!問題是我很愚蠢地用DT:= fDestDT - Now;減去,這在我的第一個代碼片段中是正確的,但是在轉換爲使用DateUtils.DaysBetween代替之後,我需要刪除該減法,並且僅設置DT:= Now;

工作代碼:

procedure TForm1.TmrTimer(Sender: TObject); 
var   
    DT: TDateTime; 
    Days, Hours, Mins, Secs: Word; 
    SDays, SHours, SMins, SSecs: String; 
    Str: String; 
begin  
    DT:= Now; 
    Days:= DaysBetween(DT, fDestDT); 
    Hours:= HoursBetween(fDestDT, DT) mod 24; // Remove total days 
    Mins:= MinutesBetween(DT, fDestDT) mod 60; 
    Secs := SecondsBetween(DT, fDestDT) mod 60; 
    if Days = 1 then SDays:= 'Day' else SDays:= 'Days'; 
    if Hours = 1 then SHours:= 'Hour' else SHours:= 'Hours'; 
    if Mins = 1 then SMins:= 'Minute' else SMins:= 'Minutes'; 
    if Secs = 1 then SSecs:= 'Second' else SSecs:= 'Seconds'; 
    Str:= Format('%d '+SDays+' %d '+SHours+' %d '+SMins+' %d '+SSecs, 
    [Days, Hours, Mins, Secs]); 
    if lblTime.Caption <> Str then 
    lblTime.Caption:= Str; 
end; 

回答

7

DaysBetweenHoursBetweenMinutesBetween,並且SecondsBetweenDateUtils 。你必須做一些小數學。 :)

下面是一個示例控制檯應用程序演示:

program Project2; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils, DateUtils; 

procedure ShowTimeDiff(const StartDate, OldDate: TDateTime); 
var 
    Days, Hours, Mins, Secs: Word; 
    OutputText: string; 
begin 
    Writeln(Format('Start: %s, Old: %s', 
     [FormatDateTime('mm/dd/yyyy hh:nn:ss', StartDate), 
     FormatDateTime('mm/dd/yyyy hh:nn:ss', OldDate)])); 
    Days := DaysBetween(StartDate, OldDate); 
    Hours := HoursBetween(OldDate, StartDate) mod 24; // Remove total days 
    Mins := MinutesBetween(StartDate, OldDate) mod 60; 
    Secs := SecondsBetween(StartDate, OldDate) mod 60; 
    OutputText := Format(' %d days, %d hours, %d min, %d secs', 
         [Days, Hours, Mins, Secs]); 
    WriteLn(OutputText); 

end; 

var 
    BeginDate, EndDate: TDateTime; 
begin 
    BeginDate := Now; 
    EndDate := BeginDate - 0.5; // about 12 hours earlier 
    ShowTimeDiff(BeginDate, EndDate); 

    EndDate := BeginDate - 2.53724; // Create date about 2 1/2 days earlier 
    ShowTimeDiff(EndDate, BeginDate); 

    EndDate := BeginDate - 5.75724; // Create date about 5 3/4 days earlier 
    ShowTimeDiff(BeginDate, EndDate); 
    ReadLn; 
end. 

產生以下輸出:

Time differences

注意參數順序的DaysBetweenHoursBetween之間的逆轉是故意的證明這些函數總是返回正值,所以參數的順序並不重要。這在文檔中提到。

+0

我在這裏得到錯誤的秒數...把它放在一個計時器中,並實時觀察輸出 - 你會發現它不太正確,秒鐘總是出現在30秒以內。 –

+0

是的,秒和分鐘應該是'mod 60'而不是'mod 24' –

+0

已經完成了。發佈最後評論時必定發生。 :) –

4

的問題是,當你從fDestDT減去Now你希望兩個日期之間獲得的區別,但實際上你得到另一個datetime值。由於您使用的值幾乎相同,因此您可以得到德爾福的datetime系統的「零日期」,即30.分鐘1899.這就是爲什麼您會得到FormatDateTime('d', DT)+' Days'的「30天」。

以來的最小量的youre在intrested是第二,我建議你使用SecondsBetween獲得兩個時間戳之間的差別,然後將其分成幾部分像

diff := SecondsBetween(Now, fDestDT); 
S:= IntToStr(diff mod 60)+' Seconds'; 
diff := diff div 60; 
N:= IntToStr(diff mod 60)+' Minutes'; 
diff := diff div 60; 
H:= IntToStr(diff mod 24)+' Hours'; 
diff := diff div 24; 
D:= IntToStr(diff)+' Days'; 
+0

謝謝,但從那時起問題就被修改了,現在正在使用一種不同的方法來使用DateUtils。 +1的答案雖然。 –

+0

+1爲解釋爲什麼OP是30天。 –

3

如果您使用的是Delphi 2010(我相信)或以上版本,您可能會簡化您的代碼,並使用TimeSpan.pas單位更清晰,該單位包含一條記錄,您可以使用該記錄來分析給定的時間跨度。

+0

不,我有德爾福7,但有什麼辦法可以潛入這個TimeSpan.pas單位嗎?聽起來像它正是我所需要的... –

+0

尼克,標籤說Delphi 7。:)傑裏,你可以通過升級你的Delphi副本來獲得'TimeSpan'。 ;) –

+1

我已經使用2010年,我仍然喜歡7:PI猜我會去得到一個該單位的副本,併爲德爾福7:D –