1、概述
时间函数在Linux编程中具有广泛的应用场景:
-
时间戳记录:在日志记录、事件跟踪和性能分析中,时间函数用于记录事件发生的时间戳,以便后续分析和调试。
-
定时任务:时间函数可以用于执行定时任务,例如定时触发某些操作、定时发送通知或执行周期性任务。
-
超时控制:在网络编程和并发编程中,时间函数用于设置超时时间,以确保程序在规定时间内完成操作或处理超时情况。
-
时间比较:时间函数可以用于比较时间的先后顺序,判断事件的顺序或计算时间间隔。
-
时间同步:时间函数可以用于系统时间的同步和校准,确保系统时间的准确性和一致性。
2、接口总结测试
2.1 常用时间转换接口
2.1.1 time函数
通常使用time(NULL)获取0时区从1970年开始到现在的秒数。
time_t time(time_t *timer)
- 入参:
timer
是一个指向time_t
类型的指针,用于存储获取的时间值。 - 返回值:当前系统时间的
time_t
类型的秒数
2.1.2 localtime函数
将time_t
类型的时间转换为本地时间,返回一个指向tm
结构体的指针.,其中年份是减去了1900之后的值,月份是从0开始:
struct tm *localtime(const time_t *timer);
其中struct tm:
struct tm {
int tm_sec; // 秒 (0-59)
int tm_min; // 分 (0-59)
int tm_hour; // 时 (0-23)
int tm_mday; // 一个月中的日期 (1-31)
int tm_mon; // 月份 (0-11)
int tm_year; // 年份 - 1900
int tm_wday; // 一周中的天数 (0-6, 0为星期日)
int tm_yday; // 一年中的天数 (0-365)
int tm_isdst; // 夏令时标识符
};
- 入参:
timep
是一个指向time_t
类型时间的指针。 - 返回值:指向表示本地时间的
tm
结构体的指针。
2.1.3 localtime_r函数
将time_t
类型的时间转换为本地时间的tm
结构体形式,将结果存储在指定的tm
结构体中。
struct tm *localtime_r(const time_t *timep, struct tm *result);
- 入参:
timep
是一个指向time_t
类型时间的指针;result
是用于存储结果的tm
结构体。 - 返回值:指向存储本地时间的
tm
结构体的指针。
2.1.4 mktime函数
将tm
结构体表示的时间转换为time_t
类型的秒数。
time_t mktime(struct tm *timeptr);
- 入参:
timeptr
是一个指向tm
结构体的指针,表示要转换的时间。 - 返回值:转换后的
time_t
类型的秒数。
2.1.5 gmtime函数
将time_t
类型的时间转换为协调世界时(UTC)的tm
结构体形式。
struct tm *gmtime(const time_t *timep);
- 入参:
timep
是一个指向time_t
类型时间的指针。 - 返回值:指向表示UTC时间的
tm
结构体的指针。
2.1.6 gmtime_r函数
将time_t
类型的时间转换为协调世界时(UTC)的tm
结构体形式,将结果存储在指定的tm
结构体中。
struct tm *gmtime_r(const time_t *timep, struct tm *result);
- 入参:
timep
是一个指向time_t
类型时间的指针;result
是用于存储结果的tm
结构体。 - 返回值:指向存储UTC时间的
tm
结构体的指针。
2.1.7 代码测试
编写测试代码:
#include <stdio.h>
#include <time.h>
int main()
{
time_t current_time;
struct tm *local_time;
struct tm timeinfo = {0};
current_time = time(NULL);
printf("time(NULL) = %ld\n", current_time);
local_time = localtime(¤t_time);
printf("localtime:%d-%d-%d %d:%d:%d\n", local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday, local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
// 将获取到的年份减1 其它值不变 测试mktime
timeinfo = *local_time;
timeinfo.tm_year -= 1;
current_time = mktime(&timeinfo);
printf("mktime return = %ld\n", current_time);
local_time = gmtime(¤t_time);
printf("gmtime:%d-%d-%d %d:%d:%d\n", local_time->tm_year + 1900, local_time->tm_mon + 1, local_time->tm_mday, local_time->tm_hour, local_time->tm_min, local_time->tm_sec);
return 0;
}
获取当前秒数,转化为年月时分秒,与当前时间一致,将时间减去1年然后调用mktime将年月日时分秒重新转换为秒数,两者差值刚好是1年的秒数:
2.2 时间转字符串接口
2.2.1 asctime函数
将tm
结构体表示的时间转换为字符串形式。
char *asctime(const struct tm *tm);
- 入参:
tm
是一个指向tm
结构体的指针,表示要转换为字符串的时间。 - 返回值:指向表示时间的字符串的指针。
2.2.2 asctime_r函数
将tm
结构体表示的时间转换为字符串形式,将结果存储在指定的缓冲区中。
char *asctime_r(const struct tm *tm, char *buf);
- 入参:
tm
是一个指向tm
结构体的指针,表示要转换为字符串的时间;buf
是用于存储结果的缓冲区。 - 返回值:指向存储时间字符串的缓冲区的指针。
2.2.3 ctime函数
将time_t
类型的时间转换为字符串形式。
char *ctime(const time_t *timep);
- 入参:
timep
是一个指向time_t
类型时间的指针。 - 返回值:指向表示时间的字符串的指针。
2.2.4 ctime_r函数
将time_t
类型的时间转换为字符串形式,将结果存储在指定的缓冲区中。
char *ctime_r(const time_t *timep, char *buf);
- 入参:
timep
是一个指向time_t
类型时间的指针;buf
是用于存储结果的缓冲区。 - 返回值:指向存储时间字符串的缓冲区的指针。
2.2.5 代码测试
编写测试代码如下:
#include <stdio.h>
#include <time.h>
int main() {
struct tm timeinfo = {0};
char temp[32] = {0};
char *time_str;
time_t current_time = time(NULL);
localtime_r(¤t_time, &timeinfo);
time_str = asctime(&timeinfo);
printf("asctime: %s", time_str);
asctime_r(&timeinfo, temp);
printf("asctime_r: %s", temp);
time_str = ctime(¤t_time);
printf("ctime: %s", time_str);
ctime_r(¤t_time, temp);
printf("ctime_r: %s", temp);
return 0;
}
转换字符串打印结果如下:
2.3 微妙获取接口
2.3.1 gettimeofday函数
获取当前时间和时区信息。
int gettimeofday(struct timeval *tv, struct timezone *tz);
其中:
// struct timeval
struct timeval {
time_t tv_sec; // 秒部分
suseconds_t tv_usec; // 微秒部分
};
- 入参:
tv
是指向struct timeval
结构体的指针,用于存储当前时间;tz
是指向struct timezone
结构体的指针,常用NULL。 - 返回值:若成功,返回0;否则返回-1。
2.3.2 settimeofday函数
设置系统的当前时间信息。
int settimeofday(const struct timeval *tv, const struct timezone *tz);
- 入参:
tv
是指向struct timeval
结构体的指针,包含要设置的时间信息;tz
是指向struct timezone
结构体的指针,常用NULL。 - 返回值:若成功,返回0;否则返回-1。
2.3.3 代码测试
测试代码如下:
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
int main()
{
struct timeval tv;
// 获取当前时间信息
gettimeofday(&tv, NULL);
// 输出秒数和微秒数
printf("Seconds: %ld\n", tv.tv_sec);
printf("Microseconds: %ld\n", tv.tv_usec);
return 0;
}
测试结果:
2.4 获取系统运行时间
2.4.1 clock_gettime函数
获取指定时钟的当前时间,并将结果存储在struct timespec
结构体中。
int clock_gettime(clockid_t clk_id, struct timespec *tp);
其中 clk_id:
CLOCK_REALTIME: 系统实时时间时钟,通常为系统的墙钟时间。
CLOCK_MONOTONIC: 一个单调递增的时钟,不受系统时间调整的影响。
CLOCK_PROCESS_CPUTIME_ID: 用于度量与进程相关的CPU时间。
CLOCK_THREAD_CPUTIME_ID: 用于度量与线程相关的CPU时间。
CLOCK_MONOTONIC_RAW: 一个单调递增的时钟,不受系统时间调整或NTP同步的影响。
CLOCK_REALTIME_COARSE: 类似于CLOCK_REALTIME,但精度较低。
CLOCK_MONOTONIC_COARSE: 类似于CLOCK_MONOTONIC,但精度较低。
CLOCK_BOOTTIME: 从系统启动开始计时,包括系统休眠时间。
CLOCK_REALTIME_ALARM: 类似于CLOCK_REALTIME,但可能会被挂起以节省能源。
CLOCK_BOOTTIME_ALARM: 类似于CLOCK_BOOTTIME,但可能会被挂起以节省能源。
struct timespec {
time_t tv_sec; // 秒
long tv_nsec; // 纳秒
};
- 入参:
clk_id
是时钟ID,tp
是用于存储时间结果的struct timespec
结构体指针。 - 返回值:若成功,返回0;否则返回-1。
2.4.2 clock_settime函数
设置指定时钟的时间为给定的时间。
int clock_settime(clockid_t clk_id, const struct timespec *tp);
- 入参:
clk_id
是时钟ID,tp
是包含要设置的时间的struct timespec
结构体指针。 - 返回值:若成功,返回0;否则返回-1。
2.4.3 代码测试
测试代码如下:
#include <stdio.h>
#include <time.h>
int main() {
struct timespec tp = {0};
clock_gettime(CLOCK_MONOTONIC, &tp);
printf("uptime: %ld s %ld ns\n", tp.tv_sec, tp.tv_nsec);
return 0;
}
测试结果:
3、Linux常用命令
3.1 date命令
用于显示或设置系统时间和日期。
- 显示当前日期和时间:
date
- 设置系统时间为指定时间:
sudo date MMDDhhmmYYYY.ss
3.2 timedatectl命令
用于控制系统时间和日期以及时区设置。
- 显示系统时间和时区信息:
timedatectl status
- 设置系统时区:
sudo timedatectl set-timezone Asia/Shanghai
3.3 hwclock命令
hwclock
: 用于显示或设置硬件时钟(RTC)的时间。
- 显示硬件时钟时间:
sudo hwclock
- 同步系统时间到硬件时钟:
sudo hwclock --systohc
4、总结
本文阐述了Linux中时间编程的应用场景,列出了时间编程常用的接口,并编写示例进行简单测试。简单介绍了几个时间相关的linux命令。