time_t的局限性及时间函数设计

时间:2021-10-27 21:29:51

time_t的局限性及时间函数设计

 

time_t早期是32位的,用来表示从1970.1.1开始的秒数,当初设计的时候受制于32位的容量,time_t只能表示136年的时间,而且精度只能到秒,后来time_t修改为64位,但仍然兼容了原来的设计,time_t虽然现在默认64位了但依然精度为秒,这是极大浪费的。

系统还有很多time相关的函数,如win下mktime、gmtime、GetSystemTime、GetSystemTimeAsFileTime、gettimeofday等,对应有日期时间的结构也很多,如:

 

typedef struct_SYSTEMTIME {

    WORDwYear;

    WORDwMonth;

    WORDwDayOfWeek;

    WORDwDay;

    WORDwHour;

    WORDwMinute;

    WORDwSecond;

    WORDwMilliseconds;

} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;

 

 

typedef struct_FILETIME {

    DWORD dwLowDateTime;

    DWORD dwHighDateTime;

} FILETIME, *PFILETIME, *LPFILETIME;

 

struct timeval{

        long    tv_sec;        /*seconds */

        long    tv_usec;       /* andmicroseconds */

};

 

struct tm{

        inttm_sec;    /*seconds after the minute - [0,59] */

        inttm_min;    /*minutes after the hour - [0,59] */

        inttm_hour;   /* hourssince midnight - [0,23] */

        inttm_mday;   /* dayof the month - [1,31] */

        inttm_mon;    /*months since January - [0,11] */

        inttm_year;   /* yearssince 1900 */

        inttm_wday;   /* dayssince Sunday - [0,6] */

        inttm_yday;   /* dayssince January 1 - [0,365] */

        inttm_isdst;  /*daylight savings time flag */

        };

 

这些时间表示都有一个特点,他们都是绝对时间或相对于某个固定基点(如1970.1.1或1600.1.1)开始的某个精度表示,系统还提供了一些相对于os启动时刻的tickcount表示,如GetTickCount、GetTickCount64等,这些函数主要用在时间间隔测量上,由于GetTickCount有47.9天回绕问题,但GetTickCount64又是vista只后才增加的函数,所以并不是太通用,虽然也有人想出了一些对付回绕的办法,但如果发生两次回绕则计算还是会出错,而且这个tickcount函数和绝对时间没有换算关系,由于参照物为os启动时间,因此这个tickcount在两台不同的机器上无法进行相对运算。

 

综上描述,时间类函数主要有三类,一类是绝对时间的,一类是相对某个固定时间(如1970.1.1或1600.1.1)的,还有相对于机器启动时间的tickcount系列,现有函数缺陷主要有两个,time_t系列精度不够,tickcount系列参照物不具有可比性,因此现有时间系列函数很不易用,实际上我们可以充分利用uint64_t的表示范围,定义一个绝对或相对于某个时间起始的时间类型,如:

typedef uint64_t millitime_t;           精度为毫秒(可标识584942417年)

typedef uint64_t microtime_t;        精度为微妙(可标识584942年)

typedef uint64_t bnanotime_t;       精度为100纳秒(可标识58494年)

它的差值即为其精度表示的间隔数,如果他们也是相对于1970.1.1基点,那么它和传统的秒表示的time_t很容易换算,如millitime_t/1000即为time_t,millitime_t%1000即为毫秒,传输也很方便,只占用8个字节,要测量时间间隔精度也满足要求,在可预测时间内也不会发生回绕,可用性易用性都满足要求,在win下有一个函数基本满足这个要求,GetSystemTimeAsFileTime这个函数返回的是从1600.1.1开始的100纳秒数,但这个函数取名不是太好,导致很多人根本不知道有这个函数可用,在linux下通过gettimeofday也很容易包装出这个函数,如果要取其他精度的函数也可根据这个函数进行一些简单运算获得。

通过使用这种新方式标识的时间,使得以前描述一个任务既要记录绝对时间SYSTEMTIME,又要记录tickcount就变成只需要记录一个时间即可,而且这个时间在不同机器上也可以基本度量tickcount,避免了原来tick由于相对参照不同带来的问题,简化了设计和实现。