0%

C语言 time函数学习

linux中关于time.h的函数

对time.h中的若干个获取时间以及时间转换的函数困惑了有一段时间了,每次操作都要man一下,查看一下具体含义,今天把这些总结一下,算是了了一桩心事。

关系图为(其实搞定这个图也就OK了):

time.h是C标准函数库中获取时间与日期、对时间与日期数据操作及格式化的头文件。

表示时间的三种数据类型

  1. 日历时间(calendar time),是从一个标准时间点(epoch)到现在的时间经过的秒数,不包括插入闰秒对时间的调整。开始计时的标准时间点,各种编译器一般使用1970年1月1日0时0秒。日历时间用数据类型time_t表示。time_t类型实际上一般是32位或64位整数类型;
  2. 时钟滴答数(clock tick),从进程启动开始计时,因此这是相对时间。每秒钟包含CLOCKS_PER_SECtime.h中定义的常量,一般为1000)个时钟滴答。时钟滴答数用数据类型clock_t表示。clock_t类型一般是32位整数类型;
  3. 分解时间(broken-down time),用结构数据类型tm表示,tm包含下列结构成员:
成员 描述
int tm_hour hour (0 – 23)
int tm_isdst 夏令时 enabled (> 0), disabled (= 0), or unknown (< 0)
int tm_mday day of the month (1 – 31)
int tm_min minutes (0 – 59)
int tm_mon month (0 – 11, 0 = January)
int tm_sec seconds (0 – 60, 60 = Leap second)
int tm_wday day of the week (0 – 6, 0 = Sunday)
int tm_yday day of the year (0 – 365)
int tm_year year since 1900

从计算机系统时钟获得时间的方法

  • time_t time(time_t* timer):得到从标准计时点(一般是1970年1月1日午夜)到当前时间的秒数
  • clock_t clock(void):得到从进程启动到此次函数调用的累计的时钟滴答数。

三种时间日期数据类型的转换函数

1
2
struct
tm* gmtime(const time_t* timer)

从日历时间time_t到分解时间tm的转换。函数返回的是一个静态分配的tm结构存储空间,该存储空间被gmtime, localtimectime函数所共用. 这些函数的每一次调用会覆盖这块tm结构存储空间的内容。

1
2
struct
tm* gmtime_r(const time_t* timer, struct tm* result)

该函数是gmtime函数的线程安全版本.

1
2
struct
tm* localtime(const time_t* timer)

从日历时间time_t到分解时间tm的转换,即结果数据已经调整到本地时区与夏令时。

1
2
time_t
mktime(struct tm* ptm)

从分解时间tm到日历时间time_t的转换。

1
2
time_t
timegm(struct tm* brokentime)

从分解时间tm(被视作UTC时间,不考虑本地时区设置)到日历时间time_t的转换。该函数较少被使用。

时间日期数据的格式化函数

1
char *asctime(const struct tm* tmptr)

把分解时间tm输出到字符串,结果的格式为“Www Mmm dd hh:mm:ss yyyy”,即“周几月份数日数小时数:分钟数:秒钟数年份数”。函数返回的字符串为静态分配,长度不大于26,与ctime函数共用。函数的每次调用将覆盖该字符串内容。

1
2
char*
ctime(const time_t* timer)

把日历时间time_t timer输出到字符串,输出格式与asctime函数一样.

1
2
3
size_t
strftime(char* s, size_t n, const char* format, const struct tm*
tptr)

把分解时间tm转换为自定义格式的字符串,类似于常见的字符串格式输出函数sprintf

1
2
3
char *
strptime(const char* buf, const char* format, struct tm*
tptr)

strftime的逆操作,把字符串按照自定义的格式转换为分解时间tm

对时间数据的操作

1
2
double
difftime(time_t timer2, time_t timer1)

比较两个日历时间之差。

time – get the Coordinated Universal Time seconds from 1970.1.1

1
2
time_t
time(time_t* timer)

获取当前的系统时间,返回的结果是一个time_t类型,其实就是一个大整数,其值表示从CUT(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到当前时刻的秒数。然后调用localtimetime_t所表示的CUT时间转换为本地时间(我们是+8区,比CUT多8个小时)并转成struct tm类型,该类型的各数据成员分别表示年月日时分秒。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <time.h>

int main(void)

{

time_t timer = time(NULL);

printf(“The number of seconds since January 1, 1970 is %ld\n”, timer);

return 0;

}

gettimeofday – get time

获得当前精确时间(UNIX到现在的时间)。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<stdio.h>
#include<sys/time.h>

#include<unistd.h>

int main()

{

struct timeval tv;

struct timezone tz;

gettimeofday(&tv, &tz);

printf(“tv_sec:%ld\n”, tv.tv_sec);

printf(“tv_usec:%ld\n”, tv.tv_usec);

printf(“tz_minuteswest:%d\n”, tz.tz_minuteswest);

printf(“tz_dsttime:%d\n”, tz.tz_dsttime);

return 0;

}

localtime – converts the calendar time timep to broken-down time representation, expressed relative to the user’s specified timezone.

1
2
3
4
struct tm *localtime(const time_t
*timep);
struct tm *localtime_r(const time_t *timep, struct tm
*result);

功能: 把从1970-1-1零点零分到当前时间系统所偏移的秒数时间转换为日历时间。
说明:此函数获得的tm结构体的时间,是 已经进行过时区转化为本地时间
返回值:返回指向tm 结构体的指针.tm结构体是time.h中定义的用于分别存储时间的各个量(年月日等)的结构体.

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<time.h>
#include<stdio.h>

int main()

{

struct tm *t;

time_t timer;

time(&timer);

t = localtime(&timer);

printf(“%4d year%02d month%02d day %02d:%02d:%02d\n”, t->tm_year + 1900,

t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min,

t->tm_sec);

return 0;

}

// 注意年份上要加上1900。

asctime – converts the broken-down time value tm into a null-terminated string with the same format as ctime()

1
2
3
4
char *asctime(const struct tm
*tm);
char *asctime_r(const struct tm *tm, char
*buf);

功能: 转换日期和时间为相应的ASCII码,返回字符串格式:星期,月,日,小时,分,秒,年与此类似ctime是将相应时间转换为字符串格式。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <string.h>

#include <time.h>

int main(void)

{

struct tm t;

char str[80];

/* sample loading of tm structure */

t.tm_sec = 1; /* Seconds */

t.tm_min = 30; /* Minutes */

t.tm_hour = 9; /* Hour */

t.tm_mday = 22; /* Day of the Month */

t.tm_mon = 11; /* Month */

t.tm_year = 12; /* Year – does not include century */

t.tm_wday = 4; /* Day of the week */

t.tm_yday = 0; /* Does not show in asctime */

t.tm_isdst = 0; /* Is Daylight SavTime; does not show in asctime */

/* converts structure to null terminated string */

strcpy(str, asctime(&t));

printf(“%s\n”, str);

return 0;

}

ctime – converts the calendar time t into a null-terminated string of the form

1
2
3
4
char
*ctime(const time_t *timep);
char
*ctime_r(const time_t *timep, char *buf);

功能:把time_t描述转换为字符串

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <time.h>

int main(void)

{

time_t timer = time(NULL);

printf(“Today’s data and time is %s\n”, ctime(&timer));

return 0;

}

gmtime – converts the calendar time timep to broken-down time representation, expressed in Coordinated Universal Time (UTC)

1
2
3
4
struct tm *gmtime(const time_t
*timep);
struct tm *gmtime_r(const time_t *timep, struct tm
*result);

功能:把日期和时间转换为格林威治(GMT)时间的函数。将参数timep 所指的time_t 结构中的信息转换成真实世界所使用的时间日期表示方法,然后将结果由结构tm返回,获取的时间未经过时区转换。与localtime唯一的区别就是相差了时区,比如对于中国而言,只有小时上相差了8个小时。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<time.h>
#include<stdio.h>

int main()

{

struct tm *t;

time_t timer;

time(&timer);

t = localtime(&timer);

printf(“%4d year%02d month%02d day %02d:%02d:%02d\n”, t->tm_year + 1900,

t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min,

t->tm_sec);

return 0;

}

timegm – inverses of gmtime

1
2
3
#include <time.h>
time_t timegm(struct tm
*tm);

将struct tm结构转成time_t结构,不使用时区信息

mktime – converts a broken-down time structure, expressed as local time, to calendar time representation.

1
time_t mktime(struct tm *tm);

功能:将时间转换为自1970年1月1日以来失去时间的秒数,发生错误是返回-1.

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <time.h>

int main(void)

{

time_t timep;

struct tm *p;

time(&timep);

printf(“time() : %ld \n”, timep);

p = localtime(&timep);

timep = mktime(p);

printf(“time()->localtime()->mktime():%ld\n”, timep);

return 0;

}

timelocal – inverses of localtime

1
2
time_t
timelocal(struct tm *tm);

timelocal 函数是GNU扩展的与posix函数mktime相当

strftime – format date and time

1
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);

函数功能:将时间格式化为一个我们想要的格式,或者说:格式化一个时间字符串。
参数说明:我们可以根据format指向字符串中格式命令把timeptr中保存的时间信息放在strDest指向的字符串中,最多向strDest中存放maxsize个字符。该函数返回向strDest指向的字符串中放置的字符数。
函数strftime()的操作有些类似于sprintf():识别以百分号(%)开始的格式命令集合,格式化输出结果放在一个字符串中。格式化命令说明串strDest中各种日期和时间信息的确切表示方法。格式串中的其他字符原样放进串中。格式命令列在下面,它们是区分大小写的。

格式化 解释
%a 星期几的简写
%A 星期几的全称
%b 月份的简写
%B 月份的全称
%c 标准的日期的时间串
%C 年份的后两位数字
%d 十进制表示的每月的第几天
%D 月/天/年
%e 在两字符域中,十进制表示的每月的第几天
%F 年–月–日
%g 年份的后两位数字,使用基于周的年
%G 年份,使用基于周的年
%h 简写的月份名
%H 24小时制的小时
%I 12小时制的小时
%j 十进制表示的每年的第几天
%m 十进制表示的月份
%M 十时制表示的分钟数
%p 本地的AM或PM的等价显示
%n 新行符
%r 12小时的时间
%R 显示小时和分钟:hh:mm
%S 十进制的秒数
%t 水平制表符
%T 显示时分秒:hh:mm:ss
%U 第年的第几周,把星期日作为第一天(值从0到53)
%u 每周的第几天,星期一为第一天(值从0到6,星期一为0)
%V 每年的第几周,使用基于周的年
%w 十进制表示的星期几(值从0到6,星期天为0)
%W 每年的第几周,把星期一做为第一天(值从0到53)
%x 标准的日期串
%X 标准的时间串
%y 不带世纪的十进制年份(值从0到99)
%Y 带世纪部分的十制年份
%z %Z 时区名称,如果不能得到时区名称则返回空字符。
%% 百分号

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
#include<time.h>

int main(void)

{

struct tm *newtime;

char tmpbuf[1280];

time_t lt1;

time(&lt1);

newtime = localtime(&lt1);

strftime(tmpbuf, 1280,“Today is\t %A – %a\nMonth is\t %B – %b\nDate is \t%c\nyear- month-day is\t %F\nhour %H\n Time is\t %T\nday %d of %B in the year %Y.\n”, newtime);

printf(“%s\n”, tmpbuf);

return 0;

}

strptime – convert a string representation of time to a time tm structure

1
char *strptime(const char *s, const char *format, struct tm *tm);

功能:按照特定时间格式将字符串转换为时间类型,与上面说的strftime刚好相反。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <time.h>

#include <stdlib.h>

int main(void)

{

char fmt[] = “%Y-%m-%d-%H:%M:%S”;

char buf[] = “2000-01-01-00:00:00”;

struct tm tb;

if (strptime(buf, fmt, &tb) != NULL) {

fprintf(stdout,“ok”);

printf(“\nTime is %s\n”, asctime(&tb));

}

return 0;

}

tzset – function initializes the tzname variable from the TZ environment variable

功能:设置时间环境变量
说明:tzset()函数使用环境变量TZ的当前设置把值赋给三个全局变量:daylight,timezone和tzname。
示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <time.h>

#include <stdlib.h>

int main(void)

{

time_t td;

putenv(“TZ=PST8PDT”);

tzset();

time(&td);

printf(“Current time = %s\n”, asctime(localtime(&td)));

return 0;

}

关于time_t类型

通过查看宏定义,我们知道time_t实际上是长整型,到未来的某一天,从一个时间点(一般是1970年1月1日0时0分0秒)到那时的秒数(即日历时间)超出了长整形所能表示的数的范围怎么办?对time_t数据类型的值来说,它所表示的时间不能晚于2038年1月18日19时14分07秒。为了能够表示更久远的时间,一些编译器厂商引入了64位甚至更长的整形数来保存日历时间。比如微软在Visual C++中采用了__time64_t数据类型来保存日历时间,并通过_time64()函数来获得日历时间(而不是通过使用32位字的time()函数),这样就可以通过该数据类型保存3001年1月1日0时0分0秒(不包括该时间点)之前的时间。
clock – Determine processor time

1
2
clock_t
clock(void);

功能: 返回处理器调用某个进程或函数所花费的时间。
示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <time.h>

#include <unistd.h>

int main(void)

{

int i = 0;

clock_t start, end;

start = clock();

while (i < 10000000)

i++;

end = clock();

printf(“The time was: %f\n”,

(double) (end – start) / CLOCKS_PER_SEC);

return 0;

}

注意,在测试进程消耗时间的时候,不要使用sleep,因为sleep不使用CPU时间。
difftime – calculate time difference

1
2
double
difftime(time_t time1, time_t time0);

功 能:返回两个time_t型变量之间的时间间隔,即计算两个时刻之间的时间差
示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <time.h>
#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

int main(void)

{

time_t first, second;

system(“clear”);

first = time(NULL);

sleep(2);

second = time(NULL);

printf(“The difference is: %f seconds\n”, difftime(second, first));

return 0;

}
处无为之事,行不言之教;作而弗始,生而弗有,为而弗恃,功成不居!

欢迎关注我的其它发布渠道