日期/时间操作 - 友好的倒计时字符串

Jer*_*dge 4 delphi math datetime timer delphi-7

我正在构建一个具有特定日期/时间倒计时的东西.我有它的工作 - 至少小时,分钟和秒工作正常.我的问题是当我尝试实现Days时,它没有给出正确的结果.我知道DateUtils单元,但那里有很多东西,我不知道怎么做,特别是因为我在数学方面很糟糕.

我有一个间隔为100的计时器.然后我有一个全局fDestDT的目的地日期/时间来倒计时.在计时器中,我有一个本地TDateTime调用DT.然后我将它分成多个字符串并将它们重新组合成一个"友好"的字符串......

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;
Run Code Online (Sandbox Code Playgroud)

它应该出来像......

0 Days, 3 Hours, 1 Minute, 12 Seconds

但相反,日子显示错误,倒计时的日期/时间是今天的日期,它显示30天......

30 Days, 3 Hours, 1 Minute, 12 Seconds

我认为,如果我提前超过1个月,它也不会正确显示.我如何正确获得天数?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;
Run Code Online (Sandbox Code Playgroud)

Ken*_*ite 7

DaysBetween,HoursBetween,MinutesBetween,和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.
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

时差

注意,在DaysBetween和之间的参数顺序的反转HoursBetween是有意的,以证明函数总是返回正值,因此参数的顺序并不重要.这在文档中提到.


ain*_*ain 5

问题是,当您Now从中减去时,fDestDT期望得到两个日期之间的差,但实际上您得到了另一个datetime值。由于您使用的值几乎相同,因此您会获得Delphi的日期时间系统30. dets 1899 的“零日期” 。这就是为什么您获得的“ 30天”的原因FormatDateTime('d', DT)+' Days'

由于您所参与的最小量是秒,因此我建议您使用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';
Run Code Online (Sandbox Code Playgroud)