#include <stdlib.h>
#include <stdint.h>
#include "datetime.h"
static const unsigned int max_days_in_month[] = { 31, 28, 31, 30, 31, 30, 31,
31, 30, 31, 30, 31, };
static const unsigned int days_of_months_in_common_year[] = { 0, 31, 59, 90,
120, 151, 181, 212, 243, 273, 304, 334, 365, };
static const unsigned int days_of_months_in_leap_year[] = { 0, 31, 60, 91,
121, 152, 182, 213, 244, 274, 305, 335, 366, };
static int ____total_leap_years_from2000(unsigned int year) {
register unsigned int elasped_years;
register unsigned int elasped_leap_years;
if (year < 2000)
return -1;
elasped_years = year - 1 - 2000;
elasped_leap_years = elasped_years / 4;
elasped_leap_years -= elasped_years / 100;
elasped_leap_years += elasped_years / 400;
if (elasped_years)
elasped_leap_years += 1;
return elasped_leap_years;
}
static int __total_leap_years(unsigned int year) {
register unsigned int elasped_leap_years;
if (year < 1970) {
return -1;
}
if (year <= 1972) {
elasped_leap_years = 0;
} else if (year <= 2000) {
elasped_leap_years = (year - 1 - 1972) / 4 + 1;
} else {
elasped_leap_years = (2000 - 1 - 1972) / 4 + 1;
elasped_leap_years += ____total_leap_years_from2000(year);
}
return elasped_leap_years;
}
static int ____total_days_in_common_year(unsigned int month, unsigned int day) {
if ((month < 1) || (month > 12))
return -1;
if (day > max_days_in_month[month - 1])
return -1;
return (days_of_months_in_common_year[month - 1] + day - 1);
}
static __inline__ int __is_leap_year(unsigned int year) {
if ((year % 4) == 0) {
if (((year % 100) == 0) && ((year % 400) != 0))
return 0;
return 1;
}
return 0;
}
static int __total_days(unsigned int year, unsigned int month, unsigned int day) {
int leap_years;
int days_in_year;
leap_years = __total_leap_years(year);
if (leap_years == -1)
return -1;
days_in_year = ____total_days_in_common_year(month, day);
if (days_in_year == -1)
return -1;
if ((month > 2) && __is_leap_year(year))
days_in_year += 1;
return (leap_years * 366 + (year - 1970 - leap_years) * 365 + days_in_year);
}
static int __year_after_days(unsigned int days) {
register unsigned int year;
year = 1970 + days / 365;
while (1) {
if (__total_days(year, 1, 1) > (int)days)
year -= 1;
else
break;
}
return year;
}
static int __days_after_month_in_common_year(unsigned int days,
unsigned int left, unsigned int right) {
register unsigned int middle;
middle = (left + right) / 2;
if (days < days_of_months_in_common_year[middle])
return __days_after_month_in_common_year(days, left, middle);
else if (days >= days_of_months_in_common_year[middle + 1])
return __days_after_month_in_common_year(days, middle + 1, right);
return (middle + 1);
}
static int ___days_after_month_in_leap_year(unsigned int days,
unsigned int left, unsigned int right) {
register unsigned int middle;
middle = (left + right) / 2;
if (days < days_of_months_in_leap_year[middle])
return ___days_after_month_in_leap_year(days, left, middle);
else if (days >= days_of_months_in_leap_year[middle + 1])
return ___days_after_month_in_leap_year(days, middle + 1, right);
return (middle + 1);
}
static int days_after_month_in_common_year(unsigned int days) {
if (days >= 365)
return -1;
return __days_after_month_in_common_year(days, 0, 12);
}
static int __days_after_month_in_leap_year(unsigned int days) {
if (days >= 366)
return -1;
return ___days_after_month_in_leap_year(days, 0, 12);
}
int total_years(struct date *date) {
if (date == NULL)
return -1;
if (date->year < 1970)
return -1;
return (date->year - 1970);
}
int total_leap_years(struct date *date) {
if (date == NULL)
return -1;
return __total_leap_years(date->year);
}
int total_months(struct date *date) {
register int years;
if (date == NULL)
return -1;
if ((date->month < 1) || (date->month > 12))
return -1;
years = total_years(date);
if (years == -1)
return -1;
return ((years * 12) + date->month - 1);
}
int total_days(struct date *date) {
if (date == NULL)
return -1;
return __total_days(date->year, date->month, date->day);
}
int make_date(unsigned int days, struct date *date) {
if (date == NULL)
return -1;
date->weekday = (((days % 7) + 3) % 7) + 1;
date->year = __year_after_days(days);
days -= __total_days(date->year, 1, 1);
if (__is_leap_year(date->year)) {
date->month = __days_after_month_in_leap_year(days);
date->day = days - days_of_months_in_leap_year[date->month - 1] + 1;
} else {
date->month = days_after_month_in_common_year(days);
date->day = days - days_of_months_in_common_year[date->month - 1] + 1;
}
return 0;
}
int day_of_year(struct date *date) {
register int days;
if (date == NULL)
return -1;
if (date->year < 1970)
return -1;
if ((date->month < 1) || (date->month > 12))
return -1;
if (date->day < 1)
return -1;
if (__is_leap_year(date->year)) {
if ((date->month == 2) && (date->day > 29))
return -1;
else if (date->day > max_days_in_month[date->month - 1])
return -1;
else
days = days_of_months_in_leap_year[date->month - 1];
} else {
if (date->day > max_days_in_month[date->month - 1])
return -1;
else
days = days_of_months_in_common_year[date->month - 1];
}
return (days + date->day);
}
int day_of_week(struct date *date) {
register int days;
if (date == NULL)
return -1;
days = __total_days(date->year, date->month, date->day);
if (days == -1)
return -1;
date->weekday = (((days % 7) + 3) % 7) + 1;
return date->weekday;
}
int time_to_timestamp(struct time *time) {
register int timestamp;
if (time == NULL) {
return -1;
}
if (time->hour > 23) {
return -1;
}
if (time->minute > 59) {
return -1;
}
if (time->second > 59) {
return -1;
}
if (time->milling > 999) {
return -1;
}
timestamp = time->hour * 60 * 60 * 1000;
timestamp += time->minute * 60 * 1000;
timestamp += time->second * 1000;
timestamp += time->milling;
return timestamp;
}
int make_time(uint64_t timestamp, struct time *time) {
if (time == NULL)
return -1;
time->milling = timestamp % 1000;
timestamp /= 1000;
time->second = timestamp % 60;
timestamp /= 60;
time->minute = timestamp % 60;
timestamp /= 60;
time->hour = timestamp % 60;
return 0;
}
int datetime_to_timestamp(struct datetime *datetime, uint64_t *timestamp) {
register int days, timestamp_in_day;
if (datetime == NULL) {
return -1;
}
days = total_days(&datetime->date);
if (days == -1) {
return -1;
}
timestamp_in_day = time_to_timestamp(&datetime->time);
if (timestamp_in_day == -1) {
return -1;
}
if (timestamp != NULL) {
*timestamp = (((uint64_t)days) * 24 * 60 * 60 * 1000) + timestamp_in_day;
}
return 0;
}
- 1
- 2
前往页