和老板问了一下,今天就可以自己上手了:
用TSCNS写了一个cpp,运行出来老板说让我去看看另一个项目是怎么做的
用TSCNS和std库获取当前时间
cpp
#include <iostream>
#include <iomanip>
#include "tscns.h"
using namespace std;
TSCNS tn;
int main() {
// 初始化 TSCNS 对象
tn.init();
// 获取当前时间的纳秒级时间戳(UTC)
int64_t timestamp_ns = tn.rdns();
// 将纳秒时间戳转换为秒
int64_t timestamp_sec = timestamp_ns / tn.NsPerSec;
int64_t nanoseconds = timestamp_ns % tn.NsPerSec; // 获取纳秒部分
// 添加 8 小时偏移(以秒为单位)以获取北京时间
int64_t beijing_time_sec = timestamp_sec + 8 * 3600;
// 将秒转换为 tm 结构体
std::time_t beijing_time_t = static_cast<std::time_t>(beijing_time_sec);
std::tm beijing_time_tm = *std::gmtime(&beijing_time_t); // 使用 gmtime 将其视为 UTC 时间处理
// 格式化输出北京时间(精确到纳秒),不带冒号,格式为 YYYYMMDD HHMMSSnnnnnnnnn
cout << "Current Beijing Time: "
<< std::put_time(&beijing_time_tm, "%Y%m%d ")
<< std::setw(2) << std::setfill('0') << beijing_time_tm.tm_hour
<< std::setw(2) << std::setfill('0') << beijing_time_tm.tm_min
<< std::setw(2) << std::setfill('0') << beijing_time_tm.tm_sec
<< std::setw(9) << std::setfill('0') << nanoseconds
<< endl;
return 0;
}
-
初始化
TSCNS
对象 :调用tn.init()
初始化TSCNS
对象tn
,完成基于 TSC(Time Stamp Counter)和系统时间的初始同步与校准。 -
获取当前时间戳 :通过
tn.rdns()
获取当前时间的纳秒值并将其存储到timestamp
变量中。 -
执行校准 :调用
tn.calibrate()
方法进行校准。这是可选的,用于定期修正 TSC 和系统时间的误差。 -
计算时间的小时、分钟、秒、毫秒和纳秒部分:
- 将
timestamp
转换为秒和纳秒部分。 - 使用整数除法和取余操作提取小时、分钟、秒等信息。
- 将纳秒部分进一步转换为毫秒,剩余的部分保留为纳秒。
- 将
-
输出格式化的时间:
- 使用
std::setfill('0')
和std::setw()
来格式化输出,使得小时、分钟和秒数都有两位数,毫秒为三位数。 - 输出了两种格式:一种是精确到毫秒的格式(
HHMMSSmmm
),另一种是精确到纳秒的格式(HHMMSSnnnnnnnnn
)。
- 使用
一些零碎知识点
setfill('0')
setfill
是一个操纵器,用来设置输出时的填充字符。通常在输出较小数字时,如果不满足指定的宽度,可以使用填充字符填补前面的空位。
setfill('0')
的作用是将输出数字前面不足的部分用字符'0'
填充。- 例如:在输出两位数的时间格式时,可以用
setfill('0')
来确保个位数前面会填充0
,以确保始终是两位数显示。
setw(width)
setw()
是一个操纵器,用来指定输出字段的宽度。它会影响接下来输出的一个值,将其宽度设置为指定的 width
。
- 如果输出的值宽度小于
width
,则在左侧用填充字符填充(默认是空格,使用setfill
可以更改填充字符)。 - 如果输出的值宽度大于或等于
width
,则setw()
会被忽略,不会截断数字
std库获取时间
- 使用
std::chrono::system_clock::now()
获取当前系统时间。 - 转换为 UTC 时间 :
std::gmtime()
函数将time_t
转换为 UTC 时间 std::time_t
是一个用于表示时间点的类型,通常表示自 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)以来的秒数。std::time_t
是 C++ 标准库中的类型,
std::tm
结构体
std::tm
结构体定义在 <ctime>
头文件中,包含了多个成员变量,每个成员变量表示日期和时间的不同组成部分。具体成员包括:
|------------|--------------------------|
| tm_mday
: | 小时(0 到 23)。 |
| tm_hour
: | 分钟(0 到 59)。 |
| tm_sec
: | 秒(0 到 60,允许闰秒)。 |
| tm_wday
: | 星期几(0 表示星期日)。 |
| tm_yday
: | 从 1 月 1 日开始的天数(0 到 365)。 |
UTC时间
UTC 时间(协调世界时,Coordinated Universal Time)是一种标准时间,用于全球时间同步
UTC的特点
- 不受时区影响:UTC 是全球统一的时间,不偏向任何一个时区。
- 与 GMT 的关系:UTC 和格林尼治标准时间(GMT)相似,但 UTC 更精确。GMT 是历史上的一种时间标准,基于天文观测,UTC 则基于原子钟。
- 没有夏令时:UTC 时间不会因季节变化而调整,因此不同国家或地区可以根据 UTC 时间确定本地时间的偏移量。
UTC 与时区
地球被划分为 24 个时区,每个时区都相对 UTC 有一个时差。例如:
- 北京时间(CST)为 UTC+8,意味着北京时间比 UTC 时间早 8 小时。
- 纽约时间(EST)为 UTC-5,但在夏令时为 UTC-4。
static_case
static_cast
是 C++ 中的一种类型转换方式,用于在编译时执行类型转换
static_cast<目标类型>(表达式);
static_cast<std::time_t>(beijing_time_sec)
将整数 beijing_time_sec
转换为 std::time_t
类型
auto关键字
auto
关键字:
auto
是 C++ 中的类型自动推导关键字。在编译时,编译器会根据右侧表达式的类型推导出auto
的实际类型。
::作用域解析运算符
::
是 C++ 中的作用域解析运算符(Scope Resolution Operator)。它用于指定某个标识符(例如变量、函数、类)所在的命名空间或类作用域,以便编译器找到正确的定义。
在 TSCNS::NsPerSec
中,::
表示 NsPerSec
是 TSCNS
类中的一个静态成员变量。这里 TSCNS
是类名,而 NsPerSec
是该类的一个静态常量,::
将它们连接起来,表示访问 TSCNS
类中的 NsPerSec
成员。
cpp
class TSCNS {
public:
static const int64_t NsPerSec = 1000000000; // 每秒的纳秒数
};
// 在其他地方访问
int64_t nanoseconds_in_a_second = TSCNS::NsPerSec;
老板说,1,不要用std库
2.不要setfill