网上看到有编写_mktime64的帖子,但是他们写的_mktime64输出的结果与Windows的输出结果不一致。经过本人对windows的_mktime64函数实现的跟踪研究,发现网上最接近正确答案的写法缺少对时区的计算。
一、_mktime64 日期时间转int64
/*
*相比网上其它帖子的源码进行完善,输出结果与windows自带的_mktime64输出结果一致
*_tm为当前真实日期,此处与windows的入参有所不同
*/
_int64 _mktime64(const tm& _tm)
{
tm _tmp = _tm;
if (0 >= (int) (_tmp.tm_mon -= 2)) { /* 1..12 -> 11,12,1..10 */
_tmp.tm_mon += 12; /* Puts Feb last since it has leap day */
_tmp.tm_year -= 1;
}
return ((((_tmp.tm_year/4 - _tmp.tm_year/100 + _tmp.tm_year/400 + 367*_tmp.tm_mon/12 + _tmp.tm_mday) +
_tmp.tm_year*365 - 719499
)*24 + _tmp.tm_hour /* now have hours */
)*60 + _tmp.tm_min /* now have minutes */
)*60 + _tmp.tm_sec /* finally seconds */
- 8*3600; /*时区*/
};
二、_localtime64_s int64转日期时间
void _localtime64_s(const long long& _iTime, tm& _tm)
{
#define CHCK_IS_LEAP_YEAR(y) (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
int startYear = 1970;
long long _iTimep = _iTime;
_iTimep += 8*3600;
_tm.tm_sec = _iTimep % 60;
_tm.tm_min = ((_iTimep - _tm.tm_sec) / 60) % 60;
_tm.tm_hour = (((_iTimep - _tm.tm_sec) / 60 - _tm.tm_min) / 60) % 24;
int _alldays = (((_iTimep - _tm.tm_sec) / 60 - _tm.tm_min) / 60 - _tm.tm_hour) / 24;
_tm.tm_wday = _alldays % 6 + 1;
_tm.tm_isdst = 0;
_tm.tm_year = _alldays / 365 + startYear; /*简易算法,直接用365整除,目前满足计算结果*/
int _ndays = 0; /*计算从startYear到_tm.tm_year-1年总计天数*/
for(int i = startYear; i < _tm.tm_year; i++)
{
if(CHCK_IS_LEAP_YEAR(i)){
_ndays += 366;
}else{
_ndays += 365;
}
}
int k,leap;
int yearday = _alldays - _ndays;
_tm.tm_yday = yearday;
int _months_days[2][13] =
{
{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}
};
if(CHCK_IS_LEAP_YEAR(_tm.tm_year)){
leap = 1;
}else{
leap = 0;
}
for(k = 1; yearday > _months_days[leap][k]; k++)
yearday -= _months_days[leap][k];
_tm.tm_mon = k;
_tm.tm_mday = yearday + 1;
};