一个日期时间字符串的解析类

网友投稿 1082 2022-09-25

一个日期时间字符串的解析类

一个日期时间字符串的解析类

一个日期时间类,可以完成:

1. 从一个给定的日期时间字符串中解析出日期时间信息

2. 提供一些常用的日期时间的校验算法

该类支持的日期时间格式如下:

5(五秒)

4:5(四分五秒)

5:3:6(五时三分六秒)(注:不是五小时,而是凌晨五时,绝对时间)

2-28(2月28日)

2-28 5:3:6(2月28日)

2008-2-28(2008年2月28日)

2008-2-28 17:3:6(2008年2月28日17时3分6秒)

还支持站位符方式:

-2-  仅设定月份为2月,其余日期采用当前值

2008-- 仅设定年

:23: 仅设定分

-- :: 全部省略,采用当前日期时间作为默认值

如果不能解析到指定的部分,则采用默认值(默认值为当前日期)

头文件:

===================================================================

/*

类名:TDateTime

描述:日期时间类

作用:1. 从一个给定的日期时间字符串中解析出日期时间信息

2. 提供一些常用的日期时间的校验算法

备注:

该类支持的日期时间格式如下:

5(五秒)

4:5(四分五秒)

5:3:6(五时三分六秒)(注:不是五小时,而是凌晨五时,绝对时间)

2-28(2月28日)

2-28 5:3:6(2月28日)

2008-2-28(2008年2月28日)

2008-2-28 17:3:6(2008年2月28日17时3分6秒)

还支持站位符方式:

-2-  仅设定月份为2月,其余日期采用当前值

2008-- 仅设定年

:23: 仅设定分

-- :: 全部省略,采用当前日期时间作为默认值

如果不能解析到指定的部分,则采用默认值(默认值为当前日期)

历史:

2008-11-21     尹曙光([email]kevdmx@sina.com[/email])  创建

*/

#ifndef _TDATETIME_H_20081121_

#define _TDATETIME_H_20081121_

//在windows下,如果强制使用32位的time_t,请定义以下宏:

//#ifndef _USE_32BIT_TIME_T

//#define _USE_32BIT_TIME_T

//#endif

#include

#ifndef BOOL

#define BOOL int

#endif

#ifndef TRUE

#define TRUE 1

#endif

#ifndef FALSE

#define FALSE 0

#endif

class TDateTime

{

public:

//年

unsigned short sYear;

//月

unsigned char sMonth;

//日

unsigned char sDay;

//时

unsigned char sHour;

//分

unsigned char sMinute;

//秒

unsigned char sSecond;

public:

//构造函数,采用当前的日期时间作为默认值

TDateTime();

//构造函数,从time_t类型的变量中取得日期时间

TDateTime(time_t t);

//从字符串中解析出日期时间,未解析到的部分,采用当前默认值

BOOL ParseDateTimeString(char *szDateTime);

//重新为当前的日期时间

BOOL LoadCurrentDateTime();

//转化为UNIX形式的time_t时间日期类型

time_t ToUnixDatetime();

//重新设定为有time_t类型变量指定的日期时间值

void FromUnixDatetime(time_t t);

//校验当前对象的日期时间数据是否正确

BOOL Validate();

//校验一个TDateTime类型变量的日期时间数据是否正确

static BOOL Validate(TDateTime *obDateTime);

//检查年份是否是闰年

static BOOL IsLeapYear(int year);

//校验给定的年份是否正确

static BOOL ValidateDate(int year);

//校验给定的年份和月分是否正确

static BOOL ValidateDate(int year,int month);

//取得给定的年份,给定的月份含有的天数

static int GetDaysOfMonth(int year, int month);

//校验给定的年月日数据是否正确

static BOOL ValidateDate(int year, int month, int day);

//检验给定的小时数据,是否正确

static BOOL ValidateTime(int hour);

//校验给定的小时分钟数据是否正确

static BOOL ValidateTime(int hour,int minute);

//校验给定的时间数据是否正确

static BOOL ValidateTime(int hour, int minute, int second);

//校验给定的日期时间数据是否正确

static BOOL ValidateDateTime(int year, int month, int day,

int hour, int minute, int second);

private:

//token类型定义

typedef enum TokenType

{

TT_Null = 0,

TT_Number =1,

TT_Minus = 2,

TT_Colon = 4,

TT_Blank = 8

};

//日期时间类型定义

typedef enum TimePart

{

TP_Second = 1,

TP_Minute = 2,

TP_Hour = 4,

TP_Day = 8,

TP_Month = 16,

TP_Year = 32

};

private:

//将当前对象变量清零

void ZeroDateTime(void);

//根据字符取得该字符所属的类型

TDateTime::TokenType GetTokenType(char c);

};

#endif  //#ifndef _TDATETIME_H_20081121_

代码文件:

==================================================================

#include "stdafx.h"

#include

#include

#include "tdatetime.h"

//中国的时间区域为格林威治的东八区,故需要一个时间偏移量

const int TIMEZONE_8 = 8*60*60;

TDateTime::TDateTime()

{

LoadCurrentDateTime();

}

TDateTime::TDateTime(time_t t)

{

FromUnixDatetime(t);

}

TDateTime::TokenType

TDateTime::GetTokenType(char c)

{

if ((c>='0') && (c<='9'))

return TT_Number;

else if ('-'==c){

return TT_Minus;

}else if ('/'==c){

return TT_Minus;

}else if (' ' == c){

return TT_Blank;

}else if(':'==c){

return TT_Colon;

}else{

return TT_Null;

}

}

BOOL

TDateTime::ParseDateTimeString(char *szDateTime)

{

int len = strlen(szDateTime) - 1;

TimePart timePart = TP_Second;

int pw =1;//加权

signed short year=-1;

signed char month=-1,day=-1,hour=-1,minute=-1,second=-1;

//过滤尾部空格

while((len>=0) && (' ' == szDateTime[len]))

len--;

if (len<0) return FALSE;

while(len>=0){

char c = szDateTime[len];

switch( GetTokenType(c))

{

case TT_Null: goto ParseDateTimeString_FALSE;

case TT_Number:

switch(timePart)

{

case TP_Second:

if (second<0 )

second = c-'0';

else

second += (c-'0') * pw;

pw *= 10;

break;

case TP_Minute:

if (minute<0 )

minute = c-'0';

else

minute += (c-'0') * pw;

pw *= 10;

break;

case TP_Hour:

if (hour<0 )

hour = c-'0';

else

hour += (c-'0') * pw;

pw *= 10;

break;

case TP_Day:

if (day<0 )

day = c-'0';

else

day += (c-'0') * pw;

pw *= 10;

break;

case TP_Month:

if (month<0 )

month = c-'0';

else

month += (c-'0') * pw;

pw *= 10;

break;

case TP_Year:

if (year<0 )

year = c-'0';

else

year += (c-'0') * pw;

pw *= 10;

break;

default:

return FALSE;

}

break;

case TT_Minus:

switch(timePart)

{

case TP_Second: //如果没有给定时间信息,则跳过,直接升级到日期

pw =1;

timePart = TP_Month; //提升

day = second;

second = -1;  //将解析到的秒信息改为日期信息

break;

case TP_Minute: goto ParseDateTimeString_FALSE;

case TP_Hour: goto ParseDateTimeString_FALSE;

case TP_Day:

pw =1;

timePart = TP_Month; //提升

break;

case TP_Month:

pw =1;

timePart = TP_Year; //提升

break;

case TP_Year: goto ParseDateTimeString_FALSE;

default: goto ParseDateTimeString_FALSE;

}

break;

case TT_Colon:

switch(timePart)

{

case TP_Second:

pw =1;

timePart = TP_Minute; //提升

break;

case TP_Minute:

pw =1;

timePart = TP_Hour; //提升

break;

case TP_Hour: goto ParseDateTimeString_FALSE;

case TP_Day: goto ParseDateTimeString_FALSE;

case TP_Month: goto ParseDateTimeString_FALSE;

case TP_Year: goto ParseDateTimeString_FALSE;

default: goto ParseDateTimeString_FALSE;

}

break;

case TT_Blank:

if (TP_Hour == timePart){

timePart = TP_Day; //提升

pw =1;

}else if (TP_Year == timePart){  //前导空格

goto ParseDateTimeString_OK;//认为结束

}else{//在其他部分不能出现空格

goto ParseDateTimeString_FALSE;

}

break;

}

len -- ;

}

ParseDateTimeString_OK:

if (year>0)

sYear = year;

if (month>0)

sMonth = month;

if (day>0)

sDay = day;

if (hour>=0)

sHour = hour;

if (minute>=0)

sMinute = minute;

if (second>=0)

sSecond = second;

if (Validate()){

return TRUE;

}else{

ZeroDateTime();

return FALSE;

}

ParseDateTimeString_FALSE:

ZeroDateTime();

return FALSE;

}

BOOL

TDateTime::LoadCurrentDateTime()

{

time_t t;

time(&t);

FromUnixDatetime(t);

return TRUE;

}

void

TDateTime::FromUnixDatetime(time_t t)

{

t += TIMEZONE_8;

struct tm *tt = gmtime( &t);

sYear = tt->tm_year+1900;

sMonth = tt->tm_mon+1;

sDay = tt->tm_mday;

sHour = tt->tm_hour;

sMinute = tt->tm_min;

sSecond = tt->tm_sec;

//free(tt);

}

void

TDateTime::ZeroDateTime(void)

{

sYear = 0;

sMonth = 0;

sDay = 0;

sHour = 0;

sMinute = 0;

sSecond = 0;

}

///

/// 判定给定的年份是否是润年

///

/// 需要判定的年份

/// true:给定的年份是润年。false:给定的年份不是润年。

BOOL

TDateTime::IsLeapYear(int year)

{

return ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0));

}

///

/// 判定给定的年份是否有效。

///

/// 给定的年份

/// true:有效,false:无效

BOOL

TDateTime::ValidateDate(int year)

{

return (year > 0) && (year <= 9999);

}

///

/// 判定给定的年月是否有效

///

/// 给定的年份

/// 给定的月份

/// true:有效。false:无效。

BOOL

TDateTime::ValidateDate(int year,int month)

{

if (!ValidateDate(year))

return FALSE;

return (month > 0) && (month < 13);

}

///

/// 得到一个月份的天数

///

///

///

/// 返回该年该月的总天数,如果给定的参数有错误,则返回0

int

TDateTime::GetDaysOfMonth(int year, int month)

{

if (!ValidateDate(year, month))

{

return 0;

}

if (month == 4 || month == 6 || month == 9 || month == 11)

{

return 30;

}

else if (month == 1 || month == 3 || month == 5

|| month == 7 || month == 8 || month == 10 || month == 12)

{

return 31;

}

else if (2 == month)

{

if (IsLeapYear(year))//如果是闰年

{

return 29;

}

else

{

return 28;

}

}

return 0;

}

///

/// 判定给定的年月日是否是一个有效的日期

///

/// 给定的年份

/// 给定的月份

/// 给定的日子

/// true:给定的年月日是一个有效的日期。false:不是一个有效的日期。

BOOL

TDateTime::ValidateDate(int year, int month, int day)

{

if (!ValidateDate(year, month))

return FALSE;

if ((day < 1) || (day > GetDaysOfMonth(year, month)))

return FALSE;

return TRUE;

}

///

/// 判定给定的小事是否有效

///

/// 给定的小时

/// true:有效;false:无效

BOOL

TDateTime::ValidateTime(int hour)

{

return (hour >= 0) && (hour < 24);

}

///

/// 判定给定的小时和分钟是否有效。

///

/// 给定的小时

/// 给定的分钟

/// true:有效;false:无效

BOOL

TDateTime::ValidateTime(int hour,int minute)

{

if (!ValidateTime(hour))

return FALSE;

return (minute >= 0) && (minute < 60);

}

///

/// 判定给定的小时、分钟、秒时否有效

///

/// 给定的小时

/// 给定的分钟

/// 给定的秒

/// true:有效;false:无效

BOOL

TDateTime::ValidateTime(int hour, int minute, int second)

{

if (!ValidateTime(hour,minute))

return FALSE;

return (second >= 0) && (second < 60);

}

///

/// 判定给定的年月日时分秒是否是一个有效的日期时间

///

/// 给定的年份

/// 给定的月份

/// 给定的日子

/// 给定的小时

/// 给定的分钟

/// 给定的秒

/// true:有效;false:无效

BOOL

TDateTime::ValidateDateTime(int year, int month, int day,

int hour, int minute, int second)

{

return ValidateDate(year, month, day)

&& ValidateTime(hour, minute, second);

}

BOOL

TDateTime::Validate()

{

return Validate(this);

}

BOOL

TDateTime::Validate(TDateTime *obDateTime)

{

return ValidateDateTime(obDateTime->sYear,obDateTime->sMonth, obDateTime->sDay,

obDateTime->sHour, obDateTime->sMinute, obDateTime->sSecond);

}

time_t

TDateTime::ToUnixDatetime()

{

tm tt;

tt.tm_year = sYear - 1900;

tt.tm_mon = sMonth -1;

tt.tm_mday = sDay;

tt.tm_hour = sHour;

tt.tm_min = sMinute;

tt.tm_sec = sSecond;

return mktime(&tt);

}

测试工程文件:

================================================================

// parsedt.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include "tdatetime.h"

//注意:在给定参数时,日期和时间中间有空格分隔,故需要有引号限定

//如:exe "2008-11-21 22:23:59"

//在UNIX下可以使用“\”进行转义

//如:exe 2008-11-21\ 22:23:59

int main(int argc, char** argv)

{

TDateTime dtm;

if (argc<2){

printf("parsedt datetime_string");

return 1;

}

if (!dtm.ParseDateTimeString(argv[1])){

printf("Error!\n");

return 1;

}

printf("year:%d, month:%d, day:%d, hour:%d, minute:%d, second:%d\n",

dtm.sYear, dtm.sMonth, dtm.sDay, dtm.sHour, dtm.sMinute, dtm.sSecond);

TDateTime dtm2(dtm.ToUnixDatetime());

printf("year:%d, month:%d, day:%d, hour:%d, minute:%d, second:%d\n",

dtm2.sYear, dtm2.sMonth, dtm2.sDay, dtm2.sHour, dtm2.sMinute, dtm2.sSecond);

return 0;

}

VS2005下编译通过。该代码没有平台相关性,可以在UNIX下编译。

~~THE END~~

尹曙光

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:新营销时代,内容种草迎来三大升级模式!
下一篇:Apache日志出现internal dummy connection信息
相关文章

 发表评论

暂时没有评论,来抢沙发吧~