C++中的时间函数
C++获取时间函数众多,何时该用什么函数,拿到的是什么时间?该怎么用?很多人都会混淆。
本文是本人经历了几款游戏客户端和服务器开发后,对游戏中时间获取的一点总结。
最早学习游戏客户端时,为了获取最精确的时间,使用两个函数
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency); BOOL QueryPerformanceCounter(LARGE_INTEGER *lpCount);
这两个函数分别是获取CPU的时钟频率和CPU计数器,是能够获取到的最精确的时间差。对于需要获取每帧走过的精确时间,使用这两个函数是最最精确的。
#include<windows.h> LARGE_INTEGER lFrequency;
QueryPerformanceFrequency(&lFrequency); LARGE_INTEGER lBeginCount;
QueryPerformanceCounter(&lBeginCount); Sleep(); LARGE_INTEGER lEndCount;
QueryPerformanceCounter(&lEndCount); double time = (double)(lEndCount.QuadPart - lBeginCount.QuadPart) / (double)lFrequency.QuadPart;
在客户端代码的时间处理模块中,每一帧调用QueryPerformanceCounter获取当前的counter,即可获取每一帧使用的时间。(当然现在有Unity,估计没人关注这俩函数了)
虽然利用这两个函数能够精确的统计经过的时间,但是却无法得到当前时间,并且以上两个函数是Windows系统所特有的,unix/linux系统中并不具备。
为了获取系统的当前精确时间,需要使用另一个系统函数
int gettimeofday(struct timeval *tv, struct timezone *tz);
获取从1970年1月1日到现在经过的时间和时区(UTC时间),(按照linux的官方文档,时区已经不再使用,正常应该传NULL)。
#include <sys/time.h> struct timeval start_tv; gettimeofday(&start_tv, NULL); sleep(); struct timeval end_tv; gettimeofday(&end_tv, NULL); double time = (end_tv.tv_sec - start_tv.tv_sec) + (double)(end_tv.tv_usec - start_tv.tv_usec)/(double);
这样同样可以获得精确到微秒的每帧经过的时间。服务器上的帧运行机制,一般便是这个时间函数来计算和同步。
如果不需要非常精确的时间,而只要精确到秒,可以使用另一个时间函数
time_t time(time_t* timer);
该函数返回一个UTC时间戳,如果传入timer参数,则为timer设置时间戳的值。
然而以上两个函数获取的都是UTC时间戳,如果在游戏中需要显示当前时区的时间,该怎么办呢?
使用localtime或localtime_r,两者效果一致,只是获取结果参数位置不同。
struct tm *localtime(const time_t *timep); // 传入UTC时间戳,返回当前时区的tm结构指针 struct tm *localtime_r(const time_t *timep, struct tm *result);
第一个函数获取tm结构静态变量的指针,第二个函数则传入一个tm结构变量的地址,并为之赋值。最终得到的tm变量,存储了当前时区的时间。
tm的结构定义如下,可以直接用来显示。
struct tm {
int tm_sec; /* seconds */
int tm_min; /* minutes */
int tm_hour; /* hours */
int tm_mday; /* day of the month */
int tm_mon; /* month */
int tm_year; /* year */
int tm_wday; /* day of the week */
int tm_yday; /* day in the year */
int tm_isdst; /* daylight saving time */
};
通常来说服务器和客户端通信同步时间时,不会传这么多int,只会传一个int64的UTC时间戳,给客户端自己转成当前时区。另外服务器也不会每次都调一次localtime转一次。一般来说,服务器和客户端都是维护一个int64的当前时间的UTC时间戳,以及一个当前时区的偏移时间,(客户端还会定时更新和服务器的时间误差,对时)。
因此,需要用到另外两个函数:
struct tm *gmtime(const time_t *timep); // time_t 到 tm 的转换,前后都是UTC时间,没有时区转换 struct tm *gmtime_r(const time_t *timep, struct tm *result); // gmtime 传入result方式 time_t mktime(struct tm *timeptr); // localtime的逆向操作,从当前时区的 tm 转到UTC的 time_t
在进程启动时
time_t t0 = ; // 当前时间为0时 time_t t1 = mktime(gmtime(&t0)); // UTC的时间 int timezone_diff = (int)(t0 - t1); // 当前时区和UTC的时间差
每次需要拿到当前时区时间,只需要用 UTCStamp + timezone_diff 即可。
除了获取时间,为了格式化显示时间,我们也可以利用一些系统函数,格式化输出时间字符串
char *asctime(const struct tm *tm); char *asctime_r(const struct tm *tm, char *buf); char ctime(const time_t *timep); char ctime_r(const time_t *timep, char *buf);
在游戏的实际应用中,一般都是根据具体需求来显示格式化的时间,甚至要做一些边界时间的特殊处理,因此这里都不详细讨论时间的格式化显示了。
C++中的时间函数的更多相关文章
- 借助JavaScript中的时间函数改变Html中Table边框的颜色
借助JavaScript中的时间函数改变Html中Table边框的颜色 <html> <head> <meta http-equiv="Content-Type ...
- ylb:SQL Server中的时间函数
ylbtech-SQL Server:SQL Server-SQL Server中的时间函数 SQL Server中的时间函数. 1,SQL Server中的时间函数 返回顶部 1. 当前系统日期 ...
- C中的时间函数的用法
C中的时间函数的用法 这个类展示了C语言中的时间函数的常用的用法. 源代码: #include <ctime>#include <iostream> using name ...
- SQLSERVER数据库中的 时间函数
一.sql server日期时间函数 Sql Server中的日期与时间函数 1. 当前系统日期.时间 select getdate() 2. dateadd 在向指定日期加上一段时间的基础上,返 ...
- PHP中日期时间函数date()用法总结
date()是我们常用的一个日期时间函数,下面我来总结一下关于date()函数的各种形式的用法,有需要学习的朋友可参考. 格式化日期date() 函数的第一个参数规定了如何格式化日期/时间.它使用字母 ...
- 【推荐】PHP中格式化时间函数date与gmdate的区别 | 修改PHP的默认时区
PHP中的时间有2个格式化函数:date()和gmdate(),在官方的文档中的描述为: date -- 格式化一个本地时间/日期 gmdate -- 格式化一个 GMT/UTC 日期/时间,返回的是 ...
- Linux C++中的时间函数(转)
http://net.pku.edu.cn/~yhf/linux_c/function/03.html asctime(将时间和日期以字符串格式表示) 相关函数 time,ctime,gmtime ...
- FineReport中日期时间函数使用总结
说明:凡函数中以日期作为参数因子的,其中日期的形式都必须是yy/mm/dd.而且必须用英文环境下双引号(" ")引用. DATE DATE(year,month,day):返回一个 ...
- Oracle中的时间函数用法(to_date、to_char) (总结)
一.24小时的形式显示出来要用HH24 select to_char(sysdate,'yyyy-MM-dd HH24:mi:ss') from dual; select to_date('2005- ...
随机推荐
- tLinux 2.2下安装Mono 4.8
Tlinux2.2发行版基于CentOS 7.2.1511研发而成,内核版本与Tlinux2.0发行版保持完全一致,更加稳定,并保持对Tlinux2.0的完全兼容.Mono 4版本要求CentOS 7 ...
- 谈谈DOMContentLoaded:Javascript中的domReady引入机制
一.扯淡部分 回想当年,在摆脱写页面时js全靠从各种DEMO中copy出来然后东拼西凑的幽暗岁月之后,毅然决然地打算放弃这种处处“拿来主义”的不正之风,然后开启通往高大上的“前端攻城狮”的飞升之旅.想 ...
- SQL Server内存遭遇操作系统进程压榨案例
场景: 最近一台DB服务器偶尔出现CPU报警,我的邮件报警阈(请读yù)值设置的是15%,开始时没当回事,以为是有什么统计类的查询,后来越来越频繁. 探索: 我决定来查一下,究竟是什么在作怪,我排查的 ...
- 2D、3D形变
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Monaco; color: #a5b2b9 } span.Apple-tab-span { ...
- Win10 IIS本地部署MVC网站时不能运行?
异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 部署后出现这个错误: 打开文件目录后发现是可以看见目录的,静态页面也是可以打开的 ...
- .NET平台开源项目速览(17)FluentConsole让你的控制台酷起来
从该系列的第一篇文章 .NET平台开源项目速览(1)SharpConfig配置文件读写组件 开始,不知不觉已经到第17篇了.每一次我们都是介绍一个小巧甚至微不足道的.NET平台的开源软件,或者学习,或 ...
- .Net 大型分布式基础服务架构横向演变概述
一. 业务背景 构建具备高可用,高扩展性,高性能,能承载高并发,大流量的分布式电子商务平台,支持用户,订单,采购,物流,配送,财务等多个项目的协作,便于后续运营报表,分析,便于运维及监控. 二. 基础 ...
- iOS开发之ReactiveCocoa下的MVVM(干货分享)
最近工作比较忙,但还是出来更新博客了,今天给大家分享一些ReactiveCocoa以及MVVM的一些东西,干活还是比较足的.在之前发表过一篇博文,名字叫做<iOS开发之浅谈MVVM的架构设计与团 ...
- Discuz NT 架构剖析之Config机制
接触了Discuz NT! 一段时间了,是时候做个总结了,标题好霸气,有木有? 都是托园子里的大牛代振军的福啊,哈哈哈哈. 首先论坛的信息不是完全存储在数据库里面的,一部分信息存储在config文件里 ...
- Android中通过ActionBar为标题栏添加搜索以及分享视窗
在Android3.0之后,Google对UI导航设计上进行了一系列的改革,其中有一个非常好用的新功能就是引入的ActionBar,他用于取代3.0之前的标题栏,并提供更为丰富的导航效果.Action ...