Unix内核通过计算从1970年1月1日0点0分0秒纪元(UTC)开始经过的秒数来提供的基本时间和日期服务。在用户层,
这个值是以time_t(在Unix中以t结尾的数据类型被称作基本系统数据类型,int的定义类型)数据类型标识的,
一般被称作日历时间(calendar time),并通过函数time获得当前的值。
time函数原型:
- #include <time.h>
- time_t time(time_t *timeptr);
如果参数timeptr不为NULL的话则返回值也保存在它所指向的内存空间中。发生错误的话返回-1。
当获取这个值后,就可以通过调用其他函数来将它转换成可读的日期和时间,它们之间的关系如下图(来自Unix高级环境编程):
struct tm结构为:
- struct tm {
- int tm_sec; // 秒 [0 - 60]
- 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; // 夏令时标志 <0不可用, 0非夏令时, >0为夏令时
- };
localtime、gmtime和mktime的函数原型
- #include <time.h>
- struct tm *gmtime(const time_t *calptr);
- struct tm *localtime(const time_t *calptr);
- time_t mktime(struct tm *tmptr);
localtime函数将日历时间转换成本地时间而购买time则转换为UTC时间,mktime则将本地时间转换为日历时间。
函数ctime和actime分别以time_t和struct tm的指针数据类型为参数,返回可读性很好的时间表示字符串,函数原型为
- #include <time.h>
- char *asctime(const struct tm *tmptr);
- char *ctime(const time_t *calptr);
strftime函数类似于snprintf函数,但它是专用于存储转换时间和日期的,并定义有特定的format,函数原型:
- #include <time.h>
- size_t strftime(char *restrict buf, size_t maxsize, const char *restrict format, const struct tm *restrict tmptr);
前3个参数和snprintf函数相同,第四个参数为struct tm结构体(通常由time函数获得),具体的format可以通过manpage 3获得。
上述的所有函数只能提供秒级的精度,如果想获得更高的精度,则可以使用函数gettimeofday(微秒级精度)和clock_gettime函数(纳秒级精度)。
不过它们都是基于单独的Unix规范和POSIX规范的。
gettimeofday函数原型和相关数据结构
- #include <sys/time.h>
- int gettimeofday(struct timeval *restrict tp, void *restrict tzp);
-
- struct timeval {
- time_t tv_sec; // 秒
- long tv_usec; // 微秒
- };
参数tzp在目前单独Unix规范中只能是NULL。
clock_gettime函数:
- #include <time.h>
- int clock_gettime(clockid_t clk_id, struct timespec *tp);
-
- struct timespec {
- time_t tv_sec; // 秒
- long tv_nsec; // 纳秒
- };
参数clk_id标识特定的时钟(系统时钟,进程特定时钟,线程特定时钟等),系统时钟所有进程可见。
根据系统实现(硬件软件)的不同,获得的精度可能也是不同的,可以通过函数clock_getres获得特定系统的精度,
而函数clock_settime则可以设定时钟,具体可从manpage 3获取。
将clk_id置为CLOCK_REALTIME则可以获得当前具体时间(从纪元开始)。