您的位置:首页 > 其它

日期时间与 time_t 相互转换

2012-05-25 16:54 716 查看
--------------------------------------------------------------------------------

标题: 日期时间与 time_t 相互转换

作者: 叶飞虎

日期: 2012.05.25

--------------------------------------------------------------------------------

time_t 类型表示从 UTC(Universal Time Coordinated) 时间1970年1月1日00:00:00 (称为

UNIX 系统的Epoch时间)到当前时刻的秒数。

假设 time_t 使用 int64_t 类型存储, 与日期时间相互转换的代码如下:

// 月天数表类型
typedef unsigned short Word;
typedef Word TMonthDays[12];

// 月天数
const TMonthDays _Month_Days[2]
= {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};

// 月偏移天数
const TMonthDays _Month_Offsets[2]
= {{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}};

// 从 0001.01.01 到 1970.01.01 之间的天数
const long _Delta_1970_1_1 = 719163;

// 判断是否闰年
inline bool _IsLeapYear(Word AYear)
{
return ((AYear & 3) == 0) && (((AYear % 100) != 0) || ((AYear % 400) == 0));
}

// 判断是否闰年
inline bool _IsLeapYear(long AYear)
{
return ((AYear & 3) == 0) && (((AYear % 100) != 0) || ((AYear % 400) == 0));
}

// 转换成相对 1970.01.01 的日期值
bool _EncodeDate1970(Word AYear, Word AMonth, Word ADay, long& ADate)
{
// 初始化
bool result = false;
bool boolLeap;

// 判断是否闰年
boolLeap = _IsLeapYear(AYear);
AMonth--;
AYear--;

// 检查日期是否合法
if ((AYear < 9999) && (AMonth < 12) && (ADay != 0)
&& (ADay <= _Month_Days[boolLeap][AMonth]))
{
ADate    = (AYear * 365) + (AYear / 4) - (AYear / 100) + (AYear / 400);
ADate   += _Month_Offsets[boolLeap][AMonth] + ADay - _Delta_1970_1_1;
result   = true;
}

// 返回结果
return result;
}

// 转换成相对 1970.01.01 的日期值(注: AYear, AMonth, ADay 合法)
long _EncodeDate1970(Word AYear, Word AMonth, Word ADay)
{
// 初始化
long result;
bool boolLeap;

// 判断是否闰年
boolLeap = _IsLeapYear(AYear);

// 计算
AYear--;
result   = (AYear * 365) + (AYear / 4) - (AYear / 100) + (AYear / 400);
result  += _Month_Offsets[boolLeap][AMonth - 1] + ADay - _Delta_1970_1_1;

// 返回结果
return result;
}

// 转换成 time_t 的日期值(注: 不检查参数是否合法)
int64_t _EncodeTime_t0(Word AYear, Word AMonth,  Word ADay,
Word AHour, Word AMinute, Word ASecond)
{
return (int64_t)_EncodeDate1970(AYear, AMonth, ADay) * 86400
+ (AHour * 3600) + (AMinute * 60) + ASecond;
}

// 转换成 time_t 的日期值
int64_t _EncodeTime_t(Word AYear, Word AMonth,  Word ADay,
Word AHour, Word AMinute, Word ASecond)
{
// 初始化
int64_t  result = 0;
long     intDate;

// 转换日期
if ((AHour < 24) && (AMinute < 60) && (ASecond < 60)
&& _EncodeDate1970(AYear, AMonth, ADay, intDate))
result = (int64_t)intDate * 86400 + (AHour * 3600) + (AMinute * 60) + ASecond;

// 返回结果
return result;
}

// 分解相对 1970.01.01 的日期值
void _DecodeDate1970(long ADate, Word& AYear, Word& AMonth, Word& ADay)
{
// 年的天基数
static const long Y1    = 365;
static const long Y4    = Y1 * 4 + 1;
static const long Y100  = Y4 * 25 - 1;
static const long Y400  = Y100 * 4 + 1;

// 初始化
long  intValue, intYear, intDays;
Word* pOffsets;

// 检查日期是否合法
intDays  = ADate + _Delta_1970_1_1 - 1;
if (intDays < 0)
{
AYear    = 0;
AMonth   = 0;
ADay     = 0;
return;
}

// 400 年分解
intValue = intDays / Y400;
intDays %= Y400;
intYear  = intValue * 400 + 1;

// 100 年分解
intValue = intDays / Y100;
intDays %= Y100;
intYear += intValue * 100;
if (intValue == 4)
{
intYear -= 100;
intDays += Y100;
}

// 4 年分解
intValue = intDays / Y4;
intDays %= Y4;
intYear += intValue * 4;

// 1 年分解
intValue = intDays / Y1;
intDays %= Y1;
intYear += intValue;
if (intValue == 4)
{
intYear--;
intDays += Y1;
}

// 计算月份索引
pOffsets = (Word*)_Month_Offsets[_IsLeapYear(intYear)];
intValue = intDays / 29;
if (intValue == 12)
intValue = 11;
else if (intDays < pOffsets[intValue])
intValue--;

// 取年月日
AYear    = (Word)intYear;
AMonth   = (Word)intValue + 1;
ADay     = (Word)intDays - pOffsets[intValue] + 1;
}

// 分解 time_t 的日期值
void _DecodeTime_t(int64_t ATime, Word& AYear, Word& AMonth,  Word& ADay,
Word& AHour, Word& AMinute, Word& ASecond)
{
// 初始化
long intDate;
long intTime;

// 判断符号
intDate  = (long)(ATime / 86400);
intTime  = (long)(ATime % 86400);
if (ATime < 0)
{
intDate--;
intTime += 86400;
}

// 分解日期
_DecodeDate1970(intDate, AYear, AMonth, ADay);

// 分解时间
AHour    = intTime / 3600;
intTime %= 3600;
AMinute  = intTime / 60;
ASecond  = intTime % 60;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: