is there a function to determine the number of days between dates. For example 04/15/2010 - 03/16/2010 is 29 days. How can I determine this in a function. date format will be 04/15/2010, 03/15/2010.
Thanks for the help.
Harvey
is there a function to determine the number of days between dates. For example 04/15/2010 - 03/16/2010 is 29 days. How can I determine this in a function. date format will be 04/15/2010, 03/15/2010.
Thanks for the help.
FUNCTION CALCJOUR(WDA1,WDA2) // CALCUL NOMBRE DE JOURS ENTRE 2 VARIABLES // WDA1 ET WDA2 FORMAT JJ/MM/AAAA
LOCAL WJOURS := 0
WJOURS := (CTOD(WDA2) - CTOD(WDA1))
IF WJOURS < 0
WJOURS := 0
ENDIF
RETURN(WJOURS)hag wrote:is there a function to determine the number of days between dates. For example 04/15/2010 - 03/16/2010 is 29 days. How can I determine this in a function. date format will be 04/15/2010, 03/15/2010.
Thanks for the help.
Expanding on EMGs answer
xBase date variables can be treated as integers and basic integer operations applied to them. They are the number of days since an arbitrary start up date. (Please note this is not the format in which they are stored in .dbf files)
The number of days between date1 and date2 (inclusive) is date2 - date1 + 1
A common programming error is to forget to add the extra 1 (that is the interval between 10th March and 11th March inclusive in the same year is 2 days not 1 day).
The other potential error is that the above assumes that date2 is after date1. Robust code requires that the possibility of the dates being reversed is handled correctly. That may vary from situation to situation. If you just want the interval then ABS( date2 - date1 ) + 1 would be the better code. In other cases you may want to simply flag an error.
There are other "tricks" that flow from date variables behaving as integers.
tomorrow is DATE() + 1
this day next week is DATE() + 7
yesterday is DATE() - 1
etc
But please be careful
this day next year is not always DATE() + 365 because it may be DATE() + 366
Some years ago I came across a piece of "problem code" that was supposed to calculate a person's age in years. This code had been reported as inaccurate around a person's birthday and the code modified and retested several times but the fault persisted, at least in part. The basic approach (it wasn't actually in xBase) was like this
nAgeInYears = ( dAgeAtDate - dBirthDate ) / 365
which is doomed to failure because of the existence of leap years. Attempted modifications included adding a small fractional day, adding an INT() function etc. (They hadn't actually tried dividing by 365.25 but that still does not always yield the correct answer.) It's not a hard function to write, it is just that you can't do the calculation reliably by day interval arithmetic.
Happy programming
xProgrammer
Function Date360(FirstDate, SecondDate)
LOCAL FirstDay, SecondDay, Date360
  DO Case
    Case Day(FirstDate)=31
      FirstDay := 30
    Case Day(FirstDate)=28 .OR. Day(FirstDate)=29
      If Month(FirstDate) = 2
        FirstDay := 30
      Else
        FirstDay := Day(FirstDate)
      EndIf
    OTHER
      FirstDay := Day(FirstDate)
  EndCASE
  DO Case
    Case Day(SecondDate)=31
      SecondDay := 30
    Case Day(SecondDate)=28 .OR. Day(SecondDate)=29
      If Month(SecondDate) = 2
        SecondDay := 30
      EndIf
    OTHER
      SecondDay := Day(SecondDate)
  EndCASE
  Date360 := ((DateDiff(FirstDate, SecondDate) - 1) * 30) + ;
              (30 -FirstDay) + SecondDay
 Â
Return Date360
Function DateDiff(FirstDate, SecondDate)Â Â
Return ((year(SecondDate)*12)+Month(SecondDate))-((year(FirstDate)*12)+Month(FirstDate))Thanks to all. It is working. And I have learned a lot.
Thanks again.
The number of days between date1 and date2 (inclusive) is date2 - date1 + 1
A common programming error is to forget to add the extra 1 (that is the interval between 10th March and 11th March inclusive in the same year is 2 days not 1 day).
Hi James
Nice to discuss coding again.
I have had to use inclusive dates often, especially in things like tax calculations. It applies when a day is either included or excluded and you are dealing with a period of inclusion or exclusion. If I start a job on 10 March and finish it on 11 March it has taken 2 days. March runs from 1 March to 31 March and is a period of 31 days not 30 days (= 31 - 1). If I need this as a fraction of a year for tax purposes it has to be 31/365 not 30/365. (in fact I had to trouble shoot a problem application where they even got the denominator wrong because 31/12/xxxx - 01/01/xxxx gives 364 in a non leap year!)
This corresponds to similar adjustments required in analagous situations. For example an array that starts at index1 and ends at index n has n - 1 + 1 = n elements not n-1 elements. A substring from character 56 to character 60 is a string of length 60 - 56 + 1 = 5 characters.
Hotel accommodation runs differently if you use arrival date and departure date. You don't need to add the 1 day (but effectively you are only getting the latter part of the first day and the former part of the day of departure). Effectively the arrival date is inclusive and the departure date exclusive. If you used the first and last dates of night's accommodation you would need to add the extra day.
As you state if the dates are exclusive you would need to subtract a day. I haven't run across a case of day intervals with exclusive dates in any practical application I have been involved in.
My experience to date has mainly dealt with cases of inclusive dates. I guess the important point is that assuming that date2 - date1 gives the answer you need is fraught with danger - you need to check because you may need to add 1 to get the correct answer (if your dates are inclusive) or even subtract 1 day (if they are exclusive). Just adopting someone's interval function and assuming the answer it gives is correct (given your particular scenario) is dangerous.
I do try to be precise (although I often fail) which is why I specified inclusive. If our discussion has highlighted the need for careful evaluation of just what is needed when writing this type of code, then it just may have helped others avoid possible pitfalls.
Interestingly enough, in the case of calculating a person's age in years, something I alluded to in my previous post, you have a somewhat analagous situation where you may or may not need to subtract 1. If I take the current year as an integer and subtract the year of my birth as an integer then the result of that calculation is my age in years provided that it is past my birthday in the current year. If not then I have to subtract 1 from the result to get my age in years.
Of course, if I was for example 55 years old then I would be in my 56th year of life - think about it - we are in the first year of our life until we turn 1 year old whereupon we are in the second year of our life. I tried explaining that to a relation of mine but met great difficulty.
Regards
Doug (xProgrammer)
xProgrammer,
Yes, as you have pointed out, there are all kinds of ways to find date intervals.
Years ago I did a lot of interest caculations for various banks and each bank did them differently. Often it was very difficult to find someone at the bank that even knew how they did it. Usually, I had to get some sample data output from the mainframe and figure out how the did it by testing a series of formulas to find the one that gave the same figures.
I did create a formula for figuring age some time ago but i forget exactly how I did it. It is complicated and leap year does create another issue.
James
FUNCTION AgeInYears( dFromDate, dToDate )
LOCAL nYearDiff
nYearDiff := Year( dToDate ) - Year(dFromDate )
IF Month( dToDate ) > Month( dFromDate )
 RETURN nYearDiff
ENDIF
IF Month( dToDate ) < Month( dFromDate )
 RETURN nYearDiff - 1
ENDIF
// if we reach here we are in the month of birth date
IF Day( dToDate ) >= Day( dFromDate )
 RETURN nYearDiff
 ELSE
 RETURN nYearDiff - 1
ENDIFFUNCTION AgeAsAtToday( dDOB )
RETURN AgeInYears( dDOB, DATE() )