日期时间与 time_t 相互转换

--------------------------------------------------------------------------------
标题: 日期时间与 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;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值