高精度时间戳的获取
获取毫秒级的高精度时间戳是一个很常见的需求,尤其在向日志文件中输出信息时通常需要附带格式化的时间戳,
下面在不同的语言中尝试生成形如 [2024-07-30 00:52:47.379]
的高精度时间戳。(虽然在大部分语境下,时间戳是一个非负整数,但是为了方便使用,这里统一为含毫秒的固定格式的时间字符串)
C++
对于C++,标准库 chrono 可以获取高精度的时间, 然后通过
localtime
函数进行格式化,由于它不支持毫秒部分的格式化,我们还需要对毫秒进行额外处理。
下面是一个生成时间戳的示例函数
1 | static std::string time_stamp() { // unsafe |
这里使用的是
std::strftime函数,它把格式化的时间写入到指定的字符数组中,除此之外,还有一个类似的函数std::put_time把格式化的时间输出到流。
我们使用的 localtime 函数无法保证线程安全,在 Windows 和
Linux 平台上分别为其提供了线程安全的版本:localtime_s和
localtime_r,都需要传入两个指针参数,需要特别注意,这两个平台提供的参数顺序是
TM 相反的!
我们可以通过条件编译来支持不同的平台,在其它情况下则通过加锁来保证线程安全。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31static std::string time_stamp() {
auto now = std::chrono::system_clock::now();
auto now_time_t = std::chrono::system_clock::to_time_t(now);
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch())
% 1000;
char buffer[32]{};
struct tm timeinfo {};
localtime_s(&timeinfo, &now_time_t);
localtime_r(&now_time_t, &timeinfo);
static std::mutex mtx;
{
std::lock_guard<std::mutex> lock(mtx);
timeinfo = *localtime(&now_time_t);
}
std::strftime(static_cast<char *>(buffer), sizeof(buffer),
"[%Y-%m-%d %H:%M:%S", &timeinfo);
std::snprintf(static_cast<char *>(buffer) + 20, 6, ".%03d]",
static_cast<int>(now_ms.count()));
return std::string{static_cast<char *>(buffer)};
}
这里没有考虑 C++20 或者更新的语法标准,期待后续可以有更简洁的写法吧。
Fortran
对于 Fortran 这个老古董语言,要获取时间戳就比 C++
还困难了,我们只能手动地实现格式化的部分,下面是一个示例子程序,使用
mingw-w64 gfortran
可以顺利编译运行,其它平台和编译器并没有测试。
1 | subroutine get_timestamp(timestamp) |
Python
在 Python 中获取指定格式的高精度时间戳是非常简单的,需要先导入
datetime 模块中的 datetime
类,然后一行代码就可以搞定
1 | from datetime import datetime |
这里 [:-3] 是为了只截取毫秒部分的前三个数字。
MATLAB
在 MATLAB 中获取指定格式的高精度时间戳同样非常简单,基于
datestr 函数即可实现
1 | timestamp = datestr(now, 'yyyy-mm-dd HH:MM:SS.FFF'); |
注意 datastr 函数在较新的版本中不再建议使用,MATLAB
建议使用 datetime 函数替代
1 | timestamp = datetime('now','Format','yyyy-MM-dd HH:mm:ss.SSS'); |
Julia
在 Julia 中获取指定格式的高精度时间戳非常简单,只需要使用内置函数
now(),然后通过调用内置模块 Dates 的
Dates.format() 函数进行格式化即可
1 | using Dates |
