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

本文探讨了当前时间表示与计算的局限性,并提出了一种基于uint64_t的新时间表示方式,以提高精度和易用性。通过使用毫秒级、微妙级和纳秒级时间单位,新方式简化了时间操作并解决了不同机器间时间比较的问题。

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由于相对参照不同带来的问题,简化了设计和实现。

 

在C语言中,`time_t time( time_t * timer )` 函数是一个标准库函数,用于获取当前的日历时间。以下是关于该函数的详细解释: ### 函数作用 `time` 函数用于返回自 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)起经过的秒数,这个返回值的类型是 `time_t`。实际上 `time_t` 通常是长整型(long),它代表了从特定时间点到当前时刻所经过的秒数 [^1][^2]。 ### 函数参数 - `timer`:这是一个指向 `time_t` 类型对象的指针。如果该指针不为 `NULL`,函数会将返回的时间值存储在 `timer` 所指向的对象中。 ### 函数返回值 - 若函数执行成功,返回自 Unix 纪元起经过的秒数,类型为 `time_t`。 - 若函数执行失败,返回 `(time_t)(-1)`。 ### 示例代码 ```c #include <stdio.h> #include <time.h> int main() { time_t current_time; current_time = time(NULL); if (current_time != (time_t)(-1)) { printf("当前时间自 Unix 纪元起经过的秒数为: %ld\n", (long)current_time); } else { printf("获取时间失败\n"); } return 0; } ``` ### 代码解释 在上述代码中,首先定义了一个 `time_t` 类型的变量 `current_time`。然后调用 `time(NULL)` 函数获取当前时间,由于传递的参数是 `NULL`,函数不会将时间值存储到任何变量中,而是直接将结果返回给 `current_time`。最后根据返回值是否为 `(time_t)(-1)` 来判断函数是否执行成功,并输出相应的信息。 ### 局限性 由于 `time_t` 通常是长整型,它所能表示的时间范围存在一定限制。一般情况下,它所表示的时间不能晚于 2038 年 1 月 18 日 19 时 14 分 07 秒。为了表示更久远的时间,一些编译器厂商引入了 64 甚至更长的整形数来保存日历时间,例如微软在 Visual C++ 中采用了 `__time64_t` 数据类型,并通过 `_time64()` 函数来获得日历时间 [^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值