Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2545665
  • 博文数量: 416
  • 博客积分: 10220
  • 博客等级: 上将
  • 技术积分: 4191
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-15 09:47
文章分类

全部博文(416)

文章存档

2022年(1)

2021年(1)

2020年(1)

2019年(5)

2018年(7)

2017年(6)

2016年(7)

2015年(11)

2014年(1)

2012年(5)

2011年(7)

2010年(35)

2009年(64)

2008年(48)

2007年(177)

2006年(40)

我的朋友

分类: C/C++

2019-08-29 10:47:23

     最近发现以前开发的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;
}


阅读(1379) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~