0

I'm developing a software and I need to subtract two dates and then get a date again. I've been trying to solve this problem for a while and I have found some additional problems. One of these problems is the "leap year" problem which I think can be solved using this algorithm

if ((Year % 400) == 0) { Is leap year }
else if ((Year % 100) == 0) { Is not }
else if ((Year % 4) == 0) { Is leap year }
else { Is not }

but even through I have solved this part, I can't figure what to in below situation (MM/DD/YYYY)

1/7/2014 - 12/30/2013 = (mm/dd/yyyy)?

So I'm looking for a pure mathematical algorithm to solve this but I'm kind of stuck because I have a very weak math background.

Edit: if i convert the date to days, then I face the problem of 30 days and 31 days months problem

Plexus
  • 111
  • 1
  • 1
  • 5
  • 3
    How is the difference (or sum) of two dates a date? I should be a timespan (possibly counted in days) or the like. Also, most languages have a datediff function that takes more into account than just leap days. – Hagen von Eitzen Jan 07 '14 at 18:23
  • The .Net Datatime does this but the result is in Total Days and it provides no dates so converting back the total days to date is a problem. – Plexus Jan 07 '14 at 18:24
  • This question is very unclear. What do you mean by "pure mathematical algorithm"? What is wrong with different months having a different number of days? Why do you consider this an obstacle? – Erick Wong Jan 07 '14 at 18:25
  • I absolutely don't want to spoil your fun, but in many programming languages comprehensive and well-thought through solutions to this kind of problems exist, like Joda-Time for Java and the derived noda-time for the .net environment. Even if for some reason you prefer a home-brew solution it may be interesting to visit the above website just to read about Instants, Intervals, Periods and Durations, the different key concepts the author uses to represent all possible time related operations. – fvu Jan 07 '14 at 18:42

3 Answers3

7

Dates form an affine space. This means that the result of subtracting two dates is not another date, but rather a time interval. For example, the result of subtracting January 1, 2013 from January 2, 2013, is the time interval of one day. It is not another date.

In an affine space, there are two sorts of things, called "points" and "vectors". In this case the points are dates and the vectors are intervals. If $a$ and $b$ are points, $i$ and $j$ are intervals, and $c$ is an ordinary number, then you can perform the following operations:

$$\begin{array}{cc} \text{operation} & \text{result type} \\ a - b & \text{interval}\\ a + i & \text{date}\\ a - i & \text{date}\\ i + j & \text{interval}\\ i - j & \text{interval}\\ c\cdot i & \text{interval} \end{array}$$

Note in particular that you can not add two dates.

Usually the easiest way to perform date calculations is to convert the dates to a so-called "epoch time", which is simply a number of days (or seconds) that have elapsed since some particular reference time, called the "epoch". For example, if we choose 1 January 2000 as the epoch, then 31 January 2000 is converted to the epoch date 30; 31 December 2000 is converted to the epoch date 365, and 1 January 2004 is converted to the epoch date 1461. Then to calculate the difference between two dates, one converts both to epoch dates and performs a simple subtraction.

The subtraction is easy, but the conversion may be complicated, because the calendar is complicated. For example, to find out that 31 December 2000 is epoch date 365 and not 364, one much know whether 2000 was a leap year, and then it makes a difference which calendar you are using; in some calendars 2000 is a leap year; in others it isn't.

You can figure out the conversions yourself, or you can use the algorithms from Calendrical Calculations by Dershowitz.

You asked in a comment how to find how many leap days are in an interval of 2,000 days, and the answer is that you can't, unless you know two things. First, what calendar are you using? And second, what day is the start of the interval? Different intervals of 2,000 days will include different numbers of leap days. In the epoch system, the question becomes: What date is 2,000 days after my start date $s$? Then to find the answer you convert $s$ to an epoch date, add 2,000, and convert back to a calendar date. If $s$ converts to the epoch date 16,077, then the date 2,000 days later is just 18,077; the tricky part is converting this back to a calendar date again.

The "Julian days" system mentioned by other posts in this thread is an example of an epoch system. The epoch date in that system is 1 January 4713 BCE. Depending on the details of your computer system, a Julian day system may or may not be the easiest thing to program.

MJD
  • 67,568
  • 43
  • 308
  • 617
  • You might want to wait to accept the answer, to see if you get another answer that you like better. – MJD Jan 07 '14 at 18:37
1

This is a terrible problem I faced decades ago and it was crucial not to be in any error. The easiest way has been, as suggested already by user44197, to use Julian Days. The book "Numerical Recipes" contains the full algorithm.

In the book entitled "Numerical Recipes in ??", you will find

a subroutine named JULDAY which returns the Julian Day corresponding to a date (month, day, year). Using this subroutine twice will allow you to perform date differences.

a subroutine named CALDAT which returns the date (month, day, year) from a Julian Day.

The homepage of "Numerical Recipes" is at http://www.nr.com/

At http://www.nr.com/oldverswitcher.html, you should be able to get free copies of these subroutines for the oldest versions of the book (in C or Fortran). These have been the subroutines I used for my work more than twenty years ago.

0

The biggest problem is that year should start on March 1 (not Jan 1). In fact it used to start on March 1 (which is why September is the 7th month, October the 8th month, November the 9th month and December the 10th).

Easiest is to pick a start date. Most commonly used is Jan 1, 1900. Then see how many days since then is any given date. You add 365 for each year, 1 more for each leap year etc. Just remember January 2014 is the 11th month of 2013!

Month numbers go: March -> 0, April -> 1 etc.

Or you can calculate the Julian Day for the date. See here for an algorithm: http://www.cs.utsa.edu/~cs1063/projects/Spring2011/Project1/jdn-explanation.html

user44197
  • 9,818