日期和时间在我们编程中经常使用,ANSI C中和日期与时间相关的头文件是<time.h>。本文介绍该头文件中定义的类型与时间函数。
<time.h>中定义了两个宏(注意是宏,不是类型):第一个是表示空指针的NULL ;第二个宏是CLOCKS_PER_SEC :用这个宏去除clock( )的返回值将产生以秒为单位的时间值。需要注意的是,有的宏或者类型时间并没有在time.h中定义,time.h只是引用了其他地方的定义,比如宏NULL、size_t类型一般定义在<stddef.h>中,time.h只是包含了一下这个头文件而已。
1. 时间类型
- size_t :一个无符号整数类型,表示一个sizeof运算符的结果。其实这个类型和宏NULL一般都是定义在头文件<stddef.h>中。
- clock_t :一般是long型,表示时间的算术类型。
- time_t :一般是long型,表示时间的算术类型。
- struct tm :用于保存组成日历时间各个部分的结构类型。所谓的日历时间(calendar time)指从一个标准时间点到此时的时间经过的秒数,一般日历时间指从1900年1月1日的第1秒(即UTC:1970-01-01 00:00:00 +0000 )至今所经过的秒数;而本地时间(local time)是指本地时区的日历时间。struct tm结构如下:
struct tm { int tm_sec; /* Seconds. [0-60] (1 leap second) */ int tm_min; /* Minutes. [0-59] */ int tm_hour; /* Hours. [0-23] */ int tm_mday; /* Day. [1-31] */ int tm_mon; /* Month. [0-11] */ int tm_year; /* Year - 1900. 1900后的年数 */ int tm_wday; /* Day of week. [0-6] */ int tm_yday; /* Days in year.[0-365] */ int tm_isdst; /* DST. [-1/0/1]*/ }
tm_year表示1900后的年数,而不是1970后的年数。
最后一个成员tm_isdst是夏令时标识:大于0的值说明夏令时有效,0说明无效,负数说明信息不可用。
日历的各个组成部分被称为分解时间(broken-down time)。
2. 时间函数
2.1 clock
函数原型:
clock_t clock(void);
函数功能:返回自从调用程序以来经过的处理器时间的最近近似;除以CLOCKS_PER_SEC可以得到以秒计算的时间;如果时间不可用或者不能表示返回-1.
2.2 difftime
函数原型:
double difftime(time_t time1, time_t time0);
函数功能:计算两个日历时间的差值(time1-time0)。
2.3 mktime
函数原型:
time_t mktime(struct tm *tm);
函数功能:把tm指向的结构中的分解时间转换为日历时间,使用与time( )函数相同的编码,结构会被改变,以便对结构中超出范围的值进行调整(例如2分100秒会变为3分40秒),并且tm_wday和tm_yday成员被设置为根据其他成员确定的值。如果日历时间不可表示返回-1,否则以time_t格式返回日历时间。
2.4 time
函数原型:
time_t time(time_t *tloc);
函数功能:该函数返回从UTC时间到现在所经历的秒数。如果tloc不为空,则返回值同时也会存储在tloc所指向的位置,如果为NULL,则不存储。
2.5 asctime
函数原型:
char *asctime(const struct tm *tm); char *asctime_r(const struct tm *tm, char *buf);
函数功能:asctime把tm指向的结构中的分解时间转换为如下格式的字符串:Thu Feb 26 13:14:33 1998n,并返回指向该字符串的指针。asctime_r则会将返回的字符串存储在buf中,这个buf至少要能容纳26个字节的数据。
2.6 ctime
函数原型:
char *ctime(const time_t *timep); char *ctime_r(const time_t *timep, char *buf);
函数功能:和asctime函数类似,不过ctime是将time_t格式的日历时间转换为如下格式的字符串:Thu Feb 26 13:14:33 1998n,并返回指向该字符串的指针。ctime_r则会将返回的字符串存储在buf中,这个buf至少要能容纳26个字节的数据。
ctime(t)等价于asctime(localtime(t)).
2.7 gmtime
函数原型:
struct tm *gmtime(const time_t *timep); struct tm *gmtime_r(const time_t *timep, struct tm *result);
函数功能:把timep指向的日历时间转换为用UTC(Universal Coordinated Time,国际标准时间;更正规的名字叫格林威治时间,Greenwich Mean Time, GMT)表示的分解时间,并返回指向保存该信息的结构的指针;如果UTC时间不可用(比如年不是一个整数),则返回NULL。gmtime_r会同时将返回值保存在result指向的地址中。
2.8 localtime
函数原型:
struct tm *localtime(const time_t *timep); struct tm *localtime_r(const time_t *timep, struct tm *result);
函数功能:和gmtime不同的是,localtime函数会将timep指向的日历时间转换为用本地时间表示的分解时间,而不是用UTC表示的分解时间。并返回指向保存该信息的结构的指针。localtime_r会同时将返回值保存在result指向的地址中。
2.9 strftime
函数原型:
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
函数功能:把字符串format复制到字符串s中,使用tm指向的结构中的分解时间得出适当的数据来替换format中的格式说明符;最多有max个字符被放入s中;函数返回放入s的字符数(不包含字符串结束符)。如果结果字符串(包含结束符)中超过了max个字符,那么函数返回0,且s中的内容是未定义的。需要注意的是,函数返回0,并不代表函数执行出错。比如,在很多场景中,%p将会产生一个空字符串,或者format如果是一个空字符串,同样也会产生空字符串,此时返回值也是0.
strftime函数支持的格式说明符如下:
- %a 星期几的简写
- %A 星期几的全称
- %b 月份的简写
- %B 月份的全称
- %c 标准的日期的时间串
- %C 年份的前两位数字
- %d 十进制表示的每月的第几天
- %D 月/天/年
- %e 在两字符域中,十进制表示的每月的第几天
- %F 年-月-日
- %g 年份的后两位数字,使用基于周的年
- %G 年份,使用基于周的年
- %h 简写的月份名
- %H 24小时制的小时
- %I 12小时制的小时
- %j 十进制表示的每年的第几天
- %m 十进制表示的月份
- %M 十时制表示的分钟数
- %n 新行符
- %p 本地的AM或PM的等价显示
- %r 12小时的时间
- %R 显示小时和分钟:hh:mm
- %S 十进制的秒数
- %t 水平制表符
- %T 显示时分秒:hh:mm:ss
- %u 每周的第几天,星期一为第一天 (值从1到7,星期一为1)
- %U 第年的第几周,把星期日作为第一天(值从0到53)
- %V 每年的第几周,使用基于周的年
- %w 十进制表示的星期几(值从0到6,星期天为0)
- %W 每年的第几周,把星期一做为第一天(值从0到53)
- %x 标准的日期串
- %X 标准的时间串
- %y 不带世纪的十进制年份(值从0到99)
- %Y 带世纪部分的十制年份
- %z,%Z 时区名称,如果不能得到时区名称则返回空字符
- %% 百分号
3. 程序实例
下面是包含上述介绍的所有函数的一个代码time.c:
#include <stdio.h> #include <stdlib.h> #include <time.h> int main() { puts("clock function:"); clock_t clk; clk = clock(); printf("clk:%ldnCLOCKS_PER_SEC/clk:%ldnn", clk, CLOCKS_PER_SEC/clk); puts("mktime function:"); time_t tmt; struct tm *tmptr; tmptr = (struct tm*)malloc(sizeof(struct tm)); tmptr->tm_sec = 100; tmptr->tm_min = 2; tmptr->tm_hour = 12; tmptr->tm_mday = 4; tmptr->tm_mon = 3; tmptr->tm_year = 91; tmptr->tm_wday = 0; tmptr->tm_yday = 20; tmptr->tm_isdst = 1; tmt = mktime(tmptr); printf("tmptr structure:ntm_sec=%dntm_min=%dntm_hour=%dntm_mday=%dn tm_mon=%dntm_year=%dntm_wday=%dntm_yday=%dn tm_isdst=%dn", tmptr->tm_sec, tmptr->tm_min, tmptr->tm_hour, tmptr->tm_mday, tmptr->tm_mon, tmptr->tm_year, tmptr->tm_wday, tmptr->tm_yday, tmptr->tm_isdst); printf("tmt=%ldnn", tmt); puts("time function:"); time_t tmt1; tmt1 = time(NULL); printf("tm1=%ldnn", tmt1); puts("asctime function:"); char *ascptr = NULL, *ascptr_r = NULL; char buf[30] = {0}; ascptr = asctime(tmptr); ascptr_r = asctime_r(tmptr, buf); printf("ascptr: %sascptr_r: %sbuf: %sn", ascptr, ascptr_r, buf); puts("ctime function:"); char *cptr = NULL, *cptr_r = NULL; char buf1[30] = {0}; cptr = ctime(&tmt); cptr_r = ctime_r(&tmt, buf1); printf("cptr: %scptr_r: %sbuf1: %sn", cptr, cptr_r, buf1); puts("gmtime function:"); struct tm *tmptr1 = NULL, *tmptr2 = NULL; struct tm tm1; tmptr1 = gmtime(&tmt); tmptr2 = gmtime_r(&tmt, &tm1); printf("tmptr1 structure:ntm_sec=%dntm_min=%dntm_hour=%dntm_mday=%dn tm_mon=%dntm_year=%dntm_wday=%dntm_yday=%dn tm_isdst=%dn", tmptr1->tm_sec, tmptr1->tm_min, tmptr1->tm_hour, tmptr1->tm_mday, tmptr1->tm_mon, tmptr1->tm_year, tmptr1->tm_wday, tmptr1->tm_yday, tmptr1->tm_isdst); printf("tmptr2 structure:ntm_sec=%dntm_min=%dntm_hour=%dntm_mday=%dn tm_mon=%dntm_year=%dntm_wday=%dntm_yday=%dn tm_isdst=%dn", tmptr2->tm_sec, tmptr2->tm_min, tmptr2->tm_hour, tmptr2->tm_mday, tmptr2->tm_mon, tmptr2->tm_year, tmptr2->tm_wday, tmptr2->tm_yday, tmptr2->tm_isdst); printf("tm1 structure:ntm_sec=%dntm_min=%dntm_hour=%dntm_mday=%dn tm_mon=%dntm_year=%dntm_wday=%dntm_yday=%dn tm_isdst=%dnn", tm1.tm_sec, tm1.tm_min, tm1.tm_hour, tm1.tm_mday, tm1.tm_mon, tm1.tm_year, tm1.tm_wday, tm1.tm_yday, tm1.tm_isdst); puts("localtime function:"); struct tm *tmptr3 = NULL, *tmptr4 = NULL; struct tm tm2; tmptr3 = localtime(&tmt); tmptr4 = localtime_r(&tmt, &tm2); printf("tmptr3 structure:ntm_sec=%dntm_min=%dntm_hour=%dntm_mday=%dn tm_mon=%dntm_year=%dntm_wday=%dntm_yday=%dn tm_isdst=%dn", tmptr3->tm_sec, tmptr3->tm_min, tmptr3->tm_hour, tmptr3->tm_mday, tmptr3->tm_mon, tmptr3->tm_year, tmptr3->tm_wday, tmptr3->tm_yday, tmptr3->tm_isdst); printf("tmptr4 structure:ntm_sec=%dntm_min=%dntm_hour=%dntm_mday=%dn tm_mon=%dntm_year=%dntm_wday=%dntm_yday=%dn tm_isdst=%dn", tmptr4->tm_sec, tmptr4->tm_min, tmptr4->tm_hour, tmptr4->tm_mday, tmptr4->tm_mon, tmptr4->tm_year, tmptr4->tm_wday, tmptr4->tm_yday, tmptr4->tm_isdst); printf("tm2 structure:ntm_sec=%dntm_min=%dntm_hour=%dntm_mday=%dn tm_mon=%dntm_year=%dntm_wday=%dntm_yday=%dn tm_isdst=%dnn", tm2.tm_sec, tm2.tm_min, tm2.tm_hour, tm2.tm_mday, tm2.tm_mon, tm2.tm_year, tm2.tm_wday, tm2.tm_yday, tm2.tm_isdst); puts("strftime function:"); char s[100] = {0}; size_t status; status = strftime(s, sizeof(s), "Data:n%Y-%m-%dnTime:n%I:%M:%Sn", tmptr4); printf("status=%ldns:n %s", status, s); return 0; }
编译后运行结果如下:
clock function: clk:1834 CLOCKS_PER_SEC/clk:545 mktime function: tmptr structure: tm_sec=40 tm_min=3 tm_hour=11 tm_mday=4 tm_mon=3 tm_year=91 tm_wday=4 tm_yday=93 tm_isdst=0 tmt=670791820 time function: tm1=1425477360 asctime function: ascptr: Thu Apr 4 11:03:40 1991 ascptr_r: Thu Apr 4 11:03:40 1991 buf: Thu Apr 4 11:03:40 1991 ctime function: cptr: Thu Apr 4 11:03:40 1991 cptr_r: Thu Apr 4 11:03:40 1991 buf1: Thu Apr 4 11:03:40 1991 gmtime function: tmptr1 structure: tm_sec=40 tm_min=3 tm_hour=19 tm_mday=4 tm_mon=3 tm_year=91 tm_wday=4 tm_yday=93 tm_isdst=0 tmptr2 structure: tm_sec=40 tm_min=3 tm_hour=19 tm_mday=4 tm_mon=3 tm_year=91 tm_wday=4 tm_yday=93 tm_isdst=0 tm1 structure: tm_sec=40 tm_min=3 tm_hour=19 tm_mday=4 tm_mon=3 tm_year=91 tm_wday=4 tm_yday=93 tm_isdst=0 localtime function: tmptr3 structure: tm_sec=40 tm_min=3 tm_hour=11 tm_mday=4 tm_mon=3 tm_year=91 tm_wday=4 tm_yday=93 tm_isdst=0 tmptr4 structure: tm_sec=40 tm_min=3 tm_hour=11 tm_mday=4 tm_mon=3 tm_year=91 tm_wday=4 tm_yday=93 tm_isdst=0 tm2 structure: tm_sec=40 tm_min=3 tm_hour=11 tm_mday=4 tm_mon=3 tm_year=91 tm_wday=4 tm_yday=93 tm_isdst=0 strftime function: status=32 s: Data: 1991-04-04 Time: 11:03:40
评论已关闭