PureBasic Forumhttp://forums.purebasic.com/english/ Calculate accurate differences between date/timeshttp://forums.purebasic.com/english/viewtopic.php?f=12&t=25085 Page 1 of 1

 Author: netmaestro [ Thu Dec 21, 2006 8:13 pm ] Post subject: Calculate accurate differences between date/times Code updated for 5.20+I originally posted a version of this yesterday that seemed to work fine, until I noticed some problems. I fixed them, or so I thought, only to discover that more problems existed. It was so unreliable and my attempts at fixing it were so stupid I thought it best to take it down for the time being and see if I could get if working. I damn near despaired, I don't mind admitting. However, a minor brainwave washed over me this morning and I came up with a better approach. After a fair bit of testing I think I have something that can be relied upon to be accurate. If someone can break this, please do and post the results:Code:;=================================================== ; Program:          DateDiff library function ; Author:           netmaestro ; Date:             December 20, 2006 ; Target OS:        Windows All ; Target Compiler:  PureBasic 4.0 ; License:          Free, unrestricted, credit ;                   appreciated but not required ;=================================================== Structure TimeDiff   totaldays.l  years.l   months.l   daysremaining.l   hours.l   minutes.l   seconds.l EndStructure Procedure DateDiff(dateearly, datelate, *diff.TimeDiff)     Protected totaldays,years,months,daysremaining,hours,minutes,seconds     curdate = dateearly   testdate = dateearly   startday = Day(dateearly)   totaldays = 0  daysremaining = 0     While testdate <= datelate     testdate = AddDate(curdate, #PB_Date_Day, 1)     If testdate <= datelate       curdate = testdate       totaldays+1       daysremaining+1      If Day(curdate) = startday         months+1         daysremaining=0       EndIf     EndIf   Wend     testdate = curdate   hours = 0   While testdate

 Author: Tranquil [ Thu Dec 21, 2006 9:44 pm ] Post subject: I thought about this methode too but there must be a way without doing it in loops or?

 Author: netmaestro [ Fri Dec 22, 2006 1:22 am ] Post subject: Well, you can always fall back on the good old windows scripting host. VBScript has a native DateDiff function and you can build a command string, save it to a file and execute it with RunProgram. There's an example of using it to solve an expression here: http://www.purebasic.fr/english/viewtopic.php?t=24957&start=3 It would just be a matter of modifying it to do DateDiff, shouldn't be hard.

 Author: PB [ Fri Dec 22, 2006 8:48 am ] Post subject: > there must be a way without doing it in loops DoubleDutch posted a similar tip in 2005 that doesn't use loops: http://www.purebasic.fr/english/viewtopic.php?t=18366 @netmaestro: Why doesn't your tip show weeks?

 Author: netmaestro [ Fri Dec 22, 2006 12:59 pm ] Post subject: I'm only looping for one reason, and that's to count accurately the number of calendar months that passed between the two dates. Everything up to weeks can be got easily with arithmetic, as their lengths never change. I'm working on a better version of this using a SYSTEMTIME structure which will handle dates before 1970 and can do stuff like tell you "You've been a human being for 62 years, 3 months, 22 days, 4 hours, 27 minutes and 13 seconds"

 Author: jear [ Fri Dec 22, 2006 1:12 pm ] Post subject: What's about this code Code:; TimeDiffString : jear Dez 2005;#TimeUnits = "Woche|n,Tag|e,Stunde|n,Minute|n,Sekunde|n"#TimeUnits = "week|s,day|s,hour|s,minute|s,second|s"  Procedure.s AddTimeUnit(number.l, unit.l)   Protected Result.s, sUnit.s  If number = 0 : ProcedureReturn "" : EndIf  If number < 0 : number * -1 : EndIf  sUnit = StringField(#TimeUnits, unit, ",")  If number > 1    sUnit = RemoveString(sUnit, "|")  Else    sUnit = StringField(sUnit, 1, "|")  EndIf  Result + Space(1) + Str(number) + Space(1) + sUnit    ProcedureReturn Result EndProcedure Procedure.s sTimeDiff(Seconds.l)   Protected Result.s  Protected Weeks.l, Days.l, Hours.l, Minutes.l  Weeks   = Seconds / 604800 : Seconds = Seconds % 604800  Days    = Seconds / 86400  : Seconds = Seconds % 86400  Hours   = Seconds / 3600   : Seconds = Seconds % 3600   Minutes = Seconds / 60     : Seconds = Seconds % 60   Result = AddTimeUnit(Weeks,1)   Result + AddTimeUnit(Days,2) : Result + AddTimeUnit(Hours,3)   Result + AddTimeUnit(Minutes,4) : Result + AddTimeUnit(Seconds,5)   ProcedureReturn ResultEndProcedurePastDate.l = ParseDate("%dd.%mm.%yyyy", "20.12.2005 12:00")Debug Date() - PastDateDebug sTimeDiff(Date() - PastDate)Delay(2000)Debug PastDate - Date()Debug sTimeDiff(PastDate - Date())

 Author: rsts [ Fri Dec 22, 2006 3:51 pm ] Post subject: netmaestro wrote:"You've been a human being for 62 years, 3 months, 22 days, 4 hours, 27 minutes and 13 seconds" Once again, you amaze me. How the heck did you know that? cheers

 Author: rsts [ Thu Feb 20, 2014 8:30 pm ] Post subject: Re: Calculate accurate differences between date/times If I run the datediff routine above as is, seems OK.If I change the "test" fromdateearly = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2005/9/9/12:30:00") todateearly = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2010/12/31/12:30:00") or evendateearly = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2005/10/30/12:30:00")it appears to fail.Did anything weird happen on the update to 5.20+ or was it always like this?cheers

 Author: Demivec [ Thu Feb 20, 2014 8:44 pm ] Post subject: Re: Calculate accurate differences between date/times rsts wrote:If I run the datediff routine above as is, seems OK.If I change the "test" fromdateearly = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2005/9/9/12:30:00") todateearly = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2010/12/31/12:30:00") or evendateearly = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2005/10/30/12:30:00")it appears to fail.When I tested, it appears to work correctly for the dates you gave. Why are you saying it fails?

 Author: rsts [ Thu Feb 20, 2014 8:51 pm ] Post subject: Re: Calculate accurate differences between date/times For the original test date I get 8 years 5 monthsfor the test date of dateearly = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2005/10/30/12:30:00") slightly over 1 month different, I get 7 years 7 months. Or have I gone mad (very possible at this stage

 Author: Demivec [ Thu Feb 20, 2014 10:41 pm ] Post subject: Re: Calculate accurate differences between date/times rsts wrote:For the original test date I get 8 years 5 monthsfor the test date of dateearly = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2005/10/30/12:30:00") slightly over 1 month different, I get 7 years 7 months. Or have I gone mad (very possible at this stage I see the problem now. When I did my tests I looked solely at the day count, which is correct.The month count is incorrectly calculated. And the year count is based on the possibly faulty month count.When I have a moment I will post a solution.

 Author: rsts [ Thu Feb 20, 2014 11:25 pm ] Post subject: Re: Calculate accurate differences between date/times My apologies, Demivec. I should have been clearer as to what the fault was. I was just wondering if the error was introduced in the update to 5.2 or if it had been there all along. I imagine only netmaestro can answer that since I do not have the original source.Thanks for your assistance in looking at it.cheers

 Author: Demivec [ Fri Feb 21, 2014 4:44 pm ] Post subject: Re: Calculate accurate differences between date/times rsts wrote:My apologies, Demivec. I should have been clearer as to what the fault was. I was just wondering if the error was introduced in the update to 5.2 or if it had been there all along. I imagine only netmaestro can answer that since I do not have the original source.Thanks for your assistance in looking at it.The error wasn't due to anything that changed in v5.21 LTS. The error was in the original code.As I said earlier, the error is in how the calendar months are counted. Netmaestro compared the starting calendar day to each sequential day in turn, if the day in the month matched the number of months that occurred thus far was incremented.Unfortunately not all months are the same length. This means if you started on a day (i.e. 1/31 of any year) and counted 40 more days you still wouldn't come to the day '31' of the next month because February would have only 28 or 29 days. This happens at various places around the calendar year and can make the month count inaccurate if the starting day is the 29th, 30th, or 31st of the month.Because the year count is based off of the month count it will also be affected.The end result is that the TotalDays count was correct, as were the hours, minutes, seconds. I believe the day count was also correct.To correct the error you can change line 37 from:Code:If Day(curdate) = startdaytoCode:If Day(curdate) = startday Or (startday > 28 And Day(curdate) = 1 And daysremaining > 3)

 Author: rsts [ Fri Feb 21, 2014 6:11 pm ] Post subject: Re: Calculate accurate differences between date/times I did not catch that.Gratitude for your assistance

 Author: Demivec [ Fri Feb 21, 2014 6:37 pm ] Post subject: Re: Calculate accurate differences between date/times rsts wrote:I did not catch that.Gratitude for your assistance Your welcome. I forgot to mention what was involved in the change. To properly count a full month of days the line checks for three additional conditions if the simple case fail. The simple case is if the day in the month is the same as the starting day.Having failed the simple case, the three additional cases are checked for and all need to be met to mark off another month. These conditions are seeing if the starting day is one of the problematic ones (29th, 30th, or 31st), and if the current day is now day 1 (this signals we went from the end of a possibly shorther month to the start of the next month) and finally, if we have counted more than 3 days since the last time the month count was incremented (this last test makes sure the count won't increment unnecessarily for the first few days after a start day of 29, or 30 if this is a long month with 30 or 31 days).

 Page 1 of 1 All times are UTC + 1 hour Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Grouphttp://www.phpbb.com/