每天进步一点点——Linux系统中的时间处理
转载请说明出处:http://blog.csdn.net/cywosp/article/details/25839551
- 真实时间:程序运行的时间,即程序启动到程序消亡所用时间或程序运行到现在所经过的时间
- 进程时间:一个进程所使用的CPU时间总量,适用于对程序、算法性能的检查或优化
在32位Linux系统中,time_t是一个有符号整数,可以表示的日期范围从1901年12月13日20时45分52秒至2038年1月19日03:14:07。因此,32位系统的机器都将面临2038年的问题,当然这我们不必担心,到了2038年,我相信这些系统早已升级为64位或者更多位的系统了。不过有些寿命更长的嵌入式设备,可能还会受到此问题的影响。
#include <sys/time.h>
// Return 0 on success, or -1 on errorint gettimeofday (struct timeval* tv, struct timezone* tz);
tv所指向的结构体如下struct timeval {time_t tv_sec; /* Seconds since 00:00:00, 1 Jan 1970 UTC*/susecond_t tv_usec; /* Additional microseconds (long int)*/};gettimeofday()函数提供到微秒级的精度并存储于tv_usec中,这样的精度对大多数程序来说已经能够满足。在x86-64平台上,gettimeofday()不是系统调用,而是在用户态实现的,没有上下文切换和陷入内核的开销,因此其速度是比较快的[1]。参数tz是一个历史产物,在早期的UNIX系统实现中使用其来获取系统的时区信息,目前已被废弃,因此在调用时始终置为NULL。
#include <time.h>
// Returns number of seconds since the Epoch, or (time_t)-1 on errortime_t time (time_t* timep);
如果timep参数不为NULL,那么还会将自Epoch以来的的秒数置于timep所指向的位置中。但是在日常使用中我们都采用简单的调用方式t = time (NULL)。从函数说明上可以得知gettimeofday()的精确度要比time()要高。
#include <time.h>
// Returns pointer to statically allocated string terminated by newline and \0 on success, or NULL on errorchar* ctime (const time_t* timep);
把一个指向time_t的指针作为timep参数传入函数,将返回一个长达26个字节的字符串,内含标准格式的日期和时间,如下:Wed May 14 15:22:34 2014该字符串包含换行符合终止空字节各一。ctime()函数在进行行转换时会自动对本地时区和DST设置加以考虑。返回的字符串经由静态分配的,因此无需调用free函数,正因如此,该函数是不可重入的(非线程安全的),线程安全的版为ctime_r()。
struct tm {int tm_sec; /*Seconds (0-60)*/int tm_min; /*Minites (0-59)*/int tm_hour; /*Hours (0-23)*/int tm_mday; /*Day of the month (1-31)*/int tm_mon; /*Month (1-12)*/int tm_year; /*Year since 1900*/int tm_wday; /*Day of the week (Sunday = 0)*/int tm_yday; /*Day in the year (0-365; 1 Jan = 0)*/int tm_isdst; /*Daylight saving time flag > 0: DST is in effect; = 0: DST is not effect; < 0: DST information not available*/
};结构体tm将日期和时间分解成多个独立的字段,这样能方便程序获取不同的字段值来处理。字段tm_sec的上限为60而不是59,这样的设计主要是考虑闰秒,偶尔用其将人类日历调整至精确的天文年(所谓的回归年)。如果程序中定义了_BSD_SOURCE测试宏,那么有glibc定义的tm结构还会包括两个字段,一个为long int tm_gmtoff,用于表示时间超出UTC以东的秒数,一个为const char* tm_zone,用于表示时区的缩写(例如:CEST为欧洲中部夏令时间)。
gmtime()和localtime()两个函数可将time_t转换成struct tm。gmtime()直接将time_t分解成UTC时间的tm,localtime()需要考虑时区和夏令时的设置,具体声明如下:#include <time.h>
// Both return a pointer to a statically allocated broker-down time structure on success, or NULL on errorstruct tm* gmtime (const time_t *timep);struct tm* localtime (const time_t *timep);以上两个函数都是非线程安全的,线程安全版本为gmtime_r()和localtime_r()
mktime()函数可以将struct tm转换成time_t,其声明如下:#include <time.h>
// Returns seconds since the Epoch corresponding to timeptr on success, or (time_t)-1 on errortime_t mktime (struct tm *timeptr);该函数可能会修改timeptr对应的值,至少会确保对tm_wday和tm_yday字段的设置,确保这些字段与其他字段能够相互对应起来。同时,mktime()在进行转换时会对时区进行设置。此外,DST设置的使用与否取决于输入字段tm_isdst的值。
- 若tm_isdst为0,则将这一时间视为标准时间(即,忽略夏令时)
- 若tm_isdst大于0,则将这一时间视为夏令时
- 若tm_isdst小于0,则试图判定DST在每年的这一时间是否生效。这往往是众望所归的设置
#include <time.h>
// Returns pointer to statically allocated string terminated by newline and \0 on success, or NULL on errorchar* asctime (const struct tm *timeptr);
与ctime()相比,本地时区的设置对asctime()没有影响。其返回的指针所指向的是由静态分配的字符串,因此其不是线程安全的,线程安全的版本为asctime_r(),输出结果大概如下:Wed May 14 16:43:21 CET 2014
asctime()函数返回的是一个固定形式的字符串,有时为了更易于理解,程序不想仅局限于这样的字符串,于是Linux中提供了strftime()函数,声明如下:#include <time.h>
// Returns number of bytes placed in outstr (excluding terminating null bytes) on success, or 0 on errorsize_t strftime (char *outstr, size_t maxsize, const char *format, const struct tm *timeptr);
outstr中返回的字符串按照format参数定义的格式做了格式化,maxsize则是ourstr的最大长度,如果成功则将格式化后的内容写入outstr所指向的缓冲区中,然后返回字符串的真实长度,含终止空字节,如果真实长度超过了maxsize参数的大小,那么返回0以表示出错,且无法确定outstr的内容。参数format是一个字符串,类似于printf()参数。具体值在此不做详解,可以google。
strptime()函数与strftime()函数正好相反,其可以将包含日期和时间的字符串转换成struct tm,声明如下:#define _XOPEN_SOURCE#include <time.h>
// Returns pointer to next unprocessed character in str on success, or NULL on errorchar* strptime (const char *str, const char *format, struct tm *timeptr);
函数strptime()按照format参数内容对由日期和时间组成的字符串str加以解析,并将转换后的数值存储于timeptr所指的缓存中,如果成功,返回指向str中下一个还未解析过的字符,如果所给的str无法和format相对应,则会解析失败,返回NULL,以示错误。最后还需注意,strptime()函数不会设置tm中的tm_isdst字段。
时区文件格式记叙于tzfile(5)手册页,其创建可通过zic(8)(时区信息编译器,zone information compiler)工具来完成。zdump(8)命令可根据指定时区文件中的时区来显示当前时间
char *tzname[2]; /*Name of timezone and alternate (DST) timezone*/int daylight; /*Nonzero if there is an alternate (DST) timezone*/long timezone; /*Seconds difference between UTC and local standard time*/
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。