【摘要】本文旨在说明在Linux中各种时间相关的变量定义,以及他们之间的转换函数。
一、时间类型
/* A time value that is accurate to the nearest
microsecond but also has a range of years. */
struct timeval
{
__time_t tv_sec; /* Seconds */
__suseconds_t tv_usec; /* Microseconds */
};
struct timespec
{
__time_t tv_sec; /* Seconds. */
__syscall_slong_t tv_nsec; /* Nanoseconds. */
};
struct tm
{
int tm_sec;/* Seconds.[0-60] (秒超过59的理由是表示润秒) */
int tm_min;/* Minutes.[0-59] */
int tm_hour;/* Hours.[0-23] */
int tm_mday;/* Day.[1-31] (除了月日,其他字段的值都以 0开始)*/
int tm_mon;/* Month.[0-11] */
int tm_year;/* Year- 1900. */
int tm_wday;/* Day of week.[0-6] */
int tm_yday;/* Days in year.[0-365]*/
int tm_isdst;/* DST.[-1/0/1]代表[不可用/非夏时制/夏时制]*/
# ifdef __USE_MISC
long int tm_gmtoff;/* Seconds east of UTC. */
const char* tm_zone;/* Timezone abbreviation. */
# else
long int __tm_gmtoff;/* Seconds east of UTC. */
const char *__tm_zone;/* Timezone abbreviation. */
# endif
};
二、时间函数
(一) 获取/设置 秒级 精度的日历时间
//取得从1970年1月1日至今的秒数
//例如:time_t totalsec = time(NULL);或time(&totalsec);
time_t time(time_t *t);
//修改系统时间,注意只有root用户才有修改系统时间的权限
int stime(time_t *t);
(二) 获取/设置 微秒级 精度的日历时间
//系统函数,返回自1970年以来的秒数和微秒数,后面的tz是时区,一般不用。
int gettimeofday(struct timeval *tv, struct timezone *tz);
//系统函数,为系统设置当前时间;后面的tz通常设为NULL,表示使用当前系统的时区
int settimeofday(struct timeval *tv, struct timezone *tz);
(三)获取/设置 纳秒级 精度的日历时间
int clock_gettime(clockid_t clk_id, struct timespec *tp);
/*根据需要,获取不同要求的精确时间
参数clk_id可取以下值:
CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时,中间时刻如果系统时间被用户改成其他,则对应的时间相应改变
CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
CLOCK_PROCESS_CPUTIME_ID:本进程到当前代码系统CPU花费的时间
CLOCK_THREAD_CPUTIME_ID:本线程到当前代码系统CPU花费的时间
*/
(四)日历时间——>本地时间
//将time_t表示的时间转换为没有经过时区转换的UTC时间
struct tm* gmtime(const time_t *timep);
//和gmtime类似,但是它是经过时区转换的时间。
struct tm* localtime(const time_t *timep);
(五)本地时间——>日历时间
//将struct tm 结构的时间转换为日历时间(从1970年至今的秒数)
time_t mktime(struct tm *timeptr);
(六)获取字符串形式的时间
char* asctime(const struct tm *timeptr);
//将结构中的信息转换为真实世界的UTC时间,以字符串的形式显示
char* ctime(const time_t *timep);
//作用同asctime,不同点仅在于传入的参数类型不同
size_t strftime(char *buf, size_t maxsize, const char *format, const struct tm *tmptr);
//将tmptr指向的tm本地时间转化为format格式的字符串,并存入buf中,返回字符串长度。
/* 格式意义例子
__________________________________________________
%a 缩写的周日名Tue
%A 全周日名 Tuesday
%b 缩写的月名 Jan
%B 月全名 January
%c 日期和时间 Tue Jan 14 19:40:30 1992
%d 月日:[01, 31] 14
%H 小时(每天2 4小时):[00, 23] 19
%I 小时(上下午各12小时):[01, 12]07
%j 年日:[001, 366] 0 14
%m 月:[01, 12] 01
%M 分:[00, 59] 40
%p AM/PM PM
%S 秒:[00, 61] 30
%U 星期日周数:[00, 53] 02包含该年中第一个星期日的周是第一周
%w 周日:[ 0=星期日,6 ] 2
%W 星期一周数:[00, 53] 02包含第一个星期一的周为第一周
%x 日期 01/14/92
%X 时间 19:40:30
%y 不带公元的年:[00, 991] 92
%Y 带公元的年 1992
%Z 时区名 MST
__________________________________________________
*/
(七)其它
//返回两个时间相差的秒数
double difftime(time_t time1, time_t time2);
Linux时间转换图:
三、实例
设置系统时间:
struct timeval tv;
tv.tv_sec = (time_t)gps_utctime_sec;
tv.tv_usec = 0;
if(settimeofday (&tv, NULL) <0){
MSG("[ GPS ]:Set system datatime error,may need root permissions!\n");
}
else
MSG("[ GPS ]:GPS valid,update system time!\n");
读取当前时间tick
/*! get the current system time tick, second unit */
static uint32_t getCurrSysTick(void)
{
time_t timep;
time (&timep);
return timep; //seconds from 1970-1-1:0:0:0
}
读取当前时间字符串:Fri Dec 20 14:44:18 2019
static char* getCurrSysTime(void)
{
time_t timep;
time (&timep);
return asctime(localtime(&timep));
}
设置延时
static void delay_ms(unsigned int dms)
{
struct timespecsleeper, dummy ;
sleeper.tv_sec= (time_t)(dms/1000) ;
sleeper.tv_nsec= (long)(dms%1000) *1000000 ;
nanosleep (&sleeper, &dummy);//delay 1ms
}
获取当前时间tm
struct tm *t_tm;
t_tm = localtime((time_t*)&meas_gps_utctime.tv_sec);
printf("today is %4d-%02d-%02d %02d:%02d:%02d\n",\
t_tm->tm_year+1900,
t_tm->tm_mon+1,
t_tm->tm_mday,
t_tm->tm_hour,
t_tm->tm_min,
t_tm->tm_sec);