来者有分------旧题新问(日期时间问题)!请说出你的见解和简便算法 ( 积分: 100 )

  • 主题发起人 主题发起人 moonshiny
  • 开始时间 开始时间
M

moonshiny

Unregistered / Unconfirmed
GUEST, unregistred user!
关于日期时间的问题
计算 日期1 到 日期2 之间相隔 X年X月X日X时X分X秒,注意这个日期时间差是从日期1推算来的,并不是标准的日期时间型数据.
举例如下:
(2005-01-26 04:10:00) 到 (2005-01-26 04:15:00)相差0年0月0天0小时5分0秒
(2005-01-25 04:10:00) 到 (2005-01-26 04:15:00)相差0年0月1天0小时5分0秒
(2005-01-25 04:10:00) 到 (2005-01-26 04:00:00)相差0年0月0天22小时50分0秒
.............
(2003-10-26 04:10:00) 到 (2005-01-26 03:05:00)相差1年2月30天23小时55分0秒
注意:这里出现了"2月30天"
希望大家说出你的见解并提供好的算法!
当然也可以用提交SQL计算方式,但最好是用函数方式解决!
 
关于日期时间的问题
计算 日期1 到 日期2 之间相隔 X年X月X日X时X分X秒,注意这个日期时间差是从日期1推算来的,并不是标准的日期时间型数据.
举例如下:
(2005-01-26 04:10:00) 到 (2005-01-26 04:15:00)相差0年0月0天0小时5分0秒
(2005-01-25 04:10:00) 到 (2005-01-26 04:15:00)相差0年0月1天0小时5分0秒
(2005-01-25 04:10:00) 到 (2005-01-26 04:00:00)相差0年0月0天22小时50分0秒
.............
(2003-10-26 04:10:00) 到 (2005-01-26 03:05:00)相差1年2月30天23小时55分0秒
注意:这里出现了"2月30天"
希望大家说出你的见解并提供好的算法!
当然也可以用提交SQL计算方式,但最好是用函数方式解决!
 
你這樣算是不是有問題呀?閏年有366天喲
 
两时间之间说相差X年X月X日X时X分X秒的说法是不正确的
 
这与天数没有关系的,也可以说关系不大,
比如(2004-01-01 00:00:00) 到 (2005-01-01 00:00:00)以天为单位相差是366天,但以年为单位是相差1年,这里(年)是一个(单位),1年可以是365天也可以是366天,同样,1个月可以是28天,29天,30天或31天,年,月,天,小时,分,秒都是日期时间单位,而不是日期时间值,其中年,月相差最为难处理
 
對呀,那你怎麼就得出了2個月30天呢?我覺得你這樣算不對。
 
To abookdog:
两时间之间说相差X年X月X日X时X分X秒的说法是不正确的
请说明理由可以吗?
如果问你的年龄,我们平时都是算你从出生到现在是X年;
同样我也可问你从出生到现在是X年X月X天X时X分X秒
 
To hotboys:
请问
(2005-01-01 00:00:00) 到 (2005-03-02 00:00:00)相差X年X月X天X小时X分0秒?
我的答案是:相差0年2月1天0小时0分0秒
那么:
(2005-01-01 00:00:00) 到 (2005-03-31 00:00:00)相差X年X月X天X小时X分0秒?
我的答案是:相差0年2月30天0小时0分0秒,因为对于2005年3月分来说30天不满1个月
 
不要用年和月做标准
因为润年和不润年就差一天,大月小月天数又不同
建议只使用X天X小时X分X秒
 
你上面這樣得出2月30天我不能說你錯,但是你開始說的我就有點懷疑了,你試試這個得出來是多少
select convert(datetime,'2005-01-26 03:05:00')-convert(datetime,'2003-10-26 04:10:00')
把得出來的月和日減去1是不是你要的結果???
 
试试吧,应该满足你的要求啦。
function TimeBetween(A, B: TDateTime;
var Y, M, D, H, N, S: Integer):do
uble;
var
DayA, DayB, TempB: TDateTime;
TimeA, TimeB: TDateTime;
YA, YB, MA, MB, DA, DB: Word;
Secs: Int64;
begin
DayA := Trunc(A);
DayB := Trunc(B);
TimeA := Frac(A);
TimeB := Frac(B);
if TimeB <
TimeA then
begin
TimeB := TimeB + 1;
DayB := DayB - 1;
end;
DecodeDate(DayA, YA, MA, DA);
DecodeDate(DayB, YB, MB, DB);
Y := YB - YA;
M := MB - MA;
D := DB - DA;
if D <
0 then
begin
TempB := IncMonth(DayB, -1);
YB := YearOf(TempB);
MB := MonthOf(TempB);
D := D + MonthDays[IsLeapYear(YB)][MB];
Dec(M);
end;
if M <
0 then
begin
TempB := IncYear(TempB, -1);
YB := YearOf(TempB);
M := M + 12;
Dec(Y);
end;
///////////////////////////////////////////////
// 改一下取整方式,更准确点。
// Secs := Trunc((TimeB - TimeA) * SecsPerDay);
Secs := Round((TimeB - TimeA) * SecsPerDay);
///////////////////////////////////////////////
H := Secs div 3600;
Secs := Secs mod 3600;
N := Secs div 60;
S := Secs mod 60;
Result := B - A;
end;
 
function SecondsBetween(const ANow, Athen
: TDateTime): Int64;
年数 := SecondsBetween div (365 * 24 * 60 * 60)
余数1 := SecondsBetween mod (365 * 24 * 60 * 60)
月数 := 余数1 div (30 * 24 * 60 * 60)
余数2 := 余数1 mod (30 * 24 * 60 * 60) - (月数 div 2) //大概地除去每月31天多出来的
日数 := 余数2 div (24 * 60 * 60)
余数3 := 余数2 mod (24 * 60 * 60)
依此类推...
问题是关于每月到底28天、29天、30天还是31天不知如何计算好。
 
我自己解决了,请大家发表意见
本贴暂不结束,请大家继续讨论!!!
function TFormDM.GetDateBetween(StartDate,EndDate:TDateTime):String;
var
TmpDate:TDateTime;
m_DaysInMonth:Word;
m_YearS,m_MonthS,m_DayS,m_HourS,m_MinuteS,m_SecondS:Word;
begin
result := '';
IF StartDate>=EndDate then
Exit;
TmpDate:=StartOfTheMonth(EndDate)-1;
m_DaysInMonth:=DaysInMonth(TmpDate);
m_YearS:=YearOf(EndDate)-YearOf(StartDate)
+Ifthen
(MonthOf(StartDate)<=MonthOf(EndDate),0,-1);
m_MonthS:=MonthOf(EndDate)-MonthOf(StartDate)
+Ifthen
(MonthOf(StartDate)<=MonthOf(EndDate),0,12);
m_MonthS:=m_MonthS+Ifthen
(DayOf(StartDate)<=DayOf(EndDate),0,-1);
m_DayS:=DayOf(EndDate)-DayOf(StartDate)
+Ifthen
(DayOf(StartDate)<=DayOf(EndDate),0,m_DaysInMonth);
m_DayS:=m_DayS+Ifthen
(HourOf(StartDate)<=HourOf(EndDate),0,-1);
TmpDate:=EndDate-StartDate;
m_HourS:=HourOf(TmpDate);
m_MinuteS:=MinuteOf(TmpDate);
m_SecondS:=SecondOf(TmpDate);
result := IntToStr(m_YearS)+' 岁 '
+IntToStr(m_MonthS)+' 月 '
+IntToStr(m_DayS)+' 天 '
+IntToStr(m_HourS)+' 小时 '
+IntToStr(m_MinuteS)+' 分 '
+IntToStr(m_SecondS)+' 秒 ';
end;
 
不对不对,1999-02-28 00:00 至 2000-02-28 00:00算不算一年???
 
楼主的这个函数算法明显不对,(2004-01-26 04:10:00) 到 (2005-01-25 04:00:00),看看结果是什么!?“1 岁 65535 月 30 天 23 小时 50 分 0 秒”,呵呵
求年时没有考虑天EndDate比StartDate小而需要向月借1个月将月份减1的情况,另外,年月日等都用Word类型,导致上面日借月而EndDate比StartDate实际的月小,相减负值又被转成无符号整数的问题。
看看我给的函数执行的结果:“0 岁 11 月 29 天23 小时50 分0 秒”
测试代码:
var
A, B: TDateTime;
Y, M, D, H, N, S: Integer;
begin
A := StrToDateTime('2004-01-26 04:10:00');
B := StrToDateTime('2005-01-25 04:00:00');
Memo1.Lines.Add(GetDateBetween(A, B));
TimeBetween(A, B, Y, M, D, H, N, S);
Memo1.Lines.Add(Format('%d 岁 %d 月 %d 天%d 小时%d 分%d 秒', [Y, M, D, H, N, S]));
end;
 
上面的函数,TempB的初值应该是DayB。更正一下:
function TimeBetween(A, B: TDateTime;
var Y, M, D, H, N, S: Integer):do
uble;
var
DateA, DateB: TDateTime;
TimeA, TimeB: TDateTime;
YA, YB, MA, MB, DA, DB: Word;
Secs: Int64;
begin
DateA := Trunc(A);
DateB := Trunc(B);
TimeA := Frac(A);
TimeB := Frac(B);
if TimeB <
TimeA then
begin
TimeB := TimeB + 1;
DateB := DateB - 1;
end;
DecodeDate(DateA, YA, MA, DA);
DecodeDate(DateB, YB, MB, DB);
Y := YB - YA;
M := MB - MA;
D := DB - DA;
if D <
0 then
begin
DateB := IncMonth(DateB, -1);
YB := YearOf(DateB);
MB := MonthOf(DateB);
D := D + DaysInAMonth(YB, MB);
Dec(M);
end;
if M <
0 then
begin
DateB := IncYear(DateB, -1);
YB := YearOf(DateB);
M := M + 12;
Dec(Y);
end;
///////////////////////////////////////////////
// 改一下取整方式,更准确点。
// Secs := Trunc((TimeB - TimeA) * SecsPerDay);
Secs := Round((TimeB - TimeA) * SecsPerDay);
///////////////////////////////////////////////
H := Secs div 3600;
Secs := Secs mod 3600;
N := Secs div 60;
S := Secs mod 60;
Result := B - A;
end;

procedure TForm1.Button10Click(Sender: TObject);
var
A, B: TDateTime;
Y, M, D, H, N, S: Integer;
begin
A := StrToDateTime('2004-01-26 04:10:00');
B := StrToDateTime('2005-01-25 04:00:00');
TimeBetween(A, B, Y, M, D, H, N, S);
Memo1.Lines.Add(Format('%d 岁 %d 月 %d 天%d 小时%d 分%d 秒', [Y, M, D, H, N, S]));
A := StrToDateTime('2003-10-23 04:10:00');
B := StrToDateTime('2005-01-26 03:05:00');
TimeBetween(A, B, Y, M, D, H, N, S);
Memo1.Lines.Add(Format('%d 岁 %d 月 %d 天%d 小时%d 分%d 秒', [Y, M, D, H, N, S]));
A := StrToDateTime('2003-01-26 03:10:00');
B := StrToDateTime('2005-10-23 04:15:00');
TimeBetween(A, B, Y, M, D, H, N, S);
Memo1.Lines.Add(Format('%d 岁 %d 月 %d 天%d 小时%d 分%d 秒', [Y, M, D, H, N, S]));
end;

测试结果:
0 岁 11 月 29 天23 小时50 分0 秒
1 岁 3 月 2 天22 小时55 分0 秒
2 岁 8 月 27 天1 小时5 分0 秒
 
非常感谢楼上解释,开始我也在考虑借位问题 月借位年 日借位月 时借位日
……
给搞迷糊了[:)]
非常感谢!!!
 
不对不对,1999-02-28 00:00 至 2000-02-28 00:00算不算一年???
===============================================
=================================================
不对不对,1999-02-28 00:00 至 2000-02-28 00:00算不算一年???
 
1999-02-28 00:00 至 2000-02-28 00:00 肯定是一年
首先对楼上的错误进行说明:2000年不是闰年
即使是闰年也不影响计算结果:
如:
2003-02-28 00:00 至 2004-02-28 00:00 1年0月0天0小时0分0秒,
2004-01-28 00:00 至 2004-02-28 00:00 0岁1月0天0小时0分0秒,
2004-02-28 00:00 至 2004-03-28 00:00 0岁1月0天0小时0分0秒,
2004-02-29 00:00 至 2004-03-29 00:00 0岁1月0天0小时0分0秒,
2004-02-28 00:00 至 2004-03-27 00:00 0岁0月28天0小时0分0秒,
2004-02-29 00:00 至 2004-03-28 00:00 0岁0月28天0小时0分0秒,
因为要按1999年的天数来计算,
或者说日期时间差是要以开始时间为基准的,要从开始时间推算过,
1999年
 
2000年不是闰年???2000不能被400整除吗?
真是晕倒,算了,不再讨论这个问题了,没什么好讨论的。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
891
import
I
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部