【问题标题】:How to correctly get date and time passed between two dates?如何正确获取两个日期之间经过的日期和时间?
【发布时间】:2014-07-11 15:31:55
【问题描述】:

我正在创建这个函数:

function LiteralTimePassed(FromDate: TDateTime; ToDate: TDateTime = 0): string;
const
  Coma = ', ';
var
  Dt, Mt: Integer; { se dos dias contarem mais que 30/31 então aumenta o mês }
  P: TDateTime;
  HC: Boolean; { indica se já há um token antes do novo token, para colocar vírgula }
  Token: string; { a parte do timestamp verificada no loop }
  Literal: string;
  Y, M, D, H, N, S: Integer; { ano, mês, dia, hora, minuto(n), segundo }
  Ys, Ms, Ds, Hs, Ns, Ss: Boolean; { valida se valores maiores que 1 para adicionar 's' }
begin
{ retorna quanto tempo se passou desde a data 1 até a data 2 em forma literal }
  if ToDate = 0 then ToDate := Now;
  HC := False;
  Literal := '';
  P := ToDate-FromDate ;
   Dt := (DaysInMonth(FromDate)-DayOf(FromDate))+(DaysInMonth(ToDate)-DayOf(ToDate));
   Mt := Dt div DaysInMonth(ToDate);
  Ys := VarAssign(Y, YearsBetween(ToDate, FromDate)) > 1;
  Ms := VarAssign(M, (MonthsBetween(ToDate, FromDate)-(Y*MonthsPerYear))-Mt) > 1;
  Ds := VarAssign(D, Dt mod DaysInMonth(ToDate)) > 1;
  // I did not make the hour, minute and second, yet...
end;

要获得如下响应:

 There has been "2 years, 4 months, 1 day, 7 hours, 30 minutes and 22 seconds" between those dates

我怀疑我的逻辑在计算天数的情况下是否正确,以及我是否必须对时间部分进行相同的计算。

但是,如果您知道任何已经这样做的免费编码,它将为我节省很多时间!

谢谢。

【问题讨论】:

  • 您可以使用 TTimeSpan(位于 System.TimeSpan 中)来做时间部分。因为它会给你的日子只有你必须用你自己的代码来做几个月和几年。
  • @UweRaabe 你能写一个解释如何使用 TTimeSpan 的答案吗?目前尚不清楚如何创建和操作此对象。
  • @EASI:学习阅读源代码。如果你这样做了,你会立即看到TTimeSpan 不是一个object,它是一个record,而且它不需要被创建。 (您还会很快看到您可以使用 TTimeSpan.Subtract(Date1, Date2: TDateTime) 来查找两个日期之间的差异。)或者,gasp 您还可以看到 TTimeSpan documentation
  • 抱歉,没注意是记录。
  • 一般来说 TTimeSpan 是一个对象。

标签: delphi datetime delphi-xe6


【解决方案1】:

首先处理年和月,然后是 TTimeSpan:

procedure TimePassed(dt1,dt2: TDateTime);
var
  y1,m1,d1,h1,mi1,s1,ms,y2,m2,d2,h2,mi2,s2,y,mo,d:word;
  ts:TTimeSpan;
begin
  DecodeDateTime(dt1,y1,m1,d1,h1,mi1,s1,ms);
  DecodeDateTime(dt2,y2,m2,d2,h2,mi2,s2,ms);
  ms:=12*y2+m2-12*y1-m1;
  if s1+60*mi1+60*60*h1+24*60*60*d1>s2+60*mi2+60*60*h2+24*60*60*d2 then ms:=ms-1;
  mo:= ms mod 12;
  y:=ms div 12; //years and months ready, now the rest
  dt1:=EncodeDateTime(y1+y,m1+mo,d1,h1,mi1,s1,0);
  ts := TTimeSpan.Subtract(dt2, dt1);
  Result:= Format('There has been "%d years, %d months, %d days, %d hours, %d minutes and %d seconds" between those dates',
    [y,mo,ts.Days, ts.Hours, ts.Minutes, ts.Seconds]);
end;

【讨论】:

    【解决方案2】:

    关于日期和时间部分,您可以使用 System.TimeSpan 中的 TTimeSpan 来缓解您的生活:

    var
      ts: TTimeSpan;
    begin
      ts := TTimeSpan.Subtract(ToDate, FromDate);
      Format('There has been "%d days, %d hours, %d minutes and %d seconds" between those dates',     
        [ts.Days, ts.Hours, ts.Minutes, ts.Seconds]);
    end;
    

    不过,这并不能解决年月部分。

    【讨论】:

      【解决方案3】:

      我会使用以下逻辑:

      Y := YearsBetween(FromDate, ToDate);
      FromDate := IncYear(FromDate, Y);
      
      M := MonthsBetween(FromDate, ToDate);
      FromDate := IncMonth(FromDate, M);
      
      and so on
      

      【讨论】:

      • 使用 MonthsSpan 不是更好吗?
      • MonthsSpan 仅给出粗略的近似值
      • 抱歉,我刚刚发现 MonthsBetween 也使用了近似值 :( 很快就会删除我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-07
      • 1970-01-01
      • 2011-06-08
      • 2018-01-11
      • 1970-01-01
      相关资源
      最近更新 更多