本文介绍C风格的日期和时间工具,文章代码库为:
https://gitee.com/gamestorm577/CppStd
时间类型
time_t
时间类型,表示从纪元开始经历的秒数,一般是整数类型,例如:
std::time_t t = 200;
printf("t = %lds\n", t);
输出结果为:
t = 200s
clock_t
用来表示进程运行时间的算术类型,除以CLOCKS_PER_SEC可以转换为秒数,例如:
std::clock_t t = 20005000;
printf("t = %ld\n", t);
输出结果为:
t = 20005000
tm
表示日期和时间的结构体:
tm_sec:秒数
tm_min:分钟数
tm_hour:小时数
tm_mday:一个月中的日期
tm_mon:月份
tm_year:从1900年开始年份
tm_wday:一周中的第几天
tm_yday:一年中的第几天
tm_isdst:夏令时标志,值若夏令时有效则为正,若无效则为零,若无可用信息则为负
代码示例为:
std::tm tm{};
printf("year: %d\nmonth: %d\nday: %d\nhour: %d\nminutes: %d\nseconds: %d\n",
tm.tm_year + 1900, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min,
tm.tm_sec);
输出结果为:
year: 1900
month: 0
day: 0
hour: 0
minutes: 0
seconds: 0
timespec
表示时长的结构体,成员有秒和纳秒:
struct timespec
{
std::time_t tv_sec;
long tv_nsec;
};
时间操作
time
获取从纪元开始的系统当前时间:
time_t time(time_t *arg);
如果arg不为空,那么返回的时间也会存储在arg中,例如:
std::time_t t1 = std::time(nullptr);
std::time_t t2;
std::time(&t2);
printf("t1 = %lds\n", t1);
printf("t2 = %lds\n", t2);
输出结果为:
t1 = 1704942541s
t2 = 1704942541s
clock
返回进程从开始到现在所用的处理器时间,例如:
std::clock_t t1 = std::clock();
std::this_thread::sleep_for(std::chrono::milliseconds(3500));
std::clock_t t2 = std::clock();
std::clock_t diff = t2 - t1;
printf("use time: %ld\n", diff);
输出结果为:
use time: 54
CLOCKS_PER_SEC表示每秒std::clock()返回的时钟计次数,可以用std::clock返回的时间除以CLOCKS_PER_SEC得到秒数。但是在POSIX中CLOCKS_PER_SEC定义为1000000,和std::clock()的实际精度无关。
difftime
计算std::time_t的时间差,例如:
std::time_t t1 = std::time(nullptr);
std::this_thread::sleep_for(std::chrono::milliseconds(3500));
std::time_t t2 = std::time(nullptr);
std::time_t diff = std::difftime(t2, t1);
printf("diff = %ld\n", diff);
输出结果为:
diff = 3
timespec_get
获取当前的timespec时间,例如:
std::timespec t;
std::timespec_get(&t, TIME_UTC);
printf("tv_sec = %ld\n", t.tv_sec);
printf("tv_nsec = %ld\n", t.tv_nsec);
输出结果为:
tv_sec = 1704948731
tv_nsec = 444908000
时间格式转换
ctime
转换std::time_t为文本格式,输出的字符串格式为:
Www Mmm dd hh:mm:ss yyyy\n
代码示例:
std::time_t now = std::time(nullptr);
char* str = std::ctime(&now);
printf("now time = %s", str);
输出结果为:
now time = Thu Jan 11 13:47:10 2024
asctime
将std::tm时间格式转换为文本,输出的字符串格式为:
Www Mmm dd hh:mm:ss yyyy\n
代码示例:
std::tm time{};
time.tm_year = 2024 - 1900;
time.tm_mon = 1;
time.tm_mday = 20;
time.tm_hour = 13;
time.tm_min = 40;
time.tm_sec = 20;
char* str = std::asctime(&time);
printf("time = %s", str);
输出结果为:
time = Sun Feb 20 13:40:20 2024
strftime
转换std::tm对象到自定义的文本表示:
std::size_t strftime(char* str,
std::size_t count,
const char* format,
const std::tm* tp);
如何自定义format可以参考:
https://zh.cppreference.com/w/cpp/chrono/c/strftime
代码示例:
std::tm time{};
time.tm_year = 2024 - 1900;
time.tm_mon = 1;
time.tm_mday = 20;
time.tm_hour = 13;
time.tm_min = 40;
time.tm_sec = 20;
char format[] = "%Y-%m-%d %H:%M:%S";
char result[100];
std::strftime(result, sizeof((result)), format, &time);
printf("time = %s\n", result);
输出结果为:
time = 2024-02-20 13:40:20
wcsftime
转换std::tm对象到自定义的宽字符串文本表示,使用方式和strftime类似。
gmtime
将std::time_t转换为std::tm时间,例如:
std::time_t now = std::time(nullptr);
std::tm* res = std::gmtime(&now);
char* str = std::asctime(res);
printf("now time = %s", str);
输出结果为:
now time = Thu Jan 11 06:20:16 2024
mktime
将std::tm转换为std::time_t时间,例如:
std::tm time{};
time.tm_year = 2024 - 1900;
time.tm_mon = 1;
time.tm_mday = 20;
time.tm_hour = 13;
time.tm_min = 40;
time.tm_sec = 20;
std::time_t res = std::mktime(&time);
char* str = std::ctime(&res);
printf("time = %s", str);
输出结果为:
time = Tue Feb 20 13:40:20 2024
localtime
将std::time_t转换为本地std::tm时间,例如:
std::time_t now = std::time(nullptr);
std::tm* res1 = std::localtime(&now);
std::tm* res2 = std::gmtime(&now);
printf("res1 = %s", std::asctime(res1));
printf("res2 = %s", std::asctime(res2));
输出结果为:
res1 = Thu Jan 11 14:30:14 2024
res2 = Thu Jan 11 06:30:14 2024