#include <time.h>

static int is_leap_year(const int y)
{
    if(y & 3) return 0;         // Not divisible by 4
    switch(y % 400) {           // Divisible by 100, but not by 400 (1900, 2100, 2200, 2300, 2500, 2600)
        case 100: case 200: case 300: return 0; 
    }
    return 1;                   // Divisible by 4 and !(100 and !400)
}

void rtc_tick(struct tm *t)
{
    static const signed char dim[12][2] = {             // Number of days in month for non-leap year and leap year
        31,     31,                                     // January
        28,     29,                                     // February
        31,     31,                                     // March
        30,     30,                                     // April
        31,     31,                                     // May
        30,     30,                                     // June
        31,     31,                                     // July
        31,     31,                                     // August
        30,     30,                                     // September
        31,     31,                                     // October
        30,     30,                                     // November
        31,     31                                      // December
    };                                                  //
                                                        //
    if(++t->tm_sec > 59) {                              // Increment seconds, check for overflow
        t->tm_sec = 0;                                  // Reset seconds
        if(++t->tm_min > 59) {                          // Increment minutes, check for overflow
            t->tm_min = 0;                              // Reset minutes
            if(++t->tm_hour > 23) {                     // Increment hours, check for overflow
                t->tm_hour = 0;                         // Reset hours
                ++t->tm_yday;                           // Increment day of year
                if(++t->tm_wday > 6)                    // Increment day of week, check for overflow
                    t->tm_wday = 0;                     // Reset day of week
                                                        // Increment day of month, check for overflow
                if(++t->tm_mday > dim[t->tm_mon][is_leap_year(t->tm_year + 1900)]) {
                    t->tm_mday = 1;                     // Reset day of month
                    if(++t->tm_mon > 11) {              // Increment month, check for overflow
                        t->tm_mon = 0;                  // Reset month
                        t->tm_yday = 0;                 // Reset day of year
                        ++t->tm_year;                   // Increment year
                    }                                   // - year       
                }                                       // - month
            }                                           // - day
        }                                               // - hour
    }                                                   // - minute
}                                                       //
