时间操作函数在实际项目开发中经常用到,最近项目中正好用到,顺便整理一下。从上图可以看出时间概览:1.可以通过系统调用函数time()从内核中获取一个time_t类型的值。这个值称为日历时间,即从UTC时间1970年1月1日到0分0秒计算到现在经过的秒数。而这个时间也用来纪念UNIX的诞生。2、函数gmtime()和localtime()可以将日历时间转换为structtm结构类型变量。通过该结构体成员可以方便的获取当前时间信息。我们也可以通过函数mktime将这种类型结构的变量转换成日历时间。structtm{inttm_sec;/*秒*/inttm_min;/*分钟*/inttm_小时;/*小时*/inttm_mday;/*日期*/inttm_mon;/*月*/inttm_year;/*自1990年以来的年数*/inttm_wday;/*week*/inttm_yday;/*自今年1月1日起的天数*/inttm_isdst;/*夏令时标志*/};3.asctime()和ctime()函数生成一个26字节的字符串形式,类似于date命令的系统默认输出形式:TueFeb1018:27:382020/n/0.4.strftime()将structtm结构格式化为字符串。常用时间函数及示例1、时间函数头文件:time.h函数定义:time_ttime(time_t*t)说明:返回UTC时间从1970年1月1日0:00:00到现在秒数。例如:#include#includeintmain(){time_ttimep;longseconds=time(&timep);printf("%ld\n",seconds);printf("%ld\n",时间);return0;}输出:有兴趣的同学可以计算一下从1970年1月1日0点00分00秒开始经过了多少秒。附:time_t一路追查,发现是从long类型开始通过连续的typedef和#define来定义的。2、ctime函数定义:char*ctime(consttime_t*timep);解释:将参数引用的time_t结构中的信息转换为现实世界的时间日期表示方法,然后以字符串的形式返回结果。请注意,这是当地时间。例如:#include#includeintmain(void){time_ttimep;time(&timep);printf("%s\n",ctime(&timep));return0;}输出:3,gmtime函数定义:structtm*gmtime(consttime_t*timep);解释:将参数timep指向的time_t结构体中的信息转换成现实世界中使用的时间日期表示方式,再由结构体tm返回结果。该函数返回的时间日期不是经过时区转换的,而是UTC时间。例如:#include#includeintmain(void){char*wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};time_ttimep;structtm*p;time(&timep);p=gmtime(&timep);printf("%d/%d/%d",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);printf("%s%d:%d:%d\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);return0;}输出:4.strftime函数#include定义:size_tstrftime(char*s,size_tmax,constchar*format,conststructtm*tm);说明:与snprintf函数类似,我们可以使用format指向的format字符串将structtm结构中的信息输出到s指针指向的字符串中,最多maxbytes。当然s指针指向的地址需要提前分配空间,比如字符数组或者malloc开辟的堆空间。其中,格式字符串中各种日期和时间的具体表示方法有很多,如下所示,我们可以根据需要对各种时间字符串进行格式化。%a星期几的缩写%A星期几的全称%b月份的缩写%B月份的全称%c标准日期时间字符串%C年份的前两位%d日期以十进制表示的月份%DMonth/Day/Year%e在双字符字段中,以十进制表示的月份中的第几天%FYear-Month-Day%g年份的最后两位数,使用基于周的年份%GYear分钟,使用基于周的年份%h缩写的月份名称%H24小时制%I12小时制%j十进制表示的一年中的第几天%m十进制表示的月份%M十进制表示的分钟%n换行符%p本地等同于AM或PM显示%r12小时时间%R显示小时和分钟:hh:mm%S十进制秒%t水平制表符%T显示小时、分钟和秒:hh:mm:ss%u星期几,星期一是第一天(取值0到6,星期一为0)%U年的星期,以星期日为第一天(取值0到53)%V一年中的第几周,用星期-basedyear%w十进制的星期几(值从0到6、星期日为0)%W一年中的第几周,以星期一为第一天(取值从0到53)%x标准日期字符串%X标准时间字符串%y不带世纪的十进制年份(取值从0to99)%Y带世纪部分的十进制年份%z,%Z时区名称,如果无法获取时区名称,则返回空字符。%%百分号返回值:如果成功,则返回格式化后s字符串的字节数,不包括空终止符,但返回的字符串包含空字节终止符。否则返回0,并且s字符串的内容未定义。值得注意的是,这是来自libc4.4.4及之后的版本。对于一些旧的libc库,比如4.4.1,如果给定的max较小,则返回max值。也就是说,返回字符串可以容纳的最大字节数。例如:1#include2#include34#defineBUFLEN2555intmain(intargc,char**argv)6{7time_tt=time(0);8chartmpBuf[BUFLEN];910strftime(tmpBuf,BUFLEN,"%Y%m%d%H%M%S",localtime(&t));//formatdatea11printf("%s\n",tmpBuf);12return0;13}执行结果如下:输出结果表示YYYYmmDDHHMMSS5,asctime函数定义:char*asctime(conststructm*timeptr);说明:时间日期表达式方法,用于将参数timeptr指向的structtm结构中的信息转换为实时,结果以字符串形式返回。与ctime()函数的区别在于传入的参数是不同的结构体。返回值:UTC时间也被返回。例如:#include#include#includeintmain(void){time_ttimep;time(&timep);printf("%s\n",asctime(gmtime(&timep)));返回EXIT_SUCCESS;}输出:6.localhost函数structtm*localhost(consttime_t*timep);获取当前本地时间和日期,如下所示:#include#include#includeintmain(void){char*wday[]={"Sun","Mon""星期二","星期三","星期四","星期五","星期六"};time_ttimep;structtm*p;时间(&timep);p=本地时间(&timep);printf("%d/%d/%d",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);printf("%s%d:%d:%d\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);returnEXIT_SUCCESS;}输出:7,mktime函数定义:time_tmktime(structtm*timeptr);说明:用于将参数timeptr指向的tm结构体数据转换为UTC时间1970年1月1日0:00:00到现在经过的秒数。例如:#include#include#includeintmain(void){time_ttimep;structtm*p;time(&timep);printf("time():%ld\n",timep);p=localtime(&timep);timep=mktime(p);printf("time()->localtime()->mktime():%ld\n",timep);returnEXIT_SUCCESS;}output:8.gettimeofday函数定义:intgettimeofday(structtimeval*tv,structtimezone*tz);说明:当前时间由tv指示的结构体返回,本地时区信息放在tz指示的结构体中。结构timeval定义如下:structtimeval{longtv_sec;/*seconds*/longtv_usec;/*microseconds*/};结构timezone定义如下:structtimezone{inttz_minuteswest;/*与格林威治时差多少分钟*/inttz_dsttime;/*夏令时状态*/}示例如下:#include#include#include#includeintmain(void){structtimevaltv;structtimezonetz;gettimeofday(&tv,&tz);printf("tv_sec:%d\n",tv.tv_sec);printf("tv_usec:%d\n",tv.tv_usec);printf("tz_minuteswest:%d\n",tz.tz_minuteswest);printf("tz_dsttime:%d\n",tz.tz_dsttime);返回EXIT_SUCCESS;}Output:comprehensiveexperiment现在我们利用这些时间函数来实现一个定时执行某个任务的函数。功能程序运行时,需要记录当前日志文件的最后修改时间;每10秒,检查日志文件是否被删除。修改,如果没有修改,休眠10秒;如果日志文件被修改,将当前日志文件复制到备份文件中,在备份文件的名称中加上当前时间;通过curl发送到ftp服务器;删除备份文件,重复步骤2。程序流程图如下:此处插图描述函数功能介绍init()首先记录当前日志文件的时间,并记录在全局变量last_mtime中。check_file_change()读取文件的最后修改时间并与last_mtime进行比较。如果相同则返回0,如果不同则返回1。file_name_add_time()将当前日志文件复制到备份文件中,并将当前时间添加到备份文件名中。stat()获取对应文件的属性信息,存储在structstat结构体的变量中。运行截图:第1步:由于日志文件没有修改,所以不会上传程序。第2步:手动将字符串yikoulinux输入到日志文件t.log中。第三步:因为文件发生了变化,打印了“fileupdated”,同时可以看到curl上传文件的log信息。下面是FTP服务器的根目录。可以看到上传的日志文件:t-2020-7-26-1-19-45.log。【补充】1、配置信息,直接写在代码中,通常应该从配置文件中读取。为了方便读者阅读,本代码不添加该功能;2.FTP服务器设置,本文不做讲解,相关文件很多,大家可以自行搜索,一口君用的是Filezilla;3、通常这种需要长时间运行的程序需要设置为守护进程。本文不添加相应功能,读者可自行搜索。如果有强烈需求,可以单独开详细介绍。4、代码中时间的管理功能,请读者自行搜索相关文章。5.curl还提供了相关的函数库curl.lib,如果想实现更灵活的功能,可以使用相应的api。之所以先将文件复制成备份文件,主要是考虑到其他模块随时可能修改日志文件,起到一定的保护作用。代码如下代码如下:/*********************************************************版权所有(C)公众号:一口linux******************************************************/#include#include#include#include#includetypedefstructstatST;unsignedlonglast_mtime;/*用户名和密码暂时硬编码,实际应该保存在配置文件中*/charname[32]="user";charpass[32]="123456";charip[32]="192.168.43.117";charfilename[32]="t.log";chardstfile[256]={0};intinit(void){//准备结构体STstatus;//调用stat函数intres=stat(filename,&status);if(-1==res){perror("error:openfilefail\n");return0;}last_mtime=status.st_mtime;printf("初始化时间:%s\n",ctime(&last_mtime));return1;}intcheck_file_change(void){//准备结构STstatus;//调用stat函数intres=stat(filename,&status);if(-1==res){perror("error:openfilefail\n");return0;}//printf("old:%snew:%s",ctime(&last_mtime),ctime(&status.st_mtime));if(last_mtime==status.st_mtime){printf("filenotchange\n");return0;}else{printf("fileupdated\n");last_mtime=status.st_mtime;return1;}}voidfile_name_add_time(void){STstatus;time_tt;structtm*tblock;charcmd[1024]={0};t=time(NULL);tblock=localtime(&t);sprintf(dstfile,"t-%d-%d-%d-%d-%d-%d.log",tblock->tm_year+1900,tblock->tm_mon,tblock->tm_mday,tblock->tm_hour,tblock->tm_min,tblock->tm_sec);sprintf(cmd,"cp%s%s",文件名,dstfile);//printf("cdm=%s\n",cmd);system(cmd);}intmain(void){charcmd[1024]={0};init();while(1){if(check_file_change()==1){file_name_add_time();sprintf(cmd,"curl-u%s:%sftp://%s/-T%s",name,pass,ip,dstfile);//printf("cdm=%s\n",cmd);system(cmd);unlink(dstfile);}sleep(10);}}本文转载自微信公众号「一口Linux」,可关注转载本文通过以下二维码请联系一口Linux公众号。