最近发现以前开发的odbc驱动(与java对接)在x64下转换出来的日期是错误的,以前则是反复测试过了的,经过跟踪,原来用的数据类型u_long长度怎么由8位变成了4位,转换出来的时间数据肯定不对。     先来看一段程序:void testDate2(){ long long ll = -439937379000; //1956-01-23 11:10:21 long long tms[] = { 1110470400000,154108800000, 999964800000, -33638400000,1138806063000, 926438401000, 926524799000,1302278400000 ,1394863683000, 903309312,3532387328, -14783068800000 }; TIMESTAMP_STRUCT tmm; for (int i = 0; i ll = tms[i] / 1000; //tmm = ImDate::GetTimeStampFromSeconds(ll); COleDateTime da = COleDateTime(ll); string strValue = da.Format("%Y-%m-%d"); tmm = *ImDate::getTimeStamp(ll); cout }}输出结果:2005-3-11 0:0:0 2005-03-111974-11-20 0:0:0        1974-11-202001-9-9 0:0:0  2001-09-091968-12-8 0:0:0 Invalid DateTime2006-2-1 23:1:3 2006-02-011999-5-12 0:0:1 1999-05-121999-5-12 23:59:59      1999-05-122011-4-9 0:0:0  2011-04-092014-3-15 14:8:3        2014-03-151970-1-11 18:55:9       1970-01-111970-2-11 5:13:7        1970-02-111501-7-19 0:0:0 Invalid DateTimetms中的变量值小于0是1970-01-01以前的日期,没有想到COleDateTime 也不支持。若有要出生于1970-01-01前的,那难道不支持了吗?自己动手实现如下./******************************************** * ImDate.h ************************************/#ifndef IMDATE_H#define IMDATE_H#include#define SECONDS_PER_HOUR (60*60)#define SECONDS_PER_DAY (SECONDS_PER_HOUR * 24)#define SECONDS_PER_ZONE (SECONDS_PER_HOUR * ImDate::Instance()->GetZone())class ImDate{public: ImDate(); int GetZone(){ return m_zone; } static ImDate* Instance(); static void Destroy(); // strTime格式::"yyyy-MM-dd hh:mm:ss", "yyyy-MM-dd","hh:mm:ss" // 返回值=-1无效 static time_t GetTimeByDateTimeStr( const char* strTime ); // 通过秒数返回struct tm static tm GetTimeStampBySeconds(time_t seconds); static DATE_STRUCT *getDate(long long seconds); static TIME_STRUCT *getTime(long long seconds); static TIMESTAMP_STRUCT *getTimeStamp(long long seconds); // 获取当前时间格式::"yyyy-MM-dd hh:mm:ss" static char *getCurrentDateTime();private: //判断是否闰年 static bool IsLeapYear(long year); //根据一年中的第几天(0起始),返回月份(1起始),并且置天数为其在本月的索引(0起始) static unsigned long GetMonthByDay(long &day,bool leap); //距离1970年1月1日的天数(0起始),返回年,并且置天数为其在本年的索引(0起始) static unsigned long GetYearByDay(long &day); // 返回本系统时区,中国为8区 int GetTimeZoneNow(); // 通过年月日返回其天数(1970.01.01 00:00:00参考点) static unsigned long GetDayByDate(tm &tmm); // 通过1970.1.1以前的天数及tm,计算timeStamp static time_t GetSecondByDate(long days, tm &tmm); // 通过1970.1.1以前的天数,计算date static void GetDateByDays(long days,tm &tmm); // 通过秒数,计算time static void GetTimeBySeconds(long seconds, tm &tmm); // 通过time产生秒数 static long GetSecondsByTime( tm &tmm); // 通过1970.1.1以来的时间戳秒数,计算DateStamp static tm GetDateTimeStamp(time_t seconds); // 是否合法的date static int IsValidDate(int y, int m, int d); // 是否合法的time static int IsValidTime(int h, int m, int s); // strTime格式::"yyyy-MM-dd" // 返回值=-1无效 static time_t GetTimeByDateStr( const char* strTime ); // strTime格式::"hh:mm:ss" // 返回值=-1无效 static time_t GetTimeByTimeStr( const char* strTime ); // 返回时间戳大于24小时的timeStamp static tm GetDateStampFromSeconds(time_t seconds); // 返回时间戳不大于24小时的timeStamp static tm GetTimeStampFromSeconds(time_t seconds);private: int m_zone; //本系统时区 static ImDate *_instance;};#endif/******************************************** * ImDate.cpp ************************************/#include "stdafx.h"#include#if defined(WITHOUT_WINTERFACE)#include#else#include#endif#include "ImDate.h"//#include "utils.h"using namespace std;ImDate *ImDate::_instance=NULL;ImDate::ImDate(){ m_zone = GetTimeZoneNow();}int ImDate::GetTimeZoneNow() {          TIME_ZONE_INFORMATION   tzi;  //GetSystemTime(&tzi.StandardDate);  GetTimeZoneInformation(&tzi);   /*CString   strStandName   =   tzi.StandardName;   CString   strDaylightName   =   tzi.DaylightName; */  int zone = tzi.Bias/ -60; //时区,如果是中国标准时间则得到8  return zone; }ImDate *ImDate::Instance(){ if (_instance==NULL){ _instance = new ImDate(); } return _instance;}void ImDate::Destroy(){ if (_instance!=NULL){ delete _instance; _instance = NULL; }}bool ImDate::IsLeapYear(long year){ return (year%4==0 && year%100!=0)||(year%400==0);}//根据一年中的第几天(0起始),返回月份(1起始),并且置天数为其在本月的索引(0起始)unsigned long ImDate::GetMonthByDay(long &day,bool leap){ //assert( day static unsigned long monthtable[] = { 31,29,31,30,31,30,31,31,30,31,30,31 } ; monthtable[1] = leap ? 29:28; long month = 0; long count = 0; long n = day; do { n = day - count; count += monthtable[month++];            }while( day >= count ); day = n; return month;   }//距离1900年1月1日的天数(0起始),返回年,并且置天数为其在本年的索引(0起始)//unsigned long ImDate::GetYearByDay(long &day)//{// long Y = day / 365;// long D = day % 365;// long  YY = Y-1;// D -= YY/4;// D += YY/100;// D -= (YY+300)/400;// while( D// {               // Y--; // D += IsLeapYear2(Y+1900) ? 366 : 365;                    // }// day = D;// return Y + 1900;        //}unsigned long ImDate::GetYearByDay(long &day){ //long days = abs(day); //long Y = (days+364) / 365; //long YY = 0; //for(int i=1970-Y; i // if (ImDate::IsLeapYear(i)){ // YY++; // } //} //bool leap = ImDate::IsLeapYear(1970-Y); //long D = days % 365; ////long md = (leap?366:365) - abs(D - YY); //long md = 365 - (D - YY); //if (md >= 365){ // if (D!=0) Y-=1; // md = md-365; //} //return 1970 - Y; long Y = 0, D=0; for(int n=day; n Y++; D+=365; if (IsLeapYear(-Y+1970)){ D++; n++; } } day = abs(day+D); return (-Y+1970);}//小于1970年时,通过年月日计算天数.unsigned long ImDate::GetDayByDate(tm &tmm){ long Y = 1970 - tmm.tm_year; long YY = 0; for(int i=tmm.tm_year; i if (ImDate::IsLeapYear(i)){ YY++; } } static unsigned long monthtable[] = { 31,29,31,30,31,30,31,31,30,31,30,31 } ; bool leap = ImDate::IsLeapYear(tmm.tm_year); //long day = (Y - 1) * 365 + YY; //day += leap ? 366:365; long day = Y * 365 + YY; monthtable[1] = leap ? 29:28; int m = tmm.tm_mon; int yd =  monthtable[m-1] - tmm.tm_mday; while( m > 0) {    day -= monthtable[m-1];   m--; } day += yd; return day+1;        }time_t ImDate::GetSecondByDate(long day, tm &tmm){ time_t sc = (time_t)day*SECONDS_PER_DAY + SECONDS_PER_ZONE; time_t seconds = tmm.tm_hour * SECONDS_PER_HOUR; seconds += tmm.tm_min * 60; seconds += tmm.tm_sec; //printf("sec=%d\n", seconds); return 0-(sc-seconds)*1000;}int ImDate::IsValidDate(int y, int m, int d){ int month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) month[1] = 29;  return  m > 0 && m 0 && d}int ImDate::IsValidTime(int h, int m, int s){ int ret = ( (h >= 0 && h (m >= 0 && m (s >= 0 && s return  ret; }// strTime::"yyyy-MM-dd hh:mm:ss"// 大于1970年用api;time_t ImDate::GetTimeByDateTimeStr( const char* strTime ){ time_t nRet = -1; do  { tm st; bool bTime = false; if (strlen(strTime) nRet = sscanf( strTime, "%02d:%02d:%02d", &st.tm_hour, &st.tm_min, &st.tm_sec ); st.tm_year=st.tm_mon=st.tm_mday = 0; bTime = true; }else if (strlen(strTime) nRet = sscanf( strTime, "%4d-%02d-%02d", &st.tm_year, &st.tm_mon, &st.tm_mday ); st.tm_hour = st.tm_min = st.tm_sec = 0; }else{ //timestamp nRet = sscanf( strTime, "%4d-%02d-%02d %02d:%02d:%02d",  &st.tm_year, &st.tm_mon, &st.tm_mday, &st.tm_hour, &st.tm_min, &st.tm_sec ); } if (nRet==-1) break; if (IsValidDate(st.tm_year, st.tm_mon, st.tm_mday)){ if (!IsValidTime(st.tm_hour, st.tm_min, st.tm_sec)){ //LOGSTR("%s IsValidTime"); break; } }else{ if(st.tm_year==0 && st.tm_mon==0 && st.tm_mday==0 && !IsValidTime(st.tm_hour, st.tm_min, st.tm_sec)){ //LOGSTR("IsValidTime"); break; } bTime = true; } if ( bTime ){ nRet = GetSecondsByTime(st)*1000; //printf("sec=%d\n", nRet); }else if (st.tm_year>=1970){ st.tm_year -= 1900; st.tm_mon -= 1; st.tm_isdst -= 1; time_t t = mktime( &st ); return mktime( &st ) * 1000; }else{ long days = GetDayByDate(st); time_t sc = GetSecondByDate(days, st); //此处st存储hour,minute, second //printf("%s, days=%d, ss=%I64d\n", strTime, days, sc); return sc; } } while (0); return nRet;}time_t ImDate::GetTimeByDateStr( const char* strTime ){ char s[128] = {0}; sprintf(s, "%s 00:00:00", strTime); return GetTimeByDateTimeStr(s);}time_t ImDate::GetTimeByTimeStr( const char* strTime ){ char s[128] = {0}; sprintf(s, "00-00-00 %s", strTime); return GetTimeByDateTimeStr(s);}//距离1970年1月1日的天数(0起始),计算这一天的日期(年,月,日)(1起始)。void ImDate::GetDateByDays(long days,tm &tmm){ tmm.tm_year = GetYearByDay(days); tmm.tm_mon = GetMonthByDay(days, IsLeapYear(tmm.tm_year)); tmm.tm_mday = days + 1;}tm ImDate::GetTimeStampBySeconds(time_t seconds){ tm tmm; if (abs(seconds + SECONDS_PER_ZONE) tmm = GetTimeStampFromSeconds(seconds); //for time }else{ tmm = GetDateStampFromSeconds(seconds); } return tmm;}tm ImDate::GetDateStampFromSeconds(time_t seconds){ time_t ll2 = 0; long days = 0; long sc = 0; tm tmm; time_t ll = seconds; if (ll ll2 = ll + SECONDS_PER_ZONE; days = (ll2-SECONDS_PER_DAY+1) /(SECONDS_PER_DAY); sc =  ll - (days * SECONDS_PER_DAY - SECONDS_PER_ZONE) ; //printf("tm=%I64d seconds = %d, days=%d ", ll, sc, days); GetTimeBySeconds(sc,tmm); GetDateByDays(days,tmm); }else{ tmm = GetDateTimeStamp(ll); } return tmm;}tm ImDate::GetTimeStampFromSeconds(time_t seconds){ struct tm tmm; memset(&tmm, 0x00, sizeof(tm)); GetTimeBySeconds(seconds+ SECONDS_PER_ZONE, tmm); return tmm;}// 通过秒数,计算timevoid ImDate::GetTimeBySeconds(long seconds, tm &tmm){ long ss = seconds; tmm.tm_hour = ss/SECONDS_PER_HOUR; tmm.tm_min = (ss-tmm.tm_hour*SECONDS_PER_HOUR)/60; tmm.tm_sec = ss%60;}// 通过time产生秒数long ImDate::GetSecondsByTime( tm &tmm){ long nRet = tmm.tm_hour * SECONDS_PER_HOUR; nRet += tmm.tm_min * 60; nRet += tmm.tm_sec; return nRet - SECONDS_PER_ZONE;}// 通过1970.1.1以来的时间戳秒数,计算DateStamptm ImDate::GetDateTimeStamp(time_t seconds){ //long long ll = 888199810000; //year,month, date,hour,minute,second //long long rawtime =ll/1000;  struct tm *ptm2; ptm2 = localtime(&seconds); ptm2->tm_year+=1900; ptm2->tm_mon += 1; //cout tm_year tm_montm_mday // tm_hour tm_min tm_sec return *ptm2;}DATE_STRUCT *ImDate::getDate(long long seconds){ DATE_STRUCT ds; struct tm tmm = GetTimeStampBySeconds(seconds); ds.day = tmm.tm_mday; ds.month = tmm.tm_mon; ds.year = tmm.tm_year; return &ds;}TIME_STRUCT *ImDate::getTime(long long seconds){ TIME_STRUCT ts; memset(&ts, 0, sizeof(TIME_STRUCT)); long ss = seconds + SECONDS_PER_ZONE; ts.hour = ss/3600; ts.minute = (ss-ts.hour*3600)/60; ts.second = ss%60; return &ts;}TIMESTAMP_STRUCT *ImDate::getTimeStamp(long long seconds){ TIMESTAMP_STRUCT ds; struct tm tmm = GetTimeStampBySeconds(seconds); ds.day = tmm.tm_mday; ds.month = tmm.tm_mon; ds.year = tmm.tm_year; ds.hour = tmm.tm_hour; ds.minute = tmm.tm_min; ds.second = tmm.tm_sec; ds.fraction = 0; return &ds;}char *ImDate::getCurrentDateTime(){ char sBuf[32] = {0}; time_t tt = time(NULL);//这句返回的只是一个时间cuo tm* t= localtime(&tt); sprintf(sBuf, "%d-%02d-%02d %02d:%02d:%02d",  t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); return sBuf;}
09-04 23:37
查看更多