c/c++时间操作函数总结

一、时区相关概念

地球自西往东转动,东边比西边先看到太阳,所以东边的时间比西边的时间早。将地球经度按照24个时区进行划分,每个时区相隔的经度为15度。以英国伦敦(格林尼治天文台旧址)为中时区(零时区),向东有11个时区,向西也有11个时区,太平洋白令海峡所在经度为12区,东西各占一半。0时区向东每隔一个时区时间快1小时,向西每隔一个时区时间慢1小时。在12区中间,左边刚好比右边日期大1天。

UTC协调时间时间=世界标准时间=格林尼治时间=G.M.T(Greenwich Mean Time),指0时区所处的时间。

夏令时(阳光节约时/DST/Daylight Saving Time):因为北半球大部分国家在夏天日照时间较长,为了节约能源,让人们充分利用太阳光源,某些国家在夏天会人为地将时间设置快一个小时。例如美国每年3月的第二个星期日开始,至每年11月的第一个星期日为夏令时。

二、计算机时间

1970-01-01 00:00:00是计算机元年,因为Unix操作系统和C语言于1971年发布,所以将这一时间作为时间元年。在32位系统中由于采用带符号的32位整形数据类型处理unix时间,所以当unix时间大于2的32次方减一(0x7FFFFFFF),也就是时间在到达2038年1月19日03:14:07UTC时,再往后时间就会变成负值。如果采用64位整形处理unix时间,则完全够用。

1900-01-01 00:00:00一般作为NTP起始时间。在RTP/RTCP等网络协议中,当采用32位字段表示NTP时间戳时,当时间大于2的33次方减1(0xFFFFFFFF),NTP时间戳在2036年会发生溢出。但是由于在RTCP中一般仅仅计算NTP的差值,所以只要时间差不超过68年就可以了。

三、C库时间操作函数c

1、time

函数原型:time_t time(time_t* timer);

函数说明:获取系统UTC时间到1970-01-01 00:00:00的秒数。timer为NULL,通过返回值返回。也可以通过timer参数返回。time_t在32位系统下最大只能表示到2038-01-19 03:14:07,在64位系统下则完全够用

2、localtime

函数原型:struct tm* localtime(const timer_t* timer);

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  */
             int tm_year;        /* 自 1900 年起的年数      */
             int tm_wday;        /* 一周中的第几天,范围从 0 到 6 */
             int tm_yday;        /* 一年中的第几天,范围从 0 到 365   */
             int tm_isdst;       /* 夏令时               */
         };

函数说明:将time_t类型值转换为tm结构,采用本地时区

线程安全:locltime为非线程安全函数,返回的为内部静态变量指针,linux下线程安全函数为localtime_r(),windows下没有

3、gmtime

函数原型:struct tm* gmtime(time_t* timer);

函数说明:将time_t类型值转换为tm结构,采用0时区

线程安全:linux下线程安全函数为gmtime_r()

4、mktime

函数原型:time_t mktime(struct tm* timeptr);

函数说明:计算将timeptr按照系统时区转换为0时区,然后到计算机元年间的秒数

例子:

#include 
#include 

int main()
{
	time_t t = time(NULL);
    //or
    //time_t t;
    //time(&t);

	struct tm* tmLocalNow = localtime(&t);
	tmLocalNow->tm_year += 1900;
	tmLocalNow->tm_mon += 1;
	printf("local now datetime: %d.%02d.%02d %02d:%02d:%02d\n",
		tmLocalNow->tm_year,tmLocalNow->tm_mon,tmLocalNow->tm_mday,tmLocalNow->tm_hour,tmLocalNow->tm_min,tmLocalNow->tm_sec);

    struct tm* tmUTCNow = gmtime(&t);
	tmUTCNow->tm_year += 1900;
	tmUTCNow->tm_mon += 1;
	printf("UTC now datetime: %d.%02d.%02d %02d:%02d:%02d\n",
		tmUTCNow->tm_year,tmUTCNow->tm_mon,tmUTCNow->tm_mday,tmUTCNow->tm_hour,tmUTCNow->tm_min,tmUTCNow->tm_sec);

	return 0;
}

线程不安全例子:

#include 
#include 

int main()
{
	time_t t1 = time(NULL);
    time_t t2 += 1800;
    
    struct tm* tm1 = localtime(&t1);
    struct tm* tm2 = localtime(&t2);
    //执行到这里的时候tm1值变为tm2,因为内部他们指向的是同一内存地址

	return 0;
}

5、Sleep/sleep/usleep

Sleep(毫秒)为windows下挂起函数,精确到毫秒级

sleep(秒)为linux下挂起函数,精确到秒级。

usleep(微秒)为linux下挂起函数,精确到微秒级。

Sleep()在windows下挂起后仍然会占用CPU处理时间,而sleep()和usleep()在linux下不会占用

6、clock

函数原型:clock_t clock();

函数说明,返回从程序执行时起到现在,消耗的处理器时间(不是程序执行时间)对应的时钟数,每秒钟处理器的时钟数为CLOCKS_PER_SEC。

例子:

#ifdef WIN32
#include 
#else
#include 
#endif

#include 

int main()
{
	clock_t clockStart;
	clockStart = clock();
#ifdef WIN32
	Sleep(2000);
#else
	sleep(2);
#endif
	clock_t clockEnd;
	clockEnd = clock();
	double dInterval = (double)(clockEnd - clockStart) / CLOCKS_PER_SEC;
	printf("interval: %f\n", dInterval);
}

执行结果:

linux下为0.000040,windows下为2.001000,因为linux下sleep()不占用CPU处理时间,而windows下Sleep()下占用系统时间。

四、linux时间系统函数

1、gettimeofday

获取当前时间,返回从计算机元年到现在经历的时间。

头文件:

sys/time.h

unistd.h

函数声明:int gettimeofday(struct timeval* tv, struct timezone* tz);

timeval结构定义为: 

struct timeval

    long tv_sec; /*秒*/ 
    long tv_usec; /*微秒*/ 
}; 
timezone 结构定义为: 
struct timezone

    int tz_minuteswest; /*和Greenwich 时间差了多少分钟*/ 
    int tz_dsttime; /*日光节约时间的状态*/ 
}; 
上述两个结构都定义在/usr/include/sys/time.h。tz_dsttime 所代表的状态如下 
DST_NONE /*不使用*/ 
DST_USA /*美国*/ 
DST_AUST /*澳洲*/ 
DST_WET /*西欧*/ 
DST_MET /*中欧*/ 
DST_EET /*东欧*/ 
DST_CAN /*加拿大*/ 
DST_GB /*大不列颠*/ 
DST_RUM /*罗马尼亚*/ 
DST_TUR /*土耳其*/ 
DST_AUSTALT /*澳洲(1986年以后)*/
返回值:成功则返回0,失败返回-1,错误代码存于errno。附加说明EFAULT指针tv和tz所指的内存空间超出存取权限。

2、settimeofday()

设置当前时间,只有root权限才能使用此函数修改时间。

头文件:

sys/time.h

unistd.h

函数声明:int settimeofday(struct timeval* tv, struct timezone* tz);

返回值:成功则返回0,失败返回-1,错误代码存于errno。

错误代码:
EPERM 并非由root权限调用settimeofday(),权限不够。 
EINVAL 时区或某个数据是不正确的,无法正确设置时间。

3、clock_gettime

函数声明:int clock_gettime(clockid_t clk_id,struct timespec* tp);

clk_id取值

CLOCK_REALTIME:系统从计算机元年到现在的时间,随系统时间变化而变化

CLOCK_MONOTONIC:系统启动到现在的时间,不随系统时间变化而变化

CLOCK_PROCESS_CPUTIME_ID:本进程从启动到现在CPU花费的时间,sleep和usleep不占用cpu时间

CLOCK_THREAD_CPUTIME_ID:本线程从启动到现在CPU花费的时间

timespec结构

struct timespec
{
        time_t tv_sec; /* 秒*/
        long tv_nsec; /* 纳秒*/
};

五、windows时间系统函数

1、GetLocalTime

获取当前系统时间,以系统时区为标准,精确到毫秒级。

函数声明:void GetLocalTime(LPSYSTEMTIME lpSystemTime);

SYSTMETIME结构定义:

typedef struct _SYSTEMTIME

{

WORD wYear;//年

WORD wMonth;//月

WORD wDayOfWeek;//星期

WORD wDay;//日

WORD wHour;//时

WORD wMinute;//分

WORD wSecond;//秒

WORD wMilliseconds;//毫秒

}SYSTEMTIME,*PSYSTEMTIME;

2、GetSystemTime

获取当前系统时间,以0时区为标准。

3、SetLocalTime

设置系统本地时间

4、SetSystemTime

设置系统UTC时间

5、GetTickCount

返回操作系统启动到现在所经过的毫秒数

函数声明:DWORD GetTickCount(void);

GetTickCount()和Clock()函数是向主板BIOS要real time clock时间,会有中断产生,以及延迟问题。

6、QueryPerformaceFrequency和QueryPerformanceCounter

返回硬件支持的高精度计数器的频率,返回系统从启动到现在的时间。

函数声明:

BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);

参数类型定义如下:

typeef union _ LARGE_INTEGER

{

struct

{

DWORD LowPart;

LONG HighPart;

};

LONGLONG QuadPart;

} LARGE_INTEGER;

QueryPerformanceCounter获取系统启动到现在计数器时钟数。QueryPerformanceFrequency获取系统的时钟频率,也就是每秒系统的时钟数。

例子:


#include 

int main()
{
	LARGE_INTEGER lagerCounter1;
	QueryPerformanceCounter(&lagerCounter1);
	long long llCounter1 = lagerCounter1.QuadPart;

	Sleep(2000);

	LARGE_INTEGER lagerCounter2;
	QueryPerformanceCounter(&lagerCounter2);
	long long llCounter2 = lagerCounter2.QuadPart;

	LARGE_INTEGER largerFreq;
	QueryPerformanceFrequency(&largerFreq);
	long long llFreq = largerFreq.QuadPart;

	double dIntervals = (llCounter2 - llCounter1) / llFreq;
	printf("the interval is: %f",dIntervals);
}

例子输出为2.0。

参考:

1.https://blog.csdn.net/hmxz2nn/article/details/77986450

2.https://blog.csdn.net/tsx86/article/details/49965171

3.https://blog.csdn.net/weixin_34295316/article/details/86061183

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值