c/c++下时间函数总结

    GMT:格林尼治标准时间,以英国格林尼治天文台上的本初子午线(精度为0的经线)为标准。
    UTC:协调世界时间,基本与GMT时间相同,使用原子钟来计算,所以更加精确。
    本地时间:UTC + 时区差。
    UNIX时间戳: 自1970年1月1日0点到现在秒数。

    夏令时:到夏季开始的时候将时钟调快一小时,夏季结束的时候再将时钟调慢一小时以恢复正常时间。夏令时能够使人们早睡早起,有利于节省电力资源。

    1、time_t time(time_t * timer);

time()函数通过返回值或参数获得本机的当前日历时间(从1970年1月1日0时0分0秒到现在经过的秒数),time_t实际上是一个long long。linux下time_t是int,这样会引发2038年问题。

    2、struct tm * gmtime(const time_t *timer);

          struct tm *localtime(const time_t * timer);

上面两个函数将日历时间转换为tm结构体所表示的时间类型,其中gmtime()函数转化为世界标准时间(格林尼治时间),localtime()转化为本地时间(带时区的时间)。

tm结构体成员:

struct tm {
int tm_sec;       /* 秒[0,59] */
int tm_min;       /* 分[0,59] */
int tm_hour;     /* 时[0,23] */
int tm_mday;    /* 日[1,31] */
int tm_mon;     /* 月[0,11],其值+1为实际月份 */
int tm_year;     /* 年,其值+1900为实际年份 */
int tm_wday;    /* 星期[0,6],其中0代表星期天,1代表星期一,以此类推,此成员可以忽略不填 */
int tm_yday;    /* 从1月1日开始的天数[0,365],此成员可以忽略不填*/
int tm_isdst;    /* 夏令时标识符,实行夏令时的时候,tm_isdst为正;不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负*/

}; 

    需要注意的是上面两个方法中返回的tm指针指向的实际上是一个静态内存,比如下面的pTm1和pTm2都是1555050416时间,推荐使用gmtime_s()、localtime_s代替上面两个函数。

time_t temp = 1444050200;
tm* pTm1 = localtime(&temp);

temp = 1555050416;
tm* pTm2 = localtime(&temp);

  3、char * ctime(const time_t *timer);

       char * asctime(const struct tm * timeptr);

     上面两个函数将日历时间、tm结构时间转换为固定时间格式的字符串。固定时间格式为:星期几 月份 日期 时:分:秒 年\n\0。

      size_t strftime( char *strDest,  size_t maxsize,  const char *format,  const struct tm *timeptr);

      strftime()函数将tm结构时间类型转换为自定义格式的字符串。strDest指向输出的字符串,maxsize为输出字符串大小,format为格式控制字符串,timeptr指向要转换的tm时间结构。

strftime()的格式控制符:

%a 星期几的简写 
%A 星期几的全称 
%b 月分的简写 
%B 月份的全称 
%c 标准的日期的时间串 
%C 年份的后两位数字 
%d 十进制表示的每月的第几天 
%D 月/天/年 
%e 在两字符域中,十进制表示的每月的第几天 
%F 年-月-日 
%g 年份的后两位数字,使用基于周的年 
%G 年分,使用基于周的年 
%h 简写的月份名 
%H 24小时制的小时 
%I 12小时制的小时 
%j 十进制表示的每年的第几天 
%m 十进制表示的月份 
%M 十时制表示的分钟数 
%n 新行符 
%p 本地的AM或PM的等价显示 
%r 12小时的时间 
%R 显示小时和分钟:hh:mm 
%S 十进制的秒数 
%t 水平制表符 
%T 显示时分秒:hh:mm:ss 
%u 每周的第几天,星期一为第一天 (值从0到6,星期一为0) 
%U 第年的第几周,把星期日做为第一天(值从0到53) 
%V 每年的第几周,使用基于周的年 
%w 十进制表示的星期几(值从0到6,星期天为0) 
%W 每年的第几周,把星期一做为第一天(值从0到53) 
%x 标准的日期串 
%X 标准的时间串 
%y 不带世纪的十进制年份(值从0到99) 
%Y 带世纪部分的十进制年份 
%z,%Z 时区名称,如果不能得到时区名称则返回空字符。 
%% 百分号

     使用time()获得的日历时间(UNIX时间戳)实际上是GMT时间,比如2022年10月31号的0点0时0分的时候在我的电脑上调用time()得到的是1667145600,使用这个数值除86400(一天24小时的秒数)的话不能够除尽,而将这个数值再加上28,800(8个小时的秒数)的话就能被除尽。虽然使用time()获得的日历时间是GMT时间,但通过localtime()获得的为带时区的本地时间,如下所示(以下代码为在Windows下的VS上运行,Linux中是否为相同效果未测试):

	time_t tim = 1667145600;
	tm tt = { 0 };
	char buf[32] = { 0 };

	localtime_s(&tt, &tim); //获得的tm为本地时间
	strftime(buf, sizeof(buf), "%F %T", &tt);
	std::cout << buf << std::endl; //输出为 2022-10-31 00:00:00

	memset(&tt, 0, sizeof(tt));
	memset(buf, 0, sizeof(buf));

	gmtime_s(&tt, &tim); //获得的tm为GMT时间
	strftime(buf, sizeof(buf), "%F %T", &tt);
	std::cout << buf << std::endl; //输出为 2022-10-30 16:00:00

4、time_t mktime(struct tm * timeptr);

mktime()函数将tm时间结构转换为日历时间。

   mktime()方法获得的时间戳也是GMT时间:

	tm t = { 0 };
	t.tm_year = 2022 - 1900;
	t.tm_mon = 9;
	t.tm_mday = 31; //tm为2022年10月31号0点0时0分
	
	time_t tim = mktime(&t); //1667145600

	double d1 = tim / (3600.0 * 24); // 19295.66666666,不能除尽
	double d2 = (tim + 8 * 3600) / (3600.0 * 24); //19296,能被除尽

5、double difftime(time_t time1, time_t time0);

difftime()函数返回两个日历时间的时间差,以秒为单位。

eg:计算2012年12月24号0点0时0分到现在经过的秒数。

struct tm tm;
tm.tm_year = 2012-1900;//实际年份-1900
tm.tm_mon = 12-1;//实际月份减1
tm.tm_mday = 24;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0; 

time_t start, now;
start = mktime(&tm);
now = time(NULL);
	
double cost = difftime(now, start);//间隔的秒数

   6、clock_t clock( void );

          clock()函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock),其中clock_t实际上是长整型。在time.h文件中,还定义了一个常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元:#define CLOCKS_PER_SEC ((clock_t)1000)。可以使用公式clock()/CLOCKS_PER_SEC来计算一个进程自身的运行时间,eg:

printf("Elapsed time:%u secs.\n", clock()/CLOCKS_PER_SEC);

    以上C/C++下的时间函数需包含time.h头文件

    7、VC++下的GetLocalTime()和GetSystemTime()函数可以分别获得本地时间和世界标准时间。

          eg:

 CString strTime;
 SYSTEMTIME lt;
 GetLocalTime(<);
 strTime.Format(_T("time: %02d:%02d:%02d:%04d"), 
 		lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds);
 AfxMessageBox(strTime);

输出为"time: 14:55:46:0546"。

VC++下的GetTickCount()函数可以获取系统从开始运行到现在经过的时间(毫秒)。函数原型:

DWORD WINAPI GetTickCount(void);

   8、MFC类中静态函数 CTime::GetCurrentTime()可以获得当前时间。

                                           CTime::Format()可以对时间对象进行格式化。

         eg,CString转换为CTime:

CTime time;
time = CTime::GetCurrentTime();
CString strTime = time.Format(L"%y-%m-%d %H:%M:%S");//strTime="14-04-26 17:07:35"

 9、时间转换

//获得现在时间,格式:1980-01-11 11:24:30
string GetTime()
{
	time_t tim;
	time(&tim);
	string strTime;
	Time_tToStr(tim, strTime);
	return strTime;
}

//time_t转换为char*
void Time_tToStr(time_t& tim, string& str)
{
	tm _tm;
	localtime_s(&_tm, &tim);
	char buf[32] = { 0 };
	sprintf_s(buf, 32, "%d-%02d-%02d %02d:%02d:%02d", _tm.tm_year + 1900, _tm.tm_mon + 1, _tm.tm_mday, _tm.tm_hour, _tm.tm_min, _tm.tm_sec);
	str = buf;
}

//char*转换为time_t,输入参数应为14长度的时间,如"20151106181346"
time_t StrToTime_t(char * szTime)  
{  
	unsigned short usLen = strlen(szTime);
	if(usLen != 14)
	{
		time_t time1;
		memset(&time1, 0, sizeof(time_t));
		return time1;
	}

	char* p = szTime;
	for(int i=0; i<usLen; i++)
	{
		if(*p==' ')
			*p = '0';

		p++;
	}

	struct tm tm1;  
	memset(&tm1, 0, sizeof(tm1));
	time_t time1;  

	sscanf(szTime, "%4d%2d%2d%2d%2d%2d",      
		&tm1.tm_year,   
		&tm1.tm_mon,   
		&tm1.tm_mday,   
		&tm1.tm_hour,   
		&tm1.tm_min,  
		&tm1.tm_sec);  
	tm1.tm_year -= 1900;  
	tm1.tm_mon --;  
	tm1.tm_isdst=-1;  

	time1 = mktime(&tm1);  

	return time1;  
}  

time_t tm2time_t(tm t)
{
	t.tm_year -= 1900;
	t.tm_mon -= 1;
	return mktime(&t);
}

time_t systime2timet(const SYSTEMTIME& st)
{
	struct tm gm = {st.wSecond, st.wMinute, st.wHour, st.wDay, st.wMonth-1, st.wYear-1900, st.wDayOfWeek, 0, 0};
	return mktime(&gm);
}

SYSTEMTIME Time_t2SystemTime(time_t t)
{
	tm temptm = *localtime(&t);
	SYSTEMTIME st = {1900 + temptm.tm_year, 
		1 + temptm.tm_mon, 
		temptm.tm_wday, 
		temptm.tm_mday, 
		temptm.tm_hour, 
		temptm.tm_min, 
		temptm.tm_sec, 
		0};
	return st;
} 

    参考文章:http://www.cnblogs.com/emanlee/archive/2007/10/23/935356.html

              http://blog.csdn.net/coder_xia/article/details/6566708

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值