static timelib_sll do_years(timelib_sll year) { timelib_sll i; timelib_sll res = 0; timelib_sll eras; eras = (year - 1970) / 40000; if (eras != 0) { year = year - (eras * 40000); res += (SECS_PER_ERA * eras * 100); } if (year >= 1970) { for (i = year - 1; i >= 1970; i--) { if (timelib_is_leap(i)) { res += (DAYS_PER_LYEAR * SECS_PER_DAY); } else { res += (DAYS_PER_YEAR * SECS_PER_DAY); } } } else { for (i = 1969; i >= year; i--) { if (timelib_is_leap(i)) { res -= (DAYS_PER_LYEAR * SECS_PER_DAY); } else { res -= (DAYS_PER_YEAR * SECS_PER_DAY); } } } return res; }
static int do_range_limit_days_relative(timelib_sll *base_y, timelib_sll *base_m, timelib_sll *y, timelib_sll *m, timelib_sll *d) { timelib_sll leapyear; timelib_sll days_this_month; timelib_sll next_month, next_year; timelib_sll days_next_month; do_range_limit(1, 13, 12, base_m, base_y); leapyear = timelib_is_leap(*base_y); days_this_month = leapyear ? days_in_month_leap[*base_m] : days_in_month[*base_m]; next_month = (*base_m) + 1; if (next_month > 12) { next_month -= 12; next_year = (*base_y) + 1; } else { next_year = (*base_y); } leapyear = timelib_is_leap(next_year); days_next_month = leapyear ? days_in_month_leap[next_month] : days_in_month[next_month]; if (*d < 0) { *d += days_this_month; (*m)--; return 1; } if (*d > days_next_month) { *d -= days_next_month; (*m)++; return 1; } return 0; }
timelib_t timelib_make(struct timelib_tm * timeinfo) { int i; timelib_t tstamp; // Compute the number of seconds since the year 1970 to the begining of // the given year on the structure, add to the output value tstamp = timeinfo->tm_year * (TIMELIB_SECS_PER_DAY * 365); // Add the seconds corresponding to leap years (add extra days) for (i = 0; i < timeinfo->tm_year; i++) { if (timelib_is_leap(i + 1970)) tstamp += (timelib_t) TIMELIB_SECS_PER_DAY; } // Add seconds for the months elapsed for (i = 1; i < timeinfo->tm_mon; i++) { if (i == 2 && timelib_is_leap(timeinfo->tm_year + 1970)) tstamp += (timelib_t) TIMELIB_SECS_PER_DAY * 29; else tstamp += (timelib_t) TIMELIB_SECS_PER_DAY * month_length[i - 1]; } // Add seconds for past days tstamp += (timelib_t) (timeinfo->tm_mday - 1) * (timelib_t) TIMELIB_SECS_PER_DAY; // Add seconds on this day tstamp += (timelib_t) timeinfo->tm_hour * (timelib_t) TIMELIB_SECS_PER_HOUR; tstamp += (timelib_t) timeinfo->tm_min * (timelib_t) TIMELIB_SECS_PER_MINUTE; tstamp += (timelib_t) timeinfo->tm_sec; return tstamp; }
void timelib_break(timelib_t timeinput, struct timelib_tm * timeinfo) { uint8_t year; uint8_t month, monthLength; uint32_t time; unsigned long days; time = (uint32_t) timeinput; timeinfo->tm_sec = time % 60; time /= 60; // now it is minutes timeinfo->tm_min = time % 60; time /= 60; // now it is hours timeinfo->tm_hour = time % 24; time /= 24; // now it is days timeinfo->tm_wday = ((time + 4) % 7) + 1; // Sunday is day 1 year = 0; days = 0; while ((unsigned) (days += (timelib_is_leap(1970 + year) ? 366 : 365)) <= time) year++; timeinfo->tm_year = year; // year is offset from 1970 days -= timelib_is_leap(1970 + year) ? 366 : 365; time -= days; // now it is days in this year, starting at 0 days = 0; month = 0; monthLength = 0; for (month = 0; month < 12; month++) { // Check if (month == 1) { if (timelib_is_leap(1970 + year)) { monthLength = 29; } else { monthLength = 28; } } else { monthLength = month_length[month]; } if (time >= monthLength) { time -= monthLength; } else { break; } } timeinfo->tm_mon = month + 1; // jan is month 1 timeinfo->tm_mday = time + 1; // day of month }
void timelib_isoweek_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iw, timelib_sll *iy) { int y_leap, prev_y_leap, doy, jan1weekday, weekday; y_leap = timelib_is_leap(y); prev_y_leap = timelib_is_leap(y-1); doy = timelib_day_of_year(y, m, d) + 1; if (y_leap && m > 2) { doy++; } jan1weekday = timelib_day_of_week(y, 1, 1); weekday = timelib_day_of_week(y, m, d); if (weekday == 0) weekday = 7; if (jan1weekday == 0) jan1weekday = 7; /* Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53 */ if (doy <= (8 - jan1weekday) && jan1weekday > 4) { *iy = y - 1; if (jan1weekday == 5 || (jan1weekday == 6 && prev_y_leap)) { *iw = 53; } else { *iw = 52; } } else { *iy = y; } /* 8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1 */ if (*iy == y) { int i; i = y_leap ? 366 : 365; if ((i - (doy - y_leap)) < (4 - weekday)) { *iy = y + 1; *iw = 1; return; } } /* 9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53 */ if (*iy == y) { int j; j = doy + (7 - weekday) + (jan1weekday - 1); *iw = j / 7; if (jan1weekday > 4) { *iw -= 1; } } }
static timelib_sll do_months(timelib_ull month, timelib_ull year) { if (timelib_is_leap(year)) { return ((month_tab_leap[month - 1] + 1) * SECS_PER_DAY); } else { return ((month_tab[month - 1]) * SECS_PER_DAY); } }
static void do_range_limit_days_relative(timelib_sll *base_y, timelib_sll *base_m, timelib_sll *y, timelib_sll *m, timelib_sll *d, timelib_sll invert) { timelib_sll leapyear; timelib_sll month, year; timelib_sll days; do_range_limit(1, 13, 12, base_m, base_y); year = *base_y; month = *base_m; /* printf( "S: Y%d M%d %d %d %d %d\n", year, month, *y, *m, *d, days); */ if (!invert) { while (*d < 0) { dec_month(&year, &month); leapyear = timelib_is_leap(year); days = leapyear ? days_in_month_leap[month] : days_in_month[month]; /* printf( "I Y%d M%d %d %d %d %d\n", year, month, *y, *m, *d, days); */ *d += days; (*m)--; } } else { while (*d < 0) { leapyear = timelib_is_leap(year); days = leapyear ? days_in_month_leap[month] : days_in_month[month]; /* printf( "I Y%d M%d %d %d %d %d\n", year, month, *y, *m, *d, days); */ *d += days; (*m)--; inc_month(&year, &month); } } /* printf( "E: Y%d M%d %d %d %d %d\n", year, month, *y, *m, *d, days); */ }
static int do_range_limit_days(timelib_sll *y, timelib_sll *m, timelib_sll *d) { timelib_sll leapyear; timelib_sll days_this_month; timelib_sll last_month, last_year; timelib_sll days_last_month; /* can jump an entire leap year period quickly */ if (*d >= DAYS_PER_LYEAR_PERIOD || *d <= -DAYS_PER_LYEAR_PERIOD) { *y += YEARS_PER_LYEAR_PERIOD * (*d / DAYS_PER_LYEAR_PERIOD); *d -= DAYS_PER_LYEAR_PERIOD * (*d / DAYS_PER_LYEAR_PERIOD); } do_range_limit(1, 13, 12, m, y); leapyear = timelib_is_leap(*y); days_this_month = leapyear ? days_in_month_leap[*m] : days_in_month[*m]; last_month = (*m) - 1; if (last_month < 1) { last_month += 12; last_year = (*y) - 1; } else { last_year = (*y); } leapyear = timelib_is_leap(last_year); days_last_month = leapyear ? days_in_month_leap[last_month] : days_in_month[last_month]; if (*d <= 0) { *d += days_last_month; (*m)--; return 1; } if (*d > days_this_month) { *d -= days_this_month; (*m)++; return 1; } return 0; }
static timelib_sll timelib_day_of_week_ex(timelib_sll y, timelib_sll m, timelib_sll d, int iso) { timelib_sll c1, y1, m1, dow; /* Only valid for Gregorian calendar, commented out as we don't handle * Julian calendar. We just return the 'wrong' day of week to be * consistent. */ c1 = century_value(y / 100); y1 = (y % 100); m1 = timelib_is_leap(y) ? m_table_leap[m] : m_table_common[m]; dow = (c1 + y1 + m1 + (y1 / 4) + d) % 7; if (iso) { if (dow == 0) { dow = 7; } } return dow; }
timelib_sll timelib_days_in_month(timelib_sll y, timelib_sll m) { return timelib_is_leap(y) ? ml_table_leap[m] : ml_table_common[m]; }
timelib_sll timelib_day_of_year(timelib_sll y, timelib_sll m, timelib_sll d) { return (timelib_is_leap(y) ? d_table_leap[m] : d_table_common[m]) + d - 1; }