问题: 如何计算两个TDateTime的相隔时间(年、月、日、时、分、秒)? ( 积分: 100 )
分类: 系统相关
来自: 叮叮当当, 时间: 2002-05-29 20:38:00, ID: 1131624
要求编制一个过程返回两个TDateTime的经过时间(年、月、日、时、分、秒)
procedure DateTimeDiff(const T1, T2: TDateTime
out Y, M, D, H, N, S, MS: Word)
T2>T1,例如输入
T1=2002-5-29 20:30:10.100
T2=2002-5-29 20:31:11.000
返回 Y、M、D、H、N、S、MS
为: 0、0、0、0、1、0、900
VB里的TimeDiff函数是能完成类似功能的,Delphi的DateUtils里的函数我都查过了,没有适合的。[
]
这个问题我想了几乎一个下午!如果用SecondsBetween函数得到经过的秒数再用整数除法计算分、时、日……会碰到闰年的问题。
来自: mlzhou, 时间: 2002-05-29 20:49:00, ID: 1131654
var
ti,t2: TDateTime
Year1, Month1, Day1, Hour1, Min1, Sec1, MSec1,
Year2, Month2, Day2, Hour2, Min2, Sec2, MSec2,
dYear, dMonth, dDay, dHour, dMin, dSec, dMSec: Word
DecodeDate(t1, Year1, Month1, Day1)
DecodeTime(t1, Hour1, Min1, Sec1, MSec1)
DecodeDate(t2, Year2, Month2, Day2)
DecodeTime(t2, Hour2, Min2, Sec2, MSec2)
dYear:=Year1-Year2
.......
来自: qdyoung, 时间: 2002-05-29 20:55:00, ID: 1131662
t=T1-T2
d=trunc(t)
t=t-d
decodetime(t,h,n,s,ms)
decodedate(d,y,m,d)
decodedate(0,y0,m0,d0)
y,m,d与y0,m0,d0要减一下,这个不难吧
-------------------
http://www.8421.org
来自: lynu, 时间: 2002-05-29 21:18:00, ID: 1131713
为什么老有人问这样的问题.
你只要明白一个事情:TDateTime=double
来自: bubble, 时间: 2002-05-29 21:41:00, ID: 1131749
hi,你要知道这个就行了,
当初我想算两个Date之间有多少天,
后来发现两个Date相减就行了,
你有启发了么??
time也是一样啊。
来自: 雪鹰, 时间: 2002-05-29 21:45:00, ID: 1131761
procedure TimeDiff(FromDate,ToDate:TDateTime;Var DayGo:integer;var TimeGo:Ttime)
var
aTimeDiff:TDateTime
begin
aTimeDiff:=ToDate-FromDate
DayGo:=(trunc(aTimeDiff))
//逝去的日子
TimeGo:=aTimeDiff;//逝去的时间.
//注意没有日期部分的时间TIMEGO STRTODATE会成1887什么的,所以用TIMEGO要用TIMETOSTR
end
来自: 雪鹰, 时间: 2002-05-29 21:47:00, ID: 1131766
随便给点分吧,好久没混分了,就是因为答了没人给分^_^
来自: 叮叮当当, 时间: 2002-05-29 21:55:00, ID: 1131768
我要用做出来的DateTimeDiff过程显示“现在已经正常运行XX天XX月XX日XX小时XX分XX秒”,所以单纯地把年月日时分秒分离出来相减返回是不符合要求的。
我们先不管毫秒罢。
比如输入
T1=2002-5-31 20:59:59
T2=2002-6-01 19:00:00
会返回什么?
mlzhou的程序会返回“0年1月30天1小时59分59秒”,而正确的应该是“0年0月0天22小时0分1秒”
qdyoung的程序好像是正确的,我试试。
来自: mlzhou, 时间: 2002-05-29 21:57:00, ID: 1131787
原来是这样,我的错了。
来自: xiao_ping, 时间: 2002-05-29 22:11:00, ID: 1131824
这个问题我问过
http://www.delphibbs.com/delphibbs/dispq.asp?lid=678320
来自: 叮叮当当, 时间: 2002-05-29 22:23:00, ID: 1131852
qdyoung的程序也有问题,时间倒没有问题,日期用简单的相减就会有问题!
TO: xiao_ping
你的问题最后接受的是menxin的答案么?
来自: 苦虫, 时间: 2002-05-29 22:31:00, ID: 1131879
二个相减,再用decode,唉~
来自: xiao_ping, 时间: 2002-05-29 22:49:00, ID: 1131906
是。
来自: 叮叮当当, 时间: 2002-05-29 23:15:00, ID: 1131940
TO: xiao_ping
menxin的程序最后好像也有问题(计算天数的地方):
r3:=DayOf(Date2)-DayOf(Date1) +IfThen(DayOf(Date1)<=DayOf(Date2),0,DaysInMonth(StartOfTheMonth(Date2)-1))
假如
Date1=2000-01-30
Date2=2000-03-31
则
StartOfTheMonth(Date2)=2000-03-01
StartOfTheMonth(Date2)-1=2000-02-29 (TDataTime的整数部分就是天数,减1就等于天数减1)
DaysInMonth(StartOfTheMonth(Date2)-1)=29
DayOf(Date1)<=DayOf(Date2) 成立,因此 r3:=DayOf(Date2)-DayOf(Date1) +29=31-30+29=30 (天)
这是错误的,应该是“2个月零1天”。
来自: Pearl., 时间: 2002-05-29 23:23:00, ID: 1131958
唉
procedure timediff(FromDate, ToDate: TDateTime
var Y, M, D, H, N, S, MS: word)
var
d: TDateTime
begin
d := ToDate-FromDate
decodedate(d, y, m, d)
decodetime(d, h, n, s, ms)
end
来自: linsb, 时间: 2002-05-29 23:33:00, ID: 1131978
T1:=StrToDateTime('2002-5-29 20:30:10.100')
T2:=StrToDateTime('2002-5-29 20:31:11.000')
//为: 0、0、0、0、1、0、900
td:=t2-t1
DecodeTime(td, Hour, Min, Sec, MSec)
DecodeDate(td, Year, Month, Day)
Label1.Caption:=IntToStr(floor(td))+'-'+IntToStr(hour)+'-'+IntToStr(min)+'-'+IntToStr(sec)+'-'+IntToStr(msec)
//为: 0-0-1-0-900
floor(td))为相差天数,如果超过30天月数加一,如果月数大于12年数加一进行折算。
来自: Oldtiger, 时间: 2002-05-29 23:37:00, ID: 1131983
明白TdateTime是Double就好了!
两个TDateTime相减,结果的整数部分就是天数
小数部分就是时分秒
例如,相减结果为3.256
则时间间隔为3天+0.256*24*60*60秒
再把这个秒数折算一下就是时分了!
来自: 叮叮当当, 时间: 2002-05-29 23:47:00, ID: 1132000
TO: Pearl.
你想让我一上来就显示“已运行1899年12月30天……”啊?[
]
TO: Oldtiger
我已经明白“TdateTime是Double”了。
也知道怎样计算经过的天数,可我不知道怎么把类似“768天”的计算结果转为显示“XX年XX月XX天”。[
]要完成这个可没有想像的那么简单,因为可能要牵涉到闰年计算。
来自: bigroute, 时间: 2002-05-29 23:53:00, ID: 1132008
formatdatetime('yyyy-mm-dd hh:ss:nn:zzz',t1-t2)
来自: stucxm, 时间: 2002-05-30 0:06:00, ID: 1132017
只能确定可经过某年某月某日,但不能确定经过多少年多少月多少日,因为一年、有多
少日是不固定的。
来自: 冰封, 时间: 2002-05-30 0:13:00, ID: 1132024
to stucxm : 可以的。
to 叮叮当当:
可以对menxin的程序稍加修改就行了。
r3除与DaysInMonth(StartOfTheMonth(Date2)-1)整数部分
加到月数,余数就是天数。
程序就不写了,这两天手指痛。
来自: 叮叮当当, 时间: 2002-05-30 0:21:00, ID: 1132033
TO: 冰封
没听懂,我的脑子现在已经满是浆糊了。。。
来自: Pearl., 时间: 2002-05-30 0:28:00, ID: 1132040
To: 叮叮当当
加一句dec(y, 1899)不就可以了?
来自: stucxm, 时间: 2002-05-30 0:30:00, ID: 1132043
Sorry,我误解了,因为可以以起始日期开始推算的。
来自: hamsoft, 时间: 2002-05-30 0:31:00, ID: 1132045
我有个现成的vcl,现奉献出来:
{*************************************************************}
{ DateTime Calculator component for Delphi 16/32 }
{ Version: 1.3 }
{ Author: Aleksey Kuznetsov }
{ E-Mail: info@utilmind.com }
{ Home Page: http://www.utilmind.com }
{ Created: May, 12, 1999 }
{ Modified: August, 3, 1999 }
{ Legal: Copyright (c) 1999, UtilMind Solutions }
{*************************************************************}
{ TDTCalc (in English) }
{ Component for calculation of amount of years, months, days, }
{ hours, minutes, seconds and miliseconds past between two }
{ time intervals. }
{ PROPERTIES: }
{ StartTime, EndTime: TDateTime
- Range of time interval. }
{ READ ONLY PROPERTIES: }
{ Years: Int64 }
{ Months: Int64 }
{ Days: Int64 }
{ Hours: Int64 }
{ Minutes: Int64 }
{ Seconds: Int64 }
{ MSeconds: Int64 }
{*************************************************************}
{ Please see demo program for more information. }
{*************************************************************}
{ IMPORTANT NOTE: }
{ This software is provided 'as-is', without any express or }
{ implied warranty. In no event will the author be held }
{ liable for any damages arising from the use of this }
{ software. }
{ Permission is granted to anyone to use this software for }
{ any purpose, including commercial applications, and to }
{ alter it and redistribute it freely, subject to the }
{ following restrictions: }
{ 1. The origin of this software must not be misrepresented, }
{ you must not claim that you wrote the original software. }
{ If you use this software in a product, an acknowledgment }
{ in the product documentation would be appreciated but is }
{ not required. }
{ 2. Altered source versions must be plainly marked as such, }
{ and must not be misrepresented as being the original }
{ software. }
{ 3. This notice may not be removed or altered from any }
{ source distribution. }
{*************************************************************}
unit DTCalc
interface
uses
{$IFDEF Win32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF}
SysUtils, Classes
type
TDTCalc = class(TComponent)
private
FStartTime, FEndTime: TDateTime
FYears, FMonths, FDays, FHours, FMinutes: Int64
FSeconds, FMSeconds: Int64
procedure SetStartTime(Value: TDateTime)
procedure SetEndTime(Value: TDateTime)
procedure Calculate
procedure SetNone(Value: Int64)
public
property Years: Int64 read FYears
property Months: Int64 read FMonths
property Days: Int64 read FDays
property Hours: Int64 read FHours
property Minutes: Int64 read FMinutes
property Seconds: Int64 read FSeconds
property MSeconds: Int64 read FMSeconds
published
property StartTime: TDateTime read FStartTime write SetStartTime
property EndTime: TDateTime read FEndTime write SetEndTime
end
procedure Register
implementation
procedure TDTCalc.SetStartTime(Value: TDateTime)
begin
FStartTime := Value
Calculate
end
procedure TDTCalc.SetEndTime(Value: TDateTime)
begin
FEndTime := Value
Calculate
end
procedure TDTCalc.Calculate
var
e: Extended
TempStr: String
procedure Truncate(var Value: Int64)
begin
try
Value := Trunc(e)
except
Value := -1
end
end
begin
e := MSecsPerDay * (FEndTime - FStartTime)
Truncate(FMSeconds)
TempStr := IntToStr(FMSeconds)
if TempStr[Length(TempStr)] = '9' then inc(FMSeconds)
e := e / 1000
Truncate(FSeconds)
e := e / 60
Truncate(FMinutes)
e := e / 60
Truncate(FHours)
e := e / 24
Truncate(FDays)
FMonths := Trunc((FEndTime - FStartTime) / 30.4375)
FYears := Trunc((FEndTime - FStartTime) / 365.25)
end
procedure TDTCalc.SetNone
begin {} end
procedure Register
begin
RegisterComponents('UtilMind', [TDTCalc])
end
end.
来自: 冰封, 时间: 2002-05-30 0:50:00, ID: 1132060
来自:叮叮当当, 时间:2002-5-29 23:15:00, ID:1131940
TO: xiao_ping
menxin的程序最后好像也有问题(计算天数的地方):
r3:=DayOf(Date2)-DayOf(Date1) +IfThen(DayOf(Date1)<=DayOf(Date2),0,DaysInMonth(StartOfTheMonth(Date2)-1))
假如
Date1=2000-01-30
Date2=2000-03-31
则
StartOfTheMonth(Date2)=2000-03-01
StartOfTheMonth(Date2)-1=2000-02-29 (TDataTime的整数部分就是天数,减1就等于天数减1)
DaysInMonth(StartOfTheMonth(Date2)-1)=29
DayOf(Date1)<=DayOf(Date2) 成立,因此 r3:=DayOf(Date2)-DayOf(Date1) +29=31-30+29=30 (天)
这是错误的,应该是“2个月零1天”。
其实,这程序基本上是可以的,就是你指出的地方有问题,修改的方法如下:
在他的程序最后部分加上
r2:= r2 + r3 div DaysInMonth(StartOfTheMonth(Date2)-1)
r3:= r3 mod DaysInMonth(StartOfTheMonth(Date2)-1)
来自: 叮叮当当, 时间: 2002-05-30 1:07:00, ID: 1132075
To: hamsoft
你这段程序计算出来的和用HoursBetween、MinutesBetween、SecondsBetween算出来的一样。没法用。
来自: 冰封, 时间: 2002-05-30 1:16:00, ID: 1132077
只要照我说那样改就成了,虽然我没试过程序,
不过从数学逻辑的角度上看,一定可以。
来自: 叮叮当当, 时间: 2002-05-30 1:23:00, ID: 1132079
To: 冰封
我试了一下
Date1=2000-01-30
Date2=2000-03-31
是没问题了,可是我又随便设了一下
Date1=2002-05-30
Date2=2002-06-29
就不对了,返回只有“1天”了。
程序比较复杂,我就不分析了。
来自: 杜宝, 时间: 2002-05-30 1:31:00, ID: 1132081
呵呵,晚上上来看到,大概做了一下:对秒数的处理还有点小问题,但可能是数据类型精度
的问题了,困了,不改了,你看着办吧。用D6:
uses
DateUtils
...
function DeTwoDateTime(Const St,Et :TDateTime):String
Const
Fmt = '相差 %d 年 %d 月 %d 日 %d 小时 %d 分 %d 秒'
var
Year,Month,Day:Integer
Hour,Min,Se:Integer
begin
Year := YearsBetween(et,st);//相差总年数
Month := MonthsBetween(et,st) mod 12;//相差月数(年后的零头)
Day := Trunc(Et - IncMonth(IncYear(St,Year),Month));//取相隔XX年YY月后的天数零头
//下面的东东有点奇怪,你可以注释以后用2002-1-31与2002-6-1试试就明白了。
if (Et - Day) < IncMonth(Et,-1) then //如果间隔天数超过一个月
begin
Month := Month + 1
Day := Day mod Trunc(Et - IncMonth(Et,-1))
end
Hour := HoursBetween(Et,St) mod 24 ;//相差总小时
Min := MinutesBetween(Et,St) mod 60
//相差分钟
Se := SecondsBetween(Et,st) mod 60
// 相差秒数
Result := Format(Fmt,[Year,Month,Day,Hour,Min,Se])
end
procedure TForm1.Button1Click(Sender: TObject)
var
t1,t2:TDateTime
begin
T1:=StrToDateTime('2002-05-31 20:59:59');//如果两个都是整数时有问题,可能是
//Tdatatime类型数据无法准确表示一个小数的缘故。
//不是每个分数都能用一个小数精确表示,涉及分数小数之间的转换,所以精度可能有点问题
//你可以试一下,不影响太多的。
//你用19:00:00 与20:00:00试试就知道了,但17:00:00 与20:00:00是正确的。
T2:=StrToDateTime('2002-06-1 19:00:00')
ShowMessage(DeTwoDateTime(T1,T2))
end
又想了一下:
对于时间(小时,分,秒等)的处理,应该以字符处理为主,这样就不会有格式的问题了。只是一个分解
字符串的过程,你自己试试吧。
只要是通过直接计算的方法,我想,可能都会存在我上面说的问题的。
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
好,搞定,安心睡觉!
来自: 叮叮当当, 时间: 2002-05-30 7:54:00, ID: 1132087
TO: 杜宝
谢谢你,但是你的程序在
Date1=2002-05-30
Date2=2003-05-30
会返回“0年11月30天”
来自: 憔悴, 时间: 2002-05-30 4:27:00, ID: 1132098
晕
来自: microming, 时间: 2002-05-30 8:34:00, ID: 1132182
formatfloat(格式,date1-date2)
来自: lch93005, 时间: 2002-05-30 8:37:00, ID: 1132190
用DecodeDate函数试试,将日期分解开来
来自: tqhuo, 时间: 2002-05-30 8:46:00, ID: 1132214
用函数daysbettween(),yearsbetween(),monthsbetween()
来自: 魔鬼大师, 时间: 2002-05-30 8:52:00, ID: 1132237
用一个sql函数就行了
来自: seucag, 时间: 2002-05-30 9:22:00, ID: 1132327
什么SQL函数?
来自: jswqg, 时间: 2002-05-30 9:25:00, ID: 1132333
好像没有那么复杂吧
其实,TDatetime可以转换成TTimeStamp
具体Ttimestamp啥意思,你可以看Delphi的帮助啦
返回秒数
function TForm1.GetDateTimeTo(AStart, AEnd: TDateTime): Real
var
FStart,FEnd: TTimeStamp
dd,tt : Real
begin
FStart := DateTimeToTimeStamp(AStart)
FEnd := DateTimeToTimeStamp(AEnd)
dd := FEnd.Date-FStart.Date;(天数)
tt := (FEnd.Time-FStart.Time)/1000;(从00:00:00起秒数)
dd := dd*24*3600
Result := dd+tt
end
具体应用,你自己参照这改就成了!
来自: bianlx, 时间: 2002-05-30 10:21:00, ID: 1132448
YearsBetween
MonthsBetween
daysBetween
MinutesBetween
SecondsBetween
MilliSecondBetween
利用上述函数分别来进行计算,然后逐一减去上面得到的数值后再计算
来自: 杜宝, 时间: 2002-05-30 19:42:00, ID: 1132452
呵呵,楼上说的TTimeStamp,不太明白的说,还请举例说明。
早晨心情好,重写了一个,应该比较好了,上面的例子都通过了,你再试试。
function De2DateTime(Const St,Et :TDateTime):String
const
Fmt = '相差 %d 年 %d 月 %d 日 %d 小时 %d 分 %d 秒 %d 毫秒'
var
//以下变量,S开始的为开始时间,E开始的为结束时间。
SYear,EYear,
SMonth,EMonth,
SDay,EDay:Word
SHour,EHour,
SMin,EMin,
SSec,ESec,
SMSec,EMSec:Word
EDate:TDateTime;//起、至数据,只是传入参数不是Var的,做中间变量用。
DYear,DMonth,DDay,DHour,DMin,DSec,DMSec:Integer;//时差。
I:Integer;//中间变量,记录时差间隔。
//中间过程,初始变量。
procedure InitVars
begin
DeCodeDate(EDate,EYear,EMonth,EDay)
DeCodeTime(EDate,EHour,EMin,ESec,EMSec)
end
begin
if St > Et then //参数出错。
begin
Result := 'Error!'
Exit
end
//变量初始化。
// DYear:=0 ;DMonth:=0;DDay:=0;DHour:=0;DMin:=0;DSec:=0;DMSec:=0
EDate := Et
DeCodeDate(St,SYear,SMonth,SDay)
DeCodeTime(St,SHour,SMin,SSec,SMSec)
InitVars
//进位的加减。从最低位开始!
//先来毫秒位:
DMSec := EMSec - SMSec;//取毫秒位差
if DMSec < 0 then //不足应该借位
begin
DMSec := 1000 + DMSec
EDate := IncSecond(EDate,-1);//借位。
InitVars;//改变量。
end
DSec := ESec - SSec ;//取秒位差
if DSec < 0 then
begin
DSec := 60 + DSec
EDate := IncMinute(EDate,-1)
InitVars
end
DMin := EMin - SMin;//取分钟差
if DMin < 0 then
begin
DMin := 60 + DMin
EDate := IncHour(EDate,-1)
InitVars
end
DHour := EHour - SHour;//取小时差
if DHour < 0 then
begin
DHour := 24 + DHour
EDate := IncDay(EDate,-1)
InitVars
end
//**********************************************
//改:
DDay := EDay - SDay;//取天差,这里就复杂了!
if DDay < 0 then
begin
DDay := DaysInMonth(SDay) - SDay + EDay;//到月底,再加
EDate := IncMonth(EDate,-1)
InitVars
end
{ 原先的是错的
******************************************
DDay := EDay - SDay;//取天差,这里就复杂了!
if DDay < 0 then
begin
while DDay < 0 do
begin
i:= DaysBetween(EDate , IncMonth(EDate,-1));//取当月天数
DDay := i + DDay
EDate :=IncMonth(EDate,-1)
end
InitVars
end
***************************************
}
DMonth := EMonth - SMonth
if DMonth < 0 then
begin
DMonth := 12 + DMonth
EDate := IncYear(EDate,-1)
InitVars
end
DYear := EYear - SYear
if DYear < 0 then
begin
Result := 'Error!'
Exit
end
//结果!
Result := Format(Fmt,[DYear,DMonth,DDay,DHour,DMin,DSec,DMSec])
end
procedure TForm1.Button1Click(Sender: TObject)
var
t1,t2:TDateTime
begin
T1:=StrToDateTime('2002-01-31 20:59:59.540')
T2:=StrToDateTime('2002-2-11 19:00:00.001')
ShowMessage(De2DateTime(T1,T2))
end
来自: real_clq, 时间: 2002-05-30 11:07:00, ID: 1132581
不会吧,这么简单的问题说得....
var
t1,t2:TDateTime
...
t1:=now
sleep(100)
t2:=now
showmessage(formatdatetime(''<-这里写上自己要的格式,t1-t2))
..
///////////////////
记住TDateTime之间相减的结果仍然是TDateTime就行了,怎么转换就由你了。
来自: 萧月禾, 时间: 2002-05-30 14:28:00, ID: 1133130
ShowMessage(formatdatetime('yyyy-mm-dd hh:ss:nn:zzz', T2-T1-693594))
返回字符串: 0001-01-02 18:48:28:000
通过分析字符串的“-”“:”得到你要的各个值,再转为整数
(则把当中0开头的值的0去之)
来自: 萧月禾, 时间: 2002-05-30 14:37:00, ID: 1133150
忘了说明,分析的结果中,日期的各部分的值均减1[
]
来自: 杜宝, 时间: 2002-05-30 15:07:00, ID: 1133213
呵呵,萧兄高明,能否讲讲693594的含义,谢谢。
萧兄的程序好象还有点小问题,对跨月处理、闰年处理都有点问题:
小弟的试验:
procedure TForm1.Button1Click(Sender: TObject)
var
t1,t2:TDateTime
i:Integer
s,s1:String
begin
T1:=StrToDateTime('2003-12-01 12:30:00')
for i := 0 to 370 do
begin
T2 := T1 + i
s:=formatdatetime('yyyy-mm-dd hh:ss:nn:zzz', T2-T1-693595)
s1:=De2DateTime(T1,T2)
memo1.Lines.Add(IntToStr(i)+' : '+DateToStr(t2)+' '+s+' '+s1)
end
end
起始:2001-01-29 12:30:00
0 : 2001-1-29 0000-00-00 00:00:00:000 相差 0 年 0 月 0 日 0 小时 0 分 0 秒 0 毫秒 //不用减
...
59 : 2001-3-29 0001-02-27 00:00:00:000 相差 0 年 2 月 0 日 0 小时 0 分 0 秒 0 毫秒 //不整月时 应该进位。
如果是闰年:2004-01-29 12:30:00,则:
31 : 2004-2-29 0001-01-30 00:00:00:000 相差 0 年 1 月 0 日 0 小时 0 分 0 秒 0 毫秒 //整月,进位
60 : 2004-3-29 0001-02-28 00:00:00:000 相差 0 年 2 月 0 日 0 小时 0 分 0 秒 0 毫秒 //整月,进位
如果跨年时:2001-12-1开始
0 : 2001-12-1 0000-00-00 00:00:00:000 相差 0 年 0 月 0 日 0 小时 0 分 0 秒 0 毫秒 //正确
1 : 2001-12-2 0000-00-00 00:00:00:000 相差 0 年 0 月 1 日 0 小时 0 分 0 秒 0 毫秒 //不对
如果时差超过一年时:以2001-12-1开始:
365 : 2002-12-1 0001-12-30 00:00:00:000 相差 1 年 0 月 0 日 0 小时 0 分 0 秒 0 毫秒
366 : 2002-12-2 0001-12-31 00:00:00:000 相差 1 年 0 月 1 日 0 小时 0 分 0 秒 0 毫秒
也有问题。
还请再试试。
来自: 萧月禾, 时间: 2002-05-30 15:24:00, ID: 1133253
to 杜宝:
刚刚我验证了一下,那方法对日期部分的处理是可以的,不管跨月处理、闰年处理都是
可以的,但。。。对时间部分处理是错误的,和formatdatetime函数处理结果有关,
搞了半天还是解决不了,看来还是得放弃用formatdatetime的方法了[
]
来自: 萧月禾, 时间: 2002-05-30 15:31:00, ID: 1133278
写成这个过程,日期部分返回结果试了几下,应该是正确的
但时间部分不对,搞不懂 [
]
procedure GetDateTimeDiff(const D1, D2: TDateTime
var AYear,
AMonth, ADay, AHour, AMin, ASec, AMSec: Word)
var
sDateDiff: string
begin
//
sDateDiff := formatdatetime('yyyy-mm-dd hh:ss:nn:zzz', D1 - D2 -693594 + 1 )
AYear := StrToInt(Copy(sDateDiff,1,4)) - 1
AMonth := StrToInt(Copy(sDateDiff,6,2)) - 1
ADay := StrToInt(Copy(sDateDiff,9,2)) - 1
AHour := StrToInt(Copy(sDateDiff,11,2))
AMin := StrToInt(Copy(sDateDiff,15,2))
ASec := StrToInt(Copy(sDateDiff,18,2))
AMSec := StrToInt(Copy(sDateDiff,21,3))
end
来自: 萧月禾, 时间: 2002-05-30 15:47:00, ID: 1133312
有个地方写错了,应该从12开始,不是11
AHour := StrToInt(Copy(sDateDiff,12,2))
这样的话,一直到小时部分的差值是正常的
但,毫秒的差值不起作用,这也罢了
最搞不懂的是,分和秒的差值居然是正好相反的
即分差的值出现在秒差的位置,秒差的值出现在分差的位置
顺序似乎又没错。。。。真搞不懂
来自: 萧月禾, 时间: 2002-05-30 15:57:00, ID: 1133325
原来是formatdatetime里面的格式写错了(顺手拷上面某仁兄的)
现在可以了,但对毫秒还是不起作用
procedure GetDateTimeDiff(const D1, D2: TDateTime
var AYear,
AMonth, ADay, AHour, AMin, ASec, AMSec: Word)
var
sDateDiff: string
begin
//
sDateDiff := formatdatetime('yyyy-mm-dd hh:mm:ss:nnn', D1 - D2 -693594 + 1 )
AYear := StrToInt(Copy(sDateDiff,1,4)) - 1
AMonth := StrToInt(Copy(sDateDiff,6,2)) - 1
ADay := StrToInt(Copy(sDateDiff,9,2)) - 1
AHour := StrToInt(Copy(sDateDiff,12,2))
AMin := StrToInt(Copy(sDateDiff,15,2))
ASec := StrToInt(Copy(sDateDiff,18,2))
AMSec := StrToInt(Copy(sDateDiff,21,3))
end
来自: 杜宝, 时间: 2002-05-30 16:12:00, ID: 1133352
呵呵,小弟以为,萧兄的方法,关键是那个常数定位的准确性。
但有个问题是:日期是有一定连续性的,是线性的;但读法就不一定,它是非线性的
因此如果用一个常数来处理的话(等差数列,是线性的),我想是有问题的。
还有就是小数的问题,如果用常数的话,涉及到与整数位的进位,这样就有问题了。
萧兄的第一次修改程序小弟测试还是有问题:
比如:
2001.12.1与 2002-10-31 0 小时 0 分 0 秒
萧兄的是:
0 年 11 月 0 日
小弟的是:
0 年 10 月 30 日 0 小时 0 分 0 秒 0 毫秒,
第二次的formatDateTime修改后,小数位先不论:
2001.12.1 0:0:0.000
364 : 2002-11-30
相差 0 年 11 月 30 日 0 小时 0 分 0 秒 0 毫秒 //萧兄
相差 0 年 11 月 29 日 0 小时 0 分 0 秒 0 毫秒 //小弟
加上小数位后差异更大。
想请萧兄把测试程序贴出来。
来自: 萧月禾, 时间: 2002-05-30 16:27:00, ID: 1133378
这是我的测试程序,通过修改edit中的日期格式的字符串的值来进行测试
不是很全面,不过我试了许多例子确实没发现错误的结果
另外,至于那个常数,你用0减去它,再转为日期型,看看是什么[
]
procedure TForm1.rbbtnRzBitBtn1Click(Sender: TObject)
var
AYear, AMonth, ADay, AHour, AMin, ASec, AMSec: Word
D1, D2: TDateTime
begin
D1 := StrToDateTime(edit2.text);//2002-01-01 00:00:00:000 格式
D2 := StrToDateTime(edit3.text);//2002-01-01 00:00:00:000
GetDateTimeDiff(D1, D2, AYear, AMonth, ADay, AHour, AMin, ASec, AMSec)
edit1.text := inttostr(AYear)+ '年'+ inttostr(AMonth)+'月'+ inttostr(ADay)+'日'+
inttostr(AHour)+'小时'+ inttostr(AMin)+'分'+ inttostr(ASec)+'秒'
end
来自: 杜宝, 时间: 2002-05-30 16:41:00, ID: 1133412
萧兄的东东,小弟把它改了一下:
function GetDateTimeDiff(const D1, D2: TDateTime):String
const
Fmt = '相差 %d 年 %d 月 %d 日 %d 小时 %d 分 %d 秒 %d 毫秒'
var
sDateDiff: string
AYear, AMonth, ADay, AHour, AMin, ASec, AMSec: Word
begin
//
sDateDiff := formatdatetime('yyyy-mm-dd hh:mm:ss:nnn', D2 - D1 -693594 +1 )
AYear := StrToInt(Copy(sDateDiff,1,4)) - 1
AMonth := StrToInt(Copy(sDateDiff,6,2)) - 1
ADay := StrToInt(Copy(sDateDiff,9,2)) - 1
AHour := StrToInt(Copy(sDateDiff,12,2))
AMin := StrToInt(Copy(sDateDiff,15,2))
ASec := StrToInt(Copy(sDateDiff,18,2))
AMSec := StrToInt(Copy(sDateDiff,21,3))
Result :=inttostr(AYear)+ '年'+ inttostr(AMonth)+'月'+ inttostr(ADay)+'日'+
inttostr(AHour)+'小时'+ inttostr(AMin)+'分'+ inttostr(ASec)+'秒'
// Result := Format(Fmt,[AYear,AMonth,ADay,AHour,AMin,ASec,AMSec])
end
我的测试代码:
procedure TForm1.Button1Click(Sender: TObject)
var
t1,t2:TDateTime
i:Integer
s,s1:String
begin
T1:=StrToDateTime('2003-12-01 0:0:0.000')
for i := 0 to 370 do
begin
T2 := T1 + i*1{.01}
//测试小数不注释。
s:=GetDateTimeDiff(t1,t2)
s1:=De2DateTime(T1,T2)
memo1.Lines.Add(IntToStr(i)+' : '+DateTimeToStr(t2)+' '+s+' '+s1)
end
end
在小弟的机器上还是有问题:
365 : 2004-11-30 1年0月0日0小时0分0秒 相差 0 年 11 月 29 日 0 小时 0 分 0 秒 0 毫秒
366 : 2004-12-1 1年0月1日0小时0分0秒 相差 1 年 0 月 0 日 0 小时 0 分 0 秒 0 毫秒
367 : 2004-12-2 1年0月2日0小时0分0秒 相差 1 年 0 月 1 日 0 小时 0 分 0 秒 0 毫秒
我的想法,萧兄不应该把这个常数设定为整数,可能它是一个小数的说。
我想这和数据类型的二进制表示精度有关。
但现在我对这种方法,不太看好,原因就是上面我说的。^_^
来自: 萧月禾, 时间: 2002-05-30 16:55:00, ID: 1133437
杜大侠果然是个严谨的人[
]
不过那个常数是经过换算得来的,的确是个整数,加上小数反而不正确了
其实我只想尽量用最简单的方法去解决问题
我再测试一下,如果真的不行再考虑放弃罢
来自: zhihuali, 时间: 2002-05-30 18:29:00, ID: 1133664
个人认为时间相差的年跟月很难说,倒不如说过了多少天来的准确;所以日期部分自己去
改良一下(不知道我的结果正确不正确,反正我没有测试。呵呵!)。
function GetDateTimeDiff(const D1, D2: TDateTime): String
const
Fmt = '现已经正常运行 %d 年 %d 月 %d 日 %d 小时 %d 分 %d 秒'
var
DT : TDateTime
D : Integer
T : TTime
Year, Month, Day : Word
Hour, Min, Sec, mSec, mSec0, mSec1 : Word
begin
DT := D2 - D1
D := Trunc(DT)
T := DT - D
if D > 0 then
begin
Year := D div 365
Month := (D mod 365) div 30
Day := (D mod 365) mod 30
end
else
begin
Year := 0
Month := 0
Day := 0
end
DecodeTime(D2, Hour, Min, Sec, mSec0)
DecodeTime(D1, Hour, Min, Sec, mSec1)
if mSec1 > mSec0 then
T := T + EncodeTime(0, 0, 1, 0)
DecodeTime(T, Hour, Min, Sec, mSec)
Result := Format(Fmt, [Year, Month, Day, Hour, Min, Sec])
end
来自: 南宫吹云, 时间: 2002-05-30 19:33:00, ID: 1133759
各位的讨论好精辟呀,收藏。
来自: 杜宝, 时间: 2002-05-30 19:39:00, ID: 1133766
呵呵,首先,我的程序有问题,就是对于1.31 到 3.1之后的日期取数有问题:
2001.1.31 到 2001.3.1 相隔应该是1个月零1天,但我的上面的程序是30天,
这是不对的。
原因是对天数的取值不对,因为天数与月分的关系不是单纯的进位的关系,所
以不能直接借位取。改成:
...
DDay := EDay - SDay;//取天差,这里就复杂了!
if DDay < 0 then
begin
DDay := DaysInMonth(SDay) - SDay + EDay;//到月底,再加
EDate := IncMonth(EDate,-1)
InitVars
end
...
就OK 了。
萧兄的说常数的问题,是我的概念有问题,萧兄是对的。我试了一下,萧兄的方法对于秒
位的处理都是正确的。微秒的方法应该是精度的问题了。
黎兄的程序对于时间的处理是对的,但对日期的处理还是有问题。除了我说2月计算以外
对于跨月的处理有问题例如:
从2004.1.31到 2005-1-25
现已经正常运行 0 年 12 月 0 日 0 小时 0 分 0 秒
相差 0 年 11 月 25 日 0 小时 0 分 0 秒 0 毫秒
出现了12个月的情况。这不是进位的问题是计算不对。
来自: zhihuali, 时间: 2002-05-30 19:52:00, ID: 1133787
To : 杜宝
>> 黎兄的程序对于时间的处理是对的,但对日期的处理还是有问题。
呵呵,我可能没有说清楚我的意思;我说了,时间相差的年跟月很难说,
倒不如说过了多少天来的准确(所以我算了天数后随便处理年月日的关系);
我在日期部分的处理只是起个抛砖引玉的作用,并不是有问题。
所以我说明了自己去改良后再用啊。什么都说的清清楚楚的就没有意思了。
来自: 杜宝, 时间: 2002-05-30 20:04:00, ID: 1133802
呵呵,黎兄所说的道理,小弟是极为认同的。本贴的问题其实是个惯用语的问题。
惯用语确实不如时间差来得精确。但楼主就是这么要求的,小弟也没办法^_^
其实我与萧兄讨论的重点, 是在于能不能用简单的增减一个常量来读出这个惯用语
现在看来,常数的方法可能有问题,2月份的处理这关就过不了。所以我现在怀疑黎
兄的东东不能能改良得出来。
就事论事,黎兄见笑了。
来自: zhihuali, 时间: 2002-05-30 20:05:00, ID: 1133803
如果今天晚上睡觉时还没有结束就抽空写完整一点。希望杜兄和萧兄写一个
简单有效的过程函数来解决,呵呵。我觉得这个问题虽然不难,但要有效并简单
解决就。。。,不知道大家怎么看?
来自: 叮叮当当, 时间: 2002-05-30 20:30:00, ID: 1133856
To: 杜宝
你早上重写的程序好像没问题了,我测试了几个数据,很完美!:)[
]
我正在消化吸收,如果没有意外的话,这个帖子就快结了。[8D]
来自: 萧月禾, 时间: 2002-05-30 20:51:00, ID: 1133891
凭良心说,我那个函数有什么问题吗?
我真的测不出不妥的地方呀???[
]
来自: 萧月禾, 时间: 2002-05-30 21:08:00, ID: 1133916
哦,我明白我错在什么地方了,多谢杜兄提点
你才是正确的[
]
来自: 叮叮当当, 时间: 2002-05-30 21:48:00, ID: 1133973
TO: 萧月禾
我也一直想寻求一种简单的解决这个问题的办法,就像你的程序,可惜事与愿违。
TO: 杜宝
我把你的代码整理了一下,附上测试程序:
新建一个Application,在窗体上放置一个TEdit和一个TTimer,双击Timer1让IDE生成OnTimer事件,然后粘贴下面整段代码,按F9运行。
代码:
unit Unit1
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls
type
TForm1 = class(TForm)
Edit1: TEdit
Timer1: TTimer
procedure FormCreate(Sender: TObject)
procedure Timer1Timer(Sender: TObject)
private
{ Private declarations }
public
{ Public declarations }
end
procedure DateTimeDiff(St, Et: TDateTime
out Y, M, D, H, N, S, MS: Word)
var
Form1: TForm1
implementation
uses DateUtils
var
BeginTime: TDateTime
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject)
begin
BeginTime := Now
end
procedure TForm1.Timer1Timer(Sender: TObject)
var
Y, M, D, H, N, S, MS: Word
begin
DateTimeDiff(BeginTime, Now, Y, M, D, H, N, S, MS)
Edit1.Text := Format('已运行 %d 年 %d 月 %d 日 %d 小时 %d 分 %d 秒 %d 毫秒',
[Y, M, D, H, N, S, MS])
end
procedure DateTimeDiff(St, Et: TDateTime
out Y, M, D, H, N, S, MS: Word)
var
SYear, SMonth, SDay, SHour, SMin, SSec, SMSec: Word
// 开始时间
EYear, EMonth, EDay, EHour, EMin, ESec, EMSec: Word
// 结束时间
DYear, DMonth, DDay, DHour, DMin, DSec, DMSec: Integer
// 时差
EDate: TDateTime
// 中间变量
i: Integer
// 中间变量,记录时差间隔。
procedure InitVars
begin
DecodeDateTime(EDate, EYear, EMonth, EDay, EHour, EMin, ESec, EMSec)
end
begin
if St > Et then // 参数出错
begin
EDate := St
// 交换起止时间
St := Et
Et := EDate
end
// 变量初始化。
DecodeDateTime(St, SYear, SMonth, SDay, SHour, SMin, SSec, SMSec)
EDate := Et
InitVars
// 进位的加减,不足则借位。
// 从最低位开始,先来毫秒位:
DMSec := EMSec - SMSec
// 取毫秒位差
if DMSec < 0 then
begin
DMSec := 1000 + DMSec
EDate := IncSecond(EDate, -1)
// 借位
InitVars
// 改变量
end
DSec := ESec - SSec
// 取秒位差
if DSec < 0 then
begin
DSec := 60 + DSec
EDate := IncMinute(EDate, -1)
InitVars
end
DMin := EMin - SMin
// 取分钟差
if DMin < 0 then
begin
DMin := 60 + DMin
EDate := IncHour(EDate, -1)
InitVars
end
DHour := EHour - SHour
// 取小时差
if DHour < 0 then
begin
DHour := 24 + DHour
EDate := IncDay(EDate, -1)
InitVars
end
DDay := EDay - SDay
// 取天差,这里就复杂了!
if DDay < 0 then
begin
DDay := DaysInMonth(SDay) - SDay + EDay
// 到月底再加
EDate := IncMonth(EDate, -1)
InitVars
end
DMonth := EMonth - SMonth
// 取月差
if DMonth < 0 then
begin
DMonth := 12 + DMonth
EDate := IncYear(EDate, -1)
InitVars
end
DYear := EYear - SYear
// 取年差
Assert(DYear >= 0, '应该不可能小于0!')
Y := DYear
M := DMonth
D := DDay
H := DHour
N := DMin
S := DSec
MS := DMSec
end
end.
你的程序才是真正符合我要求的。
向你的严谨态度致敬!
来自: hjb_dydd, 时间: 2002-05-30 22:20:00, ID: 1134027
好象不用这么烦吧!
好象SQL Server里有专门的函数的嘛!好象就叫DATEDIFF( )的!只要两个参数就可以了!
来自: 冰封, 时间: 2002-05-31 0:53:00, ID: 1134241
“来自:叮叮当当, 时间:2002-5-29 23:15:00, ID:1131940
TO: xiao_ping
menxin的程序最后好像也有问题(计算天数的地方):
r3:=DayOf(Date2)-DayOf(Date1) +IfThen(DayOf(Date1)<=DayOf(Date2),0,DaysInMonth(StartOfTheMonth(Date2)-1))
假如
Date1=2000-01-30
Date2=2000-03-31
则
StartOfTheMonth(Date2)=2000-03-01
StartOfTheMonth(Date2)-1=2000-02-29 (TDataTime的整数部分就是天数,减1就等于天数减1)
DaysInMonth(StartOfTheMonth(Date2)-1)=29
DayOf(Date1)<=DayOf(Date2) 成立,因此 r3:=DayOf(Date2)-DayOf(Date1) +29=31-30+29=30 (天)
这是错误的,应该是“2个月零1天”。
”
to 叮叮当当:
你得到你要的答案了吗?
我测试了一下menxin的程序,发现你之前分析的结果有错。
我运行得到的结果是2个月零1天没错呀。
另外我觉得,如果月份不以固定的天数计算,会出现让人理解上的错误,
假如 Date1=2000-01-30 Date2=2000-03-29,这样应该是过了1个月28天或者1个月29天或者1个月30天?
来自: 冰封, 时间: 2002-05-31 0:57:00, ID: 1134243
不过menxin的程序的确有他的错误。
我认为还是用天表示就好,否则容易让人误解。
来自: 叮叮当当, 时间: 2002-05-31 1:15:00, ID: 1134258
TO: 冰封
>另外我觉得,如果月份不以固定的天数计算,会出现让人理解上的错误,
>假如 Date1=2000-01-30 Date2=2000-03-29,这样应该是过了1个月28天或者1个月29天或者1个月30天?
也有点道理,差点连我自己也不知道结果应该是什么了,不过我用杜宝兄的程序试了一下,返回的是“1月30日”。我想了一下,这也很好解释呀。那个“1月”是指2月份整月(29天),30天是指3月份的1号~29号+1月份的31号。[
]我这个也有道理的啊:D
来自: 叮叮当当, 时间: 2002-05-31 1:26:00, ID: 1134264
谢谢大家!给分了。
来自: 杜宝, 时间: 2002-05-31 1:44:00, ID: 1134275
很不爽!!!!!睡前忍不住再说两句,感觉这个贴里面说的人多,做的人少。
这种程序,我想只要多测试就能看出效果。很多方法,其实只要充分测试一下,
就可以看出好坏来了。我不知道大家测试的数据有多少,我自己测试的时候,
基本都用1000个组数据做循环,再加上小数位的,具体可以看我上面的贴子。
冰封朋友说menxin的方法是对的,好,那我们来做个测试:
新建一个工程,加一个Button 一个 Memo,把我的程序:
De2DateTime贴上,
begin
...
//结果!
Result := Format('两个日期相差%d年%d个月%d天',[Dyear,DMonth,DDay])
//这里改一下,统一输出。
end
再把menxin兄方法改一下:
function D2(st,et:TDateTime) :String
var
Date1,Date2:TDate
r1,r2,r3:integer
begin
Date1:=Min(st,et)
Date2:=Max(st,et)
r1:=YearsBetween(Date1,Date2)
r2:=MonthsBetween(Date1,Date2)-r1*12
r3:=DayOf(Date2)-DayOf(Date1) +IfThen(DayOf(Date1)<=DayOf(Date2),0,DaysInMonth(StartOfTheMonth(Date2)-1))
r2:= r2 + r3 div DaysInMonth(StartOfTheMonth(Date2)-1)
r3:= r3 mod DaysInMonth(StartOfTheMonth(Date2)-1)
Result := Format('两个日期相差%d年%d个月%d天',[r1,r2,r3])
end
按冰封兄的修改方法改后的版本:
function D1(st,et:TDateTime) :String
var
Date1,Date2:TDate
r1,r2,r3:integer
begin
Date1:=Min(st,et)
Date2:=Max(st,et)
r1:=YearsBetween(Date1,Date2)
r2:=MonthsBetween(Date1,Date2)-r1*12
//按冰封兄的贴子修改
r3:=DayOf(Date2)-DayOf(Date1) +IfThen(DayOf(Date1)<=DayOf(Date2),0,DaysInMonth(StartOfTheMonth(Date2)-1))
Result := Format('两个日期相差%d年%d个月%d天',[r1,r2,r3])
end
一起来做个测试:
先来menxin兄的:
procedure TForm1.Button1Click(Sender: TObject)
var
t1,t2:TDateTime
i:Integer
s,s1:String
begin
T1:=StrToDateTime('2003-12-01')
//起始日期
for i := 0 to 370 do //循环测试370天,比对370天内的不同
begin
T2 := T1 + i*1
//测试小数不注释。
s:=D2(t1,t2)
s1:=De2DateTime(T1,T2)
if s <> s1 then //两种方法不同时显示!
memo1.Lines.Add(DateTimeToStr(t1)+' : '+DateTimeToStr(t2)+' '+s+' '+s1)
end
end
如果:且不说冰封兄上面说的语义上的区别:
2003-12-1 : 2003-12-31 两个日期相差0年1个月0天 两个日期相差0年0个月30天 //这里
2003-12-1 : 2004-1-31 两个日期相差0年2个月30天 两个日期相差0年1个月30天
2003-12-1 : 2004-3-1 两个日期相差0年2个月0天 两个日期相差0年3个月0天 //这里
2003-12-1 : 2004-3-30 两个日期相差0年4个月0天 两个日期相差0年3个月29天
2003-12-1 : 2004-3-31 两个日期相差0年4个月1天 两个日期相差0年3个月30天
2003-12-1 : 2004-5-1 两个日期相差0年4个月0天 两个日期相差0年5个月0天
2003-12-1 : 2004-5-31 两个日期相差0年6个月0天 两个日期相差0年5个月30天 // 这里
2003-12-1 : 2004-7-1 两个日期相差0年6个月0天 两个日期相差0年7个月0天 //这里
2003-12-1 : 2004-7-31 两个日期相差0年8个月0天 两个日期相差0年7个月30天
2003-12-1 : 2004-8-31 两个日期相差0年9个月30天 两个日期相差0年8个月30天 //这里
2003-12-1 : 2004-10-31 两个日期相差0年12个月0天 两个日期相差0年10个月30天 //这里
谁对谁错应该很明显了吧???
好,再来冰封兄的版本
procedure TForm1.Button1Click(Sender: TObject)
var
t1,t2:TDateTime
i:Integer
s,s1:String
begin
T1:=StrToDateTime('2003-12-01')
for i := 0 to 370 do
begin
T2 := T1 + i
//测试小数不注释。
s:=D1(t1,t2)
s1:=De2DateTime(T1,T2)
if s <> s1 then
memo1.Lines.Add(DateTimeToStr(t1)+' : '+DateTimeToStr(t2)+' '+s+' '+s1)
end
end
结果:
2003-12-1 : 2004-1-31 两个日期相差0年2个月30天 两个日期相差0年1个月30天
2003-12-1 : 2004-3-1 两个日期相差0年2个月0天 两个日期相差0年3个月0天
2003-12-1 : 2004-5-1 两个日期相差0年4个月0天 两个日期相差0年5个月0天
2003-12-1 : 2004-7-1 两个日期相差0年6个月0天 两个日期相差0年7个月0天
2003-12-1 : 2004-8-31 两个日期相差0年9个月30天 两个日期相差0年8个月30天
2003-12-1 : 2004-10-31 两个日期相差0年11个月30天 两个日期相差0年10个月30天
不用我说了吧????
来自: 叮叮当当, 时间: 2002-05-31 2:01:00, ID: 1134281
TO: 杜宝
SORRY,分是少了点。
我们可以交个朋友么?MSN
schen@21cn.com,QQ:990080。
来自: 冰封, 时间: 2002-05-31 23:31:00, ID: 1136278
to 杜宝:
>>>>只要照我说那样改就成了,虽然我没试过程序,不过从数学逻辑的角度上看,一定可以。
>>这又是什么态度?难道我说“感觉这个贴里面说的人多,做的人少。”有问题吗?
这句我是对叮当得出的结果,给想了个修改的方法,而对叮当当时指的那个错误,那种修改方式是可行的,因为叮当指出一个错误,当时我误以为menxin的程序就那个错误。
就这句上我承认我回答得太片面了。
>>>>我测试了一下menxin的程序,发现你之前分析的结果有错。
>>是什么结果有错,拜托你说清楚好不好?是menxin的还是你的?
是什么结果错,我有在那个贴子之前贴出,也说了我的测试结果。你要断章取义我也没办法。至于我的还是menxin的,那没有提的必要,我的本意就是只对menxin做补充,而menxin本身程序有错,我的当然也是错的。
至于你喜欢针对我,你喜欢自我称赞,那是你的自由。
我想我作的解释很明白了,如果叮叮当当也认为我有错,那我向叮当说声“对不起”。
至于你爱怎么说你说吧,我不再与你做无谓的争执。
来自: 杜宝, 时间: 2002-05-31 23:02:00, ID: 1136320
呵呵,冰封,就是针对你,就是自我称赞,怎么了?
象你说的,
>>本来论坛就是畅所欲言的地方:
那好,我测试了一下menxin的程序,再测试你修改后的程序,证明它们是错的。
(当然,我知道这并不能证明我的程序就一定是正确的。)有何不可?
>>我测试了一下menxin的程序,发现你之前分析的结果有错。
是什么结果有错,拜托你说清楚好不好?是menxin的还是你的?
>>只要照我说那样改就成了,虽然我没试过程序,不过从数学逻辑的角度上看,一定可以。
这又是什么态度?难道我说“感觉这个贴里面说的人多,做的人少。”有问题吗?
来自: 杜宝, 时间: 2002-06-01 3:11:00, ID: 1136509
KAO,少来! 说不过了就把自己的原贴改掉,要不要我提醒你:
这本来是个技术问题,是谁把它转成对我人品的讨论的?
你说我断章取意,干嘛不说你自己断章取意???
是谁自己不做测试,还找弱智的借口来搪塞?
KAO ,手伤了??? 你上网不用手,发贴不用手???
我测试你的代码,指出你的错误,就说我针对你,你以为你是谁啊?
KAO , 你TMD小人一个!!!
来自: 萧月禾, 时间: 2002-06-01 10:00:00, ID: 1136756
看到邮件才知道这里发生的事
只是讨论个技术问题
别伤和气呀。。。。。。。。
来自: chenmin_152, 时间: 2004-11-28 15:53:45, ID: 2911000
TO: xiao_ping
menxin的程序最后好像也有问题(计算天数的地方):
<<r3:=DayOf(Date2)-DayOf(Date1) +IfThen(DayOf(Date1)<=DayOf(Date2),0,DaysInMonth(StartOfTheMonth(Date2)-1))
<<假如Date1=2000-01-30;Date2=2000-03-31
<<则
<<StartOfTheMonth(Date2)=2000-03-01
<<StartOfTheMonth(Date2)-1=2000-02-29 (TDataTime的整数部分就是天数,减1就等于天数减1)
<<DaysInMonth(StartOfTheMonth(Date2)-1)=29
<<DayOf(Date1)<=DayOf(Date2) 成立,因此 r3:=DayOf(Date2)-DayOf(Date1) +29=31-<<30+29=30 (天)
<<这是错误的,应该是“2个月零1天”。
楼主计算错误了,IfThen(DayOf(Date1)<=DayOf(Date2),0,DaysInMonth(StartOfTheMonth(Date2)-1));它表示如果DayOf(Date1)<=DayOf(Date2)则返回0,如果DayOf(Date1)>DayOf(Date2)则返回上个月的天数。
所以r3:=DayOf(Date2)-DayOf(Date1) +0(因为31>30,所以返回值为0)=31-30+0=1 (天),月份部分在r2中计算,
r1:=YearsBetween(Date1,Date2)
r2:=MonthsBetween(Date1,Date2)-r1*12
r3:=DayOf(Date2)-DayOf(Date1) +IfThen(DayOf(Date1)<=DayOf(Date2),0,DaysInMonth(StartOfTheMonth(Date2)-1))
ShowMessage(Format('两个日期相差%d年%d个月%d天',[r1,r2,r3]))
如果Date1=2000-01-30;Date2=2000-03-31,则返回两个日期相差0年2个月1天,符合楼主的要求。但是这里有个问题是,当Date1=2000-03-30;Date2=2000-04-30时,利用MonthsBetween函数计算月份差时返回值为0,这是MonthsBetween函数本身的问题。
得分大富翁: hamsoft-2,linsb-2,mlzhou-2,Pearl.-2,qdyoung-2,xiao_ping-2,zhihuali-2,冰封-6,杜宝-70,萧月禾-8,雪鹰-2,