Efficient algorithm for converting number of days to years (including leap years)

后端 未结 10 1979
逝去的感伤
逝去的感伤 2021-02-05 17:04

The problem

I am writing a class for holding dates in c++, and I found the following problem:

I have a number of days N since a reference date (in

相关标签:
10条回答
  • 2021-02-05 17:33

    Let me simplify the question, I won't consider exceptions for explanation. Every 4 years, a leap occur, if you have 365*5 days, there must be a leap-year (unless if the exception 2 is applied). You could just use division for having the number of leap-years (if ignoring the exceptions).

    Then you can easily use division and remainder for having the non-leap years/months/days.

    Use the same basic intuition for resolving the Exception 1 (if the number of years is a multiple of 100, then also check the Exception 2)

    1. Years which are divisible by 4 are leap
    2. Exception to rule 1: years that are divisible with 100 are not leap
    3. Exception to rule 2: years that are divisible with 400 are leap
    0 讨论(0)
  • 2021-02-05 17:36

    I have a number of days N since a reference date (in my case that would be Jan 1, 0001 AD)...

    In that case, "efficiency" in applying the 4-100-400 rule and looking up month lengths is not your main problem. Please be also aware of the multiple problems inherent in applying today's Gregorian calendar to dates predating its inception, and the fact that Gregorian was not introduced uniformly. (*)

    Wikipedia is a good starting point to a very involved subject.

    (*): Depending on country, anywhere between 15 October 1582 and 15 February 1923, resp. not at all, actually.

    0 讨论(0)
  • 2021-02-05 17:41
    bool IsLeapYear(int year)
    {
        boost::gregorian::date d1(year, 1, 1);
        boost::gregorian::date d2 = d1 + boost::gregorian::years(1);
        boost::gregorian::date_duration diff = d2 - d1;
        return diff.days() != 365;
    }
    
    0 讨论(0)
  • 2021-02-05 17:42

    This

    bool IsLeapYear(int year) 
    { 
        if ((year % 4 == 0) && (year % 100 != 0) && (year % 400 == 0)) return true; 
        else return false; 
    }
    

    is incorrect. It returns false for 2000. Better:

    bool IsLeapYear(int year) 
    { 
        if (year % 400 == 0) return true; 
        if ((year % 4 == 0) && (year % 100 != 0)) return true; 
        return false; 
    }
    
    0 讨论(0)
提交回复
热议问题