最近发现以前开发的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 < sizeof(tms) / sizeof(tms[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 << tmm.year << "-" << tmm.month << "-" << tmm.day << " "
<< tmm.hour << ":" << tmm.minute << ":" << tmm.second << "\t"
<< strValue << endl;
}
}
输出结果:
2005-3-11 0:0:0 2005-03-11
1974-11-20 0:0:0 1974-11-20
2001-9-9 0:0:0 2001-09-09
1968-12-8 0:0:0 Invalid DateTime
2006-2-1 23:1:3 2006-02-01
1999-5-12 0:0:1 1999-05-12
1999-5-12 23:59:59 1999-05-12
2011-4-9 0:0:0 2011-04-09
2014-3-15 14:8:3 2014-03-15
1970-1-11 18:55:9 1970-01-11
1970-2-11 5:13:7 1970-02-11
1501-7-19 0:0:0 Invalid DateTime
tms中的变量值小于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 < (leap?366:365) );
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 < 0)
// {
// 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<1970; 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<0; n+=365){
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<1970; 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 <= 12 && d > 0 && d <= month[m - 1];
}
int ImDate::IsValidTime(int h, int m, int s)
{
int ret = ( (h >= 0 && h <24) &&
(m >= 0 && m <60 ) &&
(s >= 0 && s <60) );
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)<=8){ //time
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)<=10){ //date
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)<=SECONDS_PER_DAY){
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<0){ //是GetDayByDate逆向算法
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;
}
// 通过秒数,计算time
void 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以来的时间戳秒数,计算DateStamp
tm 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 << ptm2->tm_year << "-" << ptm2->tm_mon<<"-" <tm_mday<< " "
// <tm_hour << ":" << ptm2->tm_min << ":" << ptm2->tm_sec << endl;
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;
}
阅读(1938) | 评论(0) | 转发(0) |