日期和时间在我们编程中经常使用,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,&nbsp;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