Page 1 of 1

DateDiff ?

Posted: Wed Dec 20, 2006 4:18 pm
by va!n
I have a little problem to calculate the time different between two days/times. If someone can show me a working way, it would be nice. What i need is something like:

Procedure Diff (sTimeStamp1.s, sTimeStamp2.s) ; sTimeStamp.s = like 1166173200

Result = "x Years, x Months, x Days, x Hours, x Minutes, x Seconds"

thanks.

Posted: Wed Dec 20, 2006 4:36 pm
by Tranquil
This is difficult to calculate course there are month with 28/30/31 days. How many days do you want to expect in your difference calculation? 31?

And why holding the timevalue in a string?

Posted: Wed Dec 20, 2006 4:48 pm
by Trond

Code: Select all

DateDifference = DateLate-DateEarly

Code: Select all

Procedure.l YearDiff(Date)
  ProcedureReturn Year(Date)-1970
EndProcedure

Procedure.l MonthDiff(Date)
  ProcedureReturn Month(Date)-1
EndProcedure

Procedure.l DayDiff(Date)
  ProcedureReturn Day(Date)-1
EndProcedure

Debug YearDiff(DateDifference)
Debug MonthDiff(DateDifference)
Debug DayDiff(DateDifference)
Debug Hour(DateDifference)
Debug Minute(DateDifference)
Debug Second(DateDifference)

Posted: Wed Dec 20, 2006 5:09 pm
by netmaestro
Won't work, Trond, because the pattern of months will rarely line up properly. Take a six-month date difference, the months will always be assumed to be jan-feb-mar-apr-may-june, which will affect the number of days returned. See the error with these dates:

Code: Select all

dateearly = ParseDate("%yyyy/%mm/%dd/%hh:%ii:%ss", "2006/6/01/00:00:00") 
datelate =  Date()
Too many days! Also - leap years counted in the wrong place will throw it off by a whole day for longer differences.

Posted: Sat Dec 30, 2006 10:34 pm
by atnheaderlen
Date (...) returns the seconds if a date is entered.
If you do that with the beginn-date and end-date and after this subtract the values you get the difference in seconds. It should be easy to get the days/months/years then.

Posted: Sun Dec 31, 2006 12:14 am
by jear
This code will return the time difference as string.

Code: Select all

; 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 Result 
EndProcedure 

PastDate.l = ParseDate("%dd.%mm.%yyyy", "20.12.2005 12:00") 
Debug Date() - PastDate 
Debug sTimeDiff(Date() - PastDate) 
Delay(2000) 
Debug PastDate - Date() 
Debug sTimeDiff(PastDate - Date())

Posted: Sun Dec 31, 2006 12:43 am
by Tranquil
@jear:

Your routine gives not the correct results that was requested by vain.

Take a look on the Tips&Tricks section:

http://www.purebasic.fr/english/viewtopic.php?t=25085

Posted: Tue Jan 02, 2007 11:39 am
by Lewis
You can use the following code to compute the day difference.

Code: Select all

Procedure.l Days(Year.l, Month.l, Day.l) 
  ; CONVERT DATE PARTS TO JULIAN DAY (SERIAL) NUMBER: 
  A.l = (14 - Month.l) / 12 
  Y.l = Year.l + 4800 - A.l 
  M.l = Month.l + (12 * A.l) - 3 
  D.l = Day.l + Int((153 * M.l + 2) / 5) + (365 * Y.l) + Int(Y.l / 4) 
  ProcedureReturn = D.l - Int(Y.l / 100) + Int(Y.l / 400) - 32045 
EndProcedure 

Debug days(2004,3,1) - days(2004,2,28) ; 2004 was a leap year
Debug days(2001,1,1) - days(2000,1,1)  ; 2000 was a leap year
Debug days(1901,1,1) - days(1900,1,1)  ; 1900 was not a leap year
Debug days(2000,1,1) - days(1900,1,1)  ; 24 leap years between centennials
Debug days(2100,1,1) - days(2000,1,1)  ; ... unless least centennial is divisible by 400
Debug days(1908,7,19) - days(756,3,29)
The Debug Output window displays:
  • 2
    366
    365
    36524
    36525
    420871
Are the results correct? You can bet your bottom dollar on it! :)

Now all that remains is for you to do the time (clock) computation (and, if necessary, subtract a day from the day difference computation).

You might also find (the last part of) this thread interesting: As a sidenote, you might be wondering why I choose to use Int() in the Days() function. Well, it's because it's easier for me to write those to ensure that I get integer arithmetic than to constantly try to figure out whether PureBasic will automatically apply integer arithmetic to the computation. Not a big deal, I know, but one needs to be constantly on one's toes to avoid inadvertent use of the float library. I asked for it before (early 2006, I believe) and I noticed that others have recently requested the same in the Wishlist sub-forum: PLEASE, PLEASE, PLEASE give us an integer division operator (eg Div).

Posted: Tue Jan 02, 2007 2:53 pm
by dell_jockey
Lewis wrote: PLEASE, PLEASE, PLEASE give us an integer division operator (eg Div).
Have you considered using the mod-operator (%) to create a DIV ?

Posted: Tue Jan 02, 2007 3:04 pm
by gnozal
I used this one in an old project :

Code: Select all

Procedure.l Julian(year.l, month.l, day.l)
  Protected Days.l, yearsBC.l, yearsAD.l
  If month < 3
    month = month + 12
    year = year - 1
  EndIf
  yearsBC = 4714 - 1                              
  yearsAD = year - 1  
  Days = Int((yearsBC + yearsAD) * 365.25)
  Days = Days - (year / 100)
  Days = Days + (year / 400) 
  Days = Days + Int(30.6 * (month - 1) + 0.2)
  ProcedureReturn Days + day
EndProcedure
It seems to pass the Lewis test !
2
366
365
36524
36525
420871

Posted: Tue Jan 02, 2007 5:45 pm
by Lewis
dell_jockey wrote:
Lewis wrote: PLEASE, PLEASE, PLEASE give us an integer division operator (eg Div).
Have you considered using the mod-operator (%) to create a DIV ?
I'm sure you're just dying to enlighten me, so go ahead! :)

Posted: Tue Jan 02, 2007 8:51 pm
by PB
>> Have you considered using the mod-operator (%) to create a DIV ?
>
> I'm sure you're just dying to enlighten me, so go ahead! :)

http://www.purebasic.com/documentation/ ... ables.html

Posted: Tue Jan 02, 2007 11:00 pm
by Lewis
PB wrote:>> Have you considered using the mod-operator (%) to create a DIV ?
>
> I'm sure you're just dying to enlighten me, so go ahead! :)

http://www.purebasic.com/documentation/ ... ables.html
What nonsense is this? Why on earth would you think that directing me to the modulo entry in the PureBasic Reference Manual would make me any the wiser? :x