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