time时间类函数

1. struct tm time_t

(1) struct tm

struct tm {int tm_sec;			//秒, 0-59int tm_min;			//分, 0-59int tm_hour;		//时,0-23int tm_mday;		//一个月中的日期,1-31int tm_mon;			//月份,0-11,0代表一月int tm_year;		//年份,值等于实际年份减去1900int tm_wday;		//星期,0-6,0代表星期天,1代表星期1int tm_yday;		//从每年的1月1日开始的天数,0-365,0代表1月1日,1代表1月2日const char *tm_zone;	//当前时区的名字,与环境变量TZ有关...
};

(2) time_t

time.h

typdef __time_t time_t

bits/types.h

__STD_TYPE __TIME_T_TYPE __time_t
#define __STD_TYPE __extension__typedef

bits/typesizes.h

#define __TIME_T_TYPE  __SLONGWORD_TYPE

bits/types.h

#define __SLONGWORD_TYPE long int

所以,可以得出

__extension__typedef long int time_t

如果是32位机器,time_t占4字节,最大值为0x7fffffff.
如果是64位机器,time_t占8字节,最大值为0x7fffffffffffffff。
但这里实际上受到tm结构体中部分字段的限制,比如年份是32位整形,time_t过大,会导致年份输出有误。

一、time_t秒数转字符串时间

1. time函数

time_t time(time_t *seconds)
返回自纪元Epoch(1970-01-01 00:00:00 UTC)起经过的时间秒数
UTC时间也即是格林尼治标准时间GMT

2. gmtime gmtime_r localtime localtime_r

(1) gmtime 无时区转换

struct tm* gmtime(const time_t *timer)
将time_t秒数转为格林尼治当前时间struct tm

#define BST (+1)
#define CCT (+8)int main ()
{time_t rawtime;struct tm *info;time(&rawtime);/* 获取 GMT 时间 */info = gmtime(&rawtime);printf("当前的世界时钟:\n");printf("伦敦:%2d:%02d\n", (info->tm_hour+BST)%24, info->tm_min);printf("中国:%2d:%02d\n", (info->tm_hour+CCT)%24, info->tm_min);return(0);
}当前的世界时钟:
伦敦:14:10
中国:21:10

(2) localtime 有时区转换

struct tm* localtime(const time_t *timer)
将time_t秒数转为当地(带时区)当前时间struct tm

time得到的秒数,localtime转换后得到的tm_hour与gmtime转换的tm_hour多了时区值

(3) 最好使用gmtime_r localtime_r

struct tm *gmtime_r(const time_t *timep, struct tm *result);
struct tm *localtime_r(const time_t *timep, struct tm *result);gmtime_r与gmtime作用一样,localtime_r与localtime作用一样。
但gmtime_r localtime_r是线程安全的,最好使用这两个。
gmtime返回的是一个struct  tm*,这个指针指向一个静态的内存,这块区域是会经常被改动的。你刚调用gmtime(),执行了其他几条命令,然后想使用刚才gmtime()得到struct tm,会发现内容不对了,
所以很危险,使用gmtime_r后就没有问题,gmtime_r会将结果保存到你传入的内存中。

举个栗子:

int main(void)
{time_t timtmp, timep1, timep2;struct tm *p3, *p4;timtmp = time(NULL);printf("now time seconds:%ld\n", timtmp);p3 = gmtime(&timtmp);printf("p3->hour:%d\n", p3->tm_hour);p4 = localtime(&timtmp);printf("p4->hour:%d\n", p4->tm_hour);printf("p3->hour:%d\n", p3->tm_hour);printf("p4->hour:%d\n", p4->tm_hour);timep1=mktime(p3);printf("time()->gmtime()->mktime():%ld\n",timep1);timep2 = mktime(p4);printf("time()->localtime()->mktime():%ld\n",timep2);return 0;
}now time seconds:1555383494
p3->hour:2
p4->hour:10
p3->hour:10
p4->hour:10
time()->gmtime()->mktime():1555383494
time()->localtime()->mktime():1555383494

3. strftime

size_t strftime(char str, size_t maxsize, const charformat, const struct tm*timeptr)
根据format中定义的格式化规则,格式化结构体timeptr表示的时间,并把它存储在str中
格式说明符:

举个栗子:

#include <stdio.h>
#include <time.h>int main ()
{time_t rawtime;struct tm *info;char buffer[80];time(&rawtime);info = localtime( &rawtime );strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", info);printf("格式化的日期 & 时间 : |%s|\n", buffer );return(0);
}
格式化的日期 & 时间 : |2019-04-16 12:25:04|

二、 字符串时间转time_t秒数

1. strptime 带时区转换

按照特定时间格式将字符串转换为时间类型struct tm
strptime转换得到的struct tm会自带时区信息,使用mktime转换得到的秒数会考虑这个时区信息。
#include <time.h>
char *strptime(const char buf, const char format, struct tm *tm)
返回值:
调用成功返回buf最后位置,失败返回空指针
举个栗子:

比如tm初始化为 1970-1-1 00:00:00,
如果设置的是UTC时区 mktime 输出 0
如果设置的是Shanghai时区 mktime 输出 -22800
如果设置的是Tokyo时区 mktime 输出 -32400
如果设置的是NewYork时区 mktime 输出 18000

2. mktime 有时区转换

将已经根据时区信息(所谓的时区转换讲的是struct tm中自带的时区信息)计算好的struct tm转换成time_t秒数,计算得出的秒数是以UTC时间为标准的。
time_t mktime(struct tm*timeptr)

例1:
time_t time;
struct tm * timeinfo;
timeinfo->tm_year = 70;
timeinfo->tm_mon = 0;
timeinfo->tm_mday = 1;
timeinfo->tm_hour = 0;
timeinfo->tm_min = 0;
timeinfo->tm_sec = 0;time = mktime(timeinfo);
我用linux ,如果是上海, time是-28800,刚好8小时,东八区。
但把时间调到伦敦,时间time就变成-3600,而不是 0

例2:
Linux使用带时区转换的时间函数注意事项(负负得正)
比如utc时间秒数1519741060,当我用gmtime_r转换为struct tm t结构时,再用mktime函数转换为秒数时,发现时间被减了8个小时,也就是8时区,这是因为mktime认为你的结构带了时区。
因此,如果想用秒数转换为tm结构之后,再从tm结构转换秒数的正确方法应该是使用localtime_r转为有时区的tm,mktime再去掉时区得回之前的秒数。这就是负负得正。

#include<stdio.h>
#include<time.h>
int main(void)
{time_t timtmp, timep1, timep2;struct tm p1, p2;timtmp = time(NULL);printf("now time seconds:%ld\n", timtmp);gmtime_r(&timtmp, &p1);localtime_r(&timtmp, &p2);timep1=mktime(&p1);printf("time()->gmtime()->mktime():%ld\n",timep1);timep2 = mktime(&p2);printf("time()->localtime()->mktime():%ld\n",timep2);return 0;
}now time seconds:1555383248
time()->gmtime()->mktime():1555354448
time()->localtime()->mktime():1555383248

本文链接:https://my.lmcjl.com/post/10967.html

展开阅读全文

4 评论

留下您的评论.