Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>To make sense of leap years, you are almost forced to break this into two parts: an integral number of years, and a fractional part. Both need to deal with leap years, but in different ways - the integral needs to deal with a starting date of February 29, and the fractional must deal with the differing number of days in a year. You want the fractional part to increment in equal amounts until it equals 1.0 at the next anniversary date, so it should be based on the number of days in the year <em>after</em> the end date.</p> <p>Do you want your date range to include 1900 or 2100? Things get a little easier if you don't. <hr> <strong>Edit:</strong> It has taken me a long time to reason this through. The basic problem is that calendar years are not a constant size, but you're coercing them to be constant by setting them to 1.0. Any solution you come up with is going to have anomalies because of this, and you're going to have to choose which anomalies you can live with. John Machin was right.</p> <p>What's the difference between 2008-02-28 and 2009-02-28? Most people would agree that it should be exactly 1.0 years. How about the difference between 2008-03-01 and 2009-03-01? Again, most people would agree that it should be exactly 1.0 years. If you choose to represent a date as a year plus a fraction of a year based on the day, it is impossible to make both of these statements true. This is the case for your original code which assumed a day was 1/365.2425 of a year, or indeed for any code which assumes a constant fraction of a year per day, even if the size of a day accounts for the years which are leap years.</p> <p>My assertion that you needed to break this down into integral years and fractional years was an attempt to get around this problem. If you treat each of the previous conditions as an integral year, all you have to do is decide on which fraction to assign to any number of days left over. The problem with this scheme is that you still can't make sense of (date2-date1)+date3, because the fraction can't be resolved back to a day with any consistency.</p> <p>Thus I am proposing yet another encoding, based on each year containing 366 days whether it is a leap year or not. The anomalies will firstly be that there can't be a date which is exactly a year (or 2 or 3) from Feb. 29 - "Sorry Johnny, you don't get a birthday this year, there's no Feb. 29" isn't always acceptable. Second is that if you try to coerce such a number back to a date, you'll have to account for non-leap years and check for the special case of Feb. 29 and convert it, probably to Mar. 1.</p> <pre><code>from datetime import datetime from datetime import timedelta from calendar import isleap size_of_day = 1. / 366. size_of_second = size_of_day / (24. * 60. * 60.) def date_as_float(dt): days_from_jan1 = dt - datetime(dt.year, 1, 1) if not isleap(dt.year) and days_from_jan1.days &gt;= 31+28: days_from_jan1 += timedelta(1) return dt.year + days_from_jan1.days * size_of_day + days_from_jan1.seconds * size_of_second start_date = datetime(2010,4,28,12,33) end_date = datetime(2010,5,5,23,14) difference_in_years = date_as_float(end_time) - date_as_float(start_time) </code></pre> <p>I'm not suggesting that this is <em>the</em> solution, because I don't think a perfect solution is possible. But it has some desirable properties:</p> <ul> <li>The difference between any dates with the same month and day and time will be an exact number of years.</li> <li>Adding a difference to another date will result in a value that can be converted back into a useful date.</li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload