DateTime.h
#ifndef _DATE_TIME_H_
#define _DATE_TIME_H_
#ifdef __cplusplus
extern "C" {
#endif
#define YES 1
#define NO 0
typedef struct _DateTime{
unsigned short wSecond; /* The current second - [0,59] */
unsigned short wMinute; /* The current minute - [0,59] */
unsigned short wHour; /* The current hour - [0,23] */
unsigned short wDay; /* The current day of the month - [1,31] */
unsigned short wMonth; /* The current month; January is 1 - [1,12] */
unsigned short wYear; /* The current year */
}DateTime;
int IsYearLeap(int year); /* 判断year是不是闰年 */
int IsDateValid(DateTime *date); /* 判断日期是否正确, 不正确返回-1 */
int LoadDateStruct(DateTime *date, int yy, int mm, int dd); /* 填充DateTime结构体, 并判断日期参数是否正确, 不正确返回-1 */
long DateToDayNumber(DateTime *date); /* 把日期转换成天数 */
int DayOfWeek(DateTime *date); /* 给出当前日期是星期几 */
int DayOfYear(DateTime *date); /* 给出当前日期是这一年中的第几天 */
long DateDiff(DateTime *d1, DateTime *d2); /* 计算两个日期之间的天数差 */
int DayNumberToDate(long int day_num, DateTime *date); /* 把天数转换成日期 */
double TimeDiff(DateTime *t1, DateTime *t2); /* 计算两个时间之间差的秒数 */
#ifdef __cplusplus
};
#endif
#endif //~_DATE_TIME_H_
DateTime.c
#include "DateTime.h"
/* 定义PROLEPTIC代表忽略重大转变日期 */
#define PROLEPTIC
static const int Days_in_month[13] = {
0,
31, 28, 31, /* Jan, Feb, Mar */
30, 31, 30, /* Apr, May, Jun */
31, 31, 30, /* Jul, Aug, Sep */
31, 30, 31 /* Oct, Nov, Dec */
};
static const int Days_in_month_leap[13] = {
0,
31, 29, 31, /* Jan, Feb, Mar */
30, 31, 30, /* Apr, May, Jun */
31, 31, 30, /* Jul, Aug, Sep */
31, 30, 31 /* Oct, Nov, Dec */
};
static const char *Day_name[7] = {
"Sunday", "Monday",
"Tuesday", "Wednesday",
"Thursday", "Friday",
"Saturday"
};
static const char *Day_name_abbrev[7] = {
"Sun", "Mon",
"Tue", "Wed",
"Thu", "Fri",
"Sat"
};
static const char *Month_name[13] = {
"",
"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December"
};
static const char* Month_name_abbrev[13] = {
"",
"Jan", "Feb", "Mar",
"Apr", "May", "Jun",
"Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"
};
int IsYearLeap(int year)
{
if(year % 4 != 0)
return NO;
#ifndef PROLEPTIC
if(year < 1582) /* all years divisible by 4 were leap prior to 1582 */
return YES;
#endif
if(year % 100 != 0)
return YES;
if(year % 400 != 0)
return NO;
return YES;
}
int IsDateValid(DateTime *date)
{
if(date->wMonth < 1 || date->wMonth > 12)
return NO;
if(date->wYear < 1)
return NO;
if(IsYearLeap(date->wYear) == NO)
{
if(date->wDay < 1 || date->wDay > Days_in_month[date->wMonth])
return NO;
}
else
{
if(date->wDay < 1 || date->wDay > Days_in_month_leap[date->wMonth])
return NO;
}
return YES;
}
int LoadDateStruct(DateTime *date, int yy, int mm, int dd)
{
date->wYear = yy;
date->wMonth = mm;
date->wDay = dd;
if(IsDateValid(date) == NO)
return -1;
return 0;
}
long DateToDayNumber(DateTime *date)
{
long day_num;
int mm, yy;
if(IsDateValid(date) == NO)
return -1;
yy = date->wYear;
mm = date->wMonth;
/* get all the regular days in preceding years */
day_num = (yy - 1) * 365L;
/* now get the leap years */
day_num += (yy - 1) / 4L;
/* now back out the century years that are not leap:
this would be all century years that are not
evenly divisible by 400: 1700, 1800, 1900, 2100 ... */
day_num -= (yy - 1) / 100L;
day_num += (yy - 1) / 400L;
#ifndef PROLEPTIC
/* before 1582 all century years were leap, so adjust for this.
If year is > 1582, then just all 12 days for years 100, 200, 300,
500, 600, 700, 900, 1000, 1100, 1300, 1400 and 1500. Otherwise,
calculate it. */
if((yy - 1) > 1582)
day_num += 12L;
else
{
day_num += (yy - 1) / 100L;
day_num -= (yy - 1) / 400L;
}
#endif
/* now, add the days elapsed in the year so far */
if(IsYearLeap(date->wYear) == NO)
{
while(--mm)
day_num += Days_in_month[mm];
}
else
{
while(--mm)
day_num += Days_in_month_leap[mm];
}
/* add days in current month for the year being evaluated */
day_num += date->wDay;
#ifndef PROLEPTIC
/* now adjust for the 10 days cut out of the calender when
the chang was made to the Gregorian calendar. this change
reflects the jump from October 4 to October 15, 1582, a
deletion of 10 days. */
if(day_num > 577737L)
day_num -= 10L;
#endif
return day_num;
}
int DayOfWeek(DateTime *date)
{
long day_num = DateToDayNumber(date);
if(day_num < 0)
return -1;
return (int)(day_num % 7);
}
int DayOfYear(DateTime *date)
{
DateTime jan1;
if(LoadDateStruct(&jan1, date->wYear, 1,1) == -1)
return -1;
return (int)(DateDiff(date, &jan1) + 1);
}
long DateDiff(DateTime *d1, DateTime *d2)
{
return DateToDayNumber(d1) - DateToDayNumber(d2);
}
int DayNumberToDate(long int day_num, DateTime *date)
{
int dd, mm, yy, i;
long days_left;
#ifndef PROLEPTIC
if(day_num > 577737L)
day_num += 10L;
#endif
yy = (int)(day_num / 365L);
days_left = day_num % 365L;
#ifndef PROLEPTIC
/* prior to 1700, all years evenly divisible by 4 are leap */
if(yy < 1700)
days_left -= (yy / 4);
else
{
days_left -= (yy / 4);
days_left += (yy / 100);
days_left -= (yy / 400);
days_left -= 12;
}
#else
days_left -= (yy / 4);
days_left += (yy / 100);
days_left -= (yy / 400);
#endif
/* make sure days left is > 0 */
while(days_left <= 0)
{
if(IsYearLeap(yy) == YES)
{
yy -= 1;
days_left += 366;
}
else
{
yy -= 1;
days_left += 365;
}
}
/* yy holds the number of elapsed years.
so, add 1 for the current year. */
yy += 1;
/* now deduct the days in each month, starting
from January to find month and day of month.
adjust for leap year, of course. */
dd = (int) days_left;
mm = 0;
if(IsYearLeap(yy) == YES)
{
for(i = 1; i <= 12; i++)
{
mm = i;
if(dd <= Days_in_month_leap[i])
break;
else
dd -= Days_in_month_leap[i];
}
}
else
{
for(i = 1; i <= 12; i++)
{
mm = i;
if(dd <= Days_in_month[i])
break;
else
dd -= Days_in_month[i];
}
}
return LoadDateStruct(date, yy, mm, dd);
}
double TimeDiff(DateTime *t1, DateTime *t2)
{
long day_num;
double d1, d2;
day_num = DateToDayNumber(t1);
d1 = day_num * 86400.0 + t1->wHour * 3600.0 + t1->wMinute * 60.0 + t1->wSecond;
day_num = DateToDayNumber(t2);
d2 = day_num * 86400.0 + t2->wHour * 3600.0 + t2->wMinute * 60.0 + t2->wSecond;
return d1 - d2;
}