C++ std::chrono库使用指南 (实现C++ 获取日期,时间戳,计时等功能)(一)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: C++ std::chrono库使用指南 (实现C++ 获取日期,时间戳,计时等功能)

1. 引言

1.1. std::chrono库的主要功能

std::chrono是C++标准库中的一个组件,用于表示和处理时间。其功能就像是心理学中的感知系统,它可以为我们捕捉、量化并操作抽象的时间概念。这就如同我们的大脑可以理解和感知周围环境的时间流逝一样,这种感知和理解能力是人类进行日常活动所必需的。

如同马斯洛的需求层次理论中,生理需求位于最底层,时间感知就是计算机程序在处理各种任务时的基础需求,如果没有这个能力,计算机程序将无法进行任何有效的操作。

std::chrono库主要包含以下功能:

  • 时间点:表示特定的时间点,比如当前的时间。这如同人们通过记忆可以回忆起特定的时刻。
  • 时间段:表示时间的长度,比如1秒,1分钟,1小时等。这如同人们能够感知时间的流逝,理解"早","晚"等概念。
  • 时钟:用于获取当前的时间点,有三种类型的时钟:system_clock,steady_clock和high_resolution_clock。这如同人们通过看表来知道现在的具体时间。

为了更好的理解这些功能,让我们看一下下面的表格:

类名 描述 对应的心理学概念
std::chrono::system_clock 系统的实际时间,可能会受到系统时间调整的影响 外部环境对人的影响
std::chrono::steady_clock 稳定的时钟,时间从不调整 稳定、可靠的心理状态
std::chrono::high_resolution_clock 提供最小的可表示的时间间隔 细微的心理变化
std::chrono::time_point 表示特定的时间点 特定的记忆
std::chrono::duration 表示时间的长度 时间的感知

接下来,我们将详细探讨std::chrono库的各种子类如何使用,以及如何在实际编程中应用这些知识。

2. std::chrono库的子类介绍与应用

2.1. std::chrono::system_clock的用法和示例

我们的生活在时间的流逝中不断推进,这个自然的过程在C++中被封装在了std::chrono::system_clock这个类中。我们如同航海者使用指南针导航一样,可以借助system_clock在编程的海洋中导航。

std::chrono::system_clock是一个代表系统广泛使用的实时钟的类。它表示当前的墙上时间,从中可以获得当前时间,也可以在时间点上执行算术运算。

获取当前时间

你可以想象std::chrono::system_clock就像是一个不断向前的时间车轮。要获取当前时间,你只需要使用now()成员函数。看下面的代码:

std::chrono::system_clock::time_point now = std::chrono::system_clock::now();

这就像是在你的时间旅行中按下暂停按钮,捕捉到了一个时间点。这个点可以被保存,可以用来与其他时间点做比较,或者用作时间运算。

从time_point获取具体时间

system_clock::time_point表示一个时间点。但是我们通常需要更人性化的表达方式,比如年、月、日、小时、分钟和秒。这时候,我们可以像打开一个礼物盒一样,打开这个time_point,取出我们需要的信息。请看下面的代码:

std::time_t tt = std::chrono::system_clock::to_time_t(now);
std::tm* ptm = std::localtime(&tt);
std::cout << "Current time is: " << std::put_time(ptm,"%c") << std::endl;

这段代码就像是在一个连续的时间轴上拨动时间,找到那个特殊的瞬间,并用人们熟悉的方式表达出来。

进行时间运算

有时候,我们会需要对时间进行一些计算,比如计算从现在开始的某个时间点是何时。这时候,我们就像是在时间的河流中划动桨板,按照我们的意愿改变时间的前进。请看下面的代码:

std::chrono::system_clock::time_point in_an_hour = std::chrono::system_clock::now() + std::chrono::hours(1);

这就像我们在时间的河流中向前推进了一小时。

功能 代码示例
获取当前时间 std::chrono::system_clock::now();
time_point获取具体时间 std::chrono::system_clock::to_time_t(now); std::localtime(&tt); std::put_time(ptm,"%c");
进行时间运算 std::chrono::system_clock::now() + std::chrono::hours(1);

通过上述的学习和比喻,你可能已经对std::chrono::system_clock有了一些了解。接下来,我们将通过实际的示例,来深入探讨和使用这个强大的类。

2.2. std::chrono::steady_clock的用法和示例

想象一下,你正在烹饪一道需要精确时间的菜肴,你可能需要一个计时器来确保你的食物得到正确的烹饪时间。在这种情况下,你不希望因为 daylight saving time(夏令时)或者系统时钟调整等导致你的时间计算出错。在C++中,这就是std::chrono::steady_clock的用途。

std::chrono::steady_clock是一个表示物理时间流逝的时钟,不受任何外部因素(如用户修改系统时间,夏令时等)的影响。就像是你的厨房里的计时器,它按照一致的速度前进,不会突然快了或慢了。

获取当前时间

std::chrono::system_clock一样,你可以通过调用now()函数来获取当前的std::chrono::steady_clock::time_point。看下面的代码:

std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();

这就像你在开始烹饪时按下计时器的开始按钮。

计算经过的时间

在你的菜肴烹饪完成后,你可能会想知道实际的烹饪时间。同样,在C++中,你可以通过减去开始时间来得到一个std::chrono::steady_clock::duration,这个duration表示了一个时间段。看下面的代码:

std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::chrono::steady_clock::duration elapsed = end - start;

这就像你在结束烹饪时查看计时器,看你的食物烹饪了多长时间。

转换时间单位

std::chrono::steady_clock::duration给出的默认时间单位可能并不是你想要的。比如,默认可能给你的是微秒级别的时间,但你可能想要以秒为单位的时间。这时候,你就需要转换时间单位。看下面的代码:

long long elapsed_seconds = std::chrono::duration_cast<std::chrono::seconds>(elapsed).count();

这就像你将计时器的显示从“分钟:秒”转换为“总秒数”。

功能 代码示例
获取当前时间 std::chrono::steady_clock::now();
计算经过的时间 std::chrono::steady_clock::now() - start;
转换时间单位 std::chrono::duration_cast<std::chrono::seconds>(elapsed).count();

通过对std::chrono::steady_clock的学习,你可以像烹饪大师一样掌握时间,在编程的厨房里烹饪出美味的代码。

2.3. std::chrono::high_resolution_clock的用法和示例

考虑到现实生活中,我们有时候需要对时间进行极度精确的测量,比如科学实验或者高精度事件的时间戳,std::chrono::high_resolution_clock就像是我们手中的精密计时器,提供了尽可能高的时间分辨率。

std::chrono::high_resolution_clock是一个特殊的时钟,它提供了最高的可用时间分辨率。它通常是std::chrono::system_clockstd::chrono::steady_clock中的一个类型别名,具体取决于具体平台和库实现。

获取当前时间

使用std::chrono::high_resolution_clock获取当前时间就像我们按下精密计时器的按钮,记录下现在的时刻。如下所示:

std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();

计算经过的时间

我们可以通过比较两个时间点来计算经过的时间,就像精密计时器可以为我们提供精确到纳秒级别的时间间隔。请参考以下代码:

std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
std::chrono::high_resolution_clock::duration elapsed = end - start;

转换时间单位

和其他时钟一样,我们可能需要将std::chrono::high_resolution_clock::duration的时间单位进行转换,使其满足我们的需求。例如,我们可以将时间间隔转换为微秒,如下所示:

long long elapsed_microseconds = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();

这就像你的精密计时器可以以各种不同的时间单位来显示测量结果。

功能 代码示例
获取当前时间 std::chrono::high_resolution_clock::now();
计算经过的时间 std::chrono::high_resolution_clock::now() - start;
转换时间单位 std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();

通过理解和应用std::chrono::high_resolution_clock,我们可以像使用精密计时器一样,在编程世界里精确地测量和控制时间。

3. 获取时间戳 (Obtaining Timestamps)

3.1. 使用std::chrono::system_clock::now获取当前时间戳

在我们的日常生活中,我们依赖时间去安排我们的日程,设置闹钟,甚至计算烹饪的时间。在编程的世界里,时间同样重要,而std::chrono::system_clock::now就是我们获取当前时间戳的工具。

auto now = std::chrono::system_clock::now();

这就像你打开手机看看现在几点一样简单。从心理学的角度看,人类对时间的感知并不准确,我们的大脑经常会过度估计或低估实际的时间流逝。但是,计算机是完全精确的,它们对时间的把握可以精确到微秒级。

获取当前时间点的详细日期和时间

有时候,我们需要知道更多的信息,比如当前的具体日期和时间。为此,我们可以使用C++的time_point转换为time_t,然后再使用标准库中的localtime函数来获取详细信息。

auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);
std::tm* now_tm = std::localtime(&t);

这就像你从简单地知道现在是下午转变为知道现在是下午3点25分。在编程中,这个功能非常有用,比如在记录事件或者在debug中打印出具体的时间点。

获取时间戳的应用

获取时间戳的应用广泛而且重要。例如,在性能调优时,你需要知道代码执行的具体时间,或者在日志记录时,你需要记录事件发生的准确时间。你可以将std::chrono::system_clock::now想象成一个永不停息的时钟,它可以精确地告诉你现在的时间。当你需要测量一段代码的运行时间时,只需要在代码开始和结束时各取一个时间戳,然后将它们相减,就可以得到运行时间。

人们对于时间的需求,从基本的查看时间,到计算间隔,再到记录精确的时间戳,编程语言都提供了强大的工具来满足。在C++中,std::chrono::system_clock::now就是这样一个强大的工具。

3.2. 时间戳的转换和应用

在许多场景中,我们需要将时间戳(Timestamp)转换为更容易理解和使用的格式。同时,我们可能需要在不同的时间单位之间进行转换。好在C++中的std::chrono库提供了丰富的函数和类来满足这些需求。

时间戳转换为具体日期和时间

获取的时间戳通常是从某个参考点(通常是Epoch,1970年1月1日)开始计算的毫秒数。为了将这个时间戳转换为人们习惯的日期和时间格式,我们可以利用std::chrono库提供的接口将std::chrono::system_clock::time_point转换为std::time_t,然后使用C语言的标准库函数将其转换为struct tm,最后可以使用std::strftimestruct tm转换为字符串。

auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);
std::tm* now_tm = std::localtime(&t);
char buffer[80];
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", now_tm);
std::cout << "Current time: " << buffer << std::endl;

这就像我们将一个长篇的数字字符串(比如一串电话号码)转换成更容易理解的格式,比如在适当的位置添加了短横线。

时间单位的转换

std::chrono库中,我们可以很容易地在不同的时间单位之间转换。这种转换类似于我们在长度、重量等不同的物理单位之间进行转换。比如,我们可以很容易地将std::chrono::seconds转换为std::chrono::milliseconds

std::chrono::seconds sec(1);
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(sec);

通过这样的方式,我们可以将代码中的时间管理变得更加灵活,满足各种精度的需求。

时间戳在实际问题中的应用示例

在实际的编程问题中,时间戳的应用是广泛的。例如,我们可以使用时间戳来度量一段代码的执行时间,也可以在日志记录中添加时间戳,来追踪事件发生的时间。

auto start = std::chrono::high_resolution_clock::now();
// Code to be measured.
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = end - start;
std::cout << "Elapsed time: " << elapsed.count() << "ns\n";

在这个示例中,我们使用std::chrono::high_resolution_clock::now获取代码开始和结束的时间,然后计算出代码执行所需的时间。这就像我们使用秒表来测量运动员的速度一样,可以帮助我们更好地理解和优化代码的性能。

3.3. 时间戳在实际问题中的应用示例

在软件开发中,时间戳的使用几乎无处不在,例如性能测量、日志记录、时间戳计算等。在这一部分,我们将探讨一些常见的时间戳应用示例。

性能测量

当你需要优化代码以提高执行速度时,时间戳的使用就显得尤为重要。可以在代码块的开始和结束处获取时间戳,然后计算执行时间:

auto start = std::chrono::high_resolution_clock::now();
// ... Your code to measure ...
auto stop = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
std::cout << "Time taken by function: " << duration.count() << " microseconds" << std::endl;

这就像你使用秒表来测量一个运动员完成赛跑所需的时间,从而分析他的运动表现并寻找改进的地方。

日志记录

在日志记录中,时间戳可以帮助我们跟踪事件的发生时间。当我们查看日志以调试或理解系统行为时,知道事件发生的准确时间通常非常有用。

auto now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::cout << "Log event happened at " << std::ctime(&now_c);

时间戳计算

有时候,我们需要进行基于时间的计算,比如计算两个日期之间的差值,或者添加特定的时间量。这时,我们可以使用std::chrono::duration来执行这些操作。

auto t1 = std::chrono::system_clock::now();
// ... some code ...
auto t2 = std::chrono::system_clock::now();
auto duration = t2 - t1;
std::cout << "Duration between t1 and t2: " << duration.count() << " seconds\n";

以上这些只是时间戳在实际问题中的一些应用示例。使用C++的std::chrono库,你可以进行更复杂和高级的时间处理操作。

4. 计时器的实现

4.1 使用std::chrono库实现基本计时器

在编程中,我们经常需要测量代码的执行时间,比如,对比两种算法的性能或者查找代码中的性能瓶颈。C++的std::chrono库为我们提供了这样的工具。

基本计时器实现

我们首先需要理解,计时器 (Timer) 可以被比作是心理学中的“定时器”。当人们需要专注于某项任务时,他们会设定一个定时器来保持专注并度量时间。这与编程中使用计时器的动机非常相似。我们希望对程序的运行时间有个准确的度量,以此来优化我们的代码。

在C++中,一个基本的计时器可以通过std::chrono库中的high_resolution_clock来实现。代码示例如下:

#include <iostream>
#include <chrono>
int main() {
    auto start = std::chrono::high_resolution_clock::now(); // 开始计时
    // 你需要测量的代码块
    auto end = std::chrono::high_resolution_clock::now(); // 结束计时
    std::chrono::duration<double> diff = end-start; // 计算时间差
    std::cout << "Code executed in " << diff.count() << " seconds" << std::endl;
    return 0;
}

在上述代码中,startend都是std::chrono::time_point对象,表示一个时间点。high_resolution_clock::now()函数返回当前时间点。然后,我们通过计算endstart之间的差值,得到代码执行的时间。最后,使用count()函数以秒为单位打印出运行时间。

这就像是你设定了一个心理学中的定时器,你知道何时开始,何时结束,并且你可以测量这段时间。

在接下来的章节中,我们将详细介绍更高级的计时器功能。

4.2 高级计时器功能与实现(例如:暂停、重置)

计时器的暂停与恢复

在现实生活中,我们的计时器有时需要暂停并稍后恢复。比如说,你正在烹饪并根据食谱倒计时,突然有人敲门,你需要停下来应对。在这种情况下,你会暂停计时器,然后在事情处理完后恢复计时。同样,我们在编程中也会遇到类似的情况。

在C++中,我们可以通过以下方法来实现计时器的暂停和恢复功能:

#include <iostream>
#include <chrono>
class Timer {
    private:
        bool running;
        std::chrono::time_point<std::chrono::high_resolution_clock> start_time, end_time;
    public:
        Timer() : running(false) {}
        void start() {
            running = true;
            start_time = std::chrono::high_resolution_clock::now();
        }
        void stop() {
            if (running) {
                end_time = std::chrono::high_resolution_clock::now();
                running = false;
            }
        }
        double elapsed() {
            if (running) {
                return std::chrono::duration<double>(std::chrono::high_resolution_clock::now() - start_time).count();
            }
            else {
                return std::chrono::duration<double>(end_time - start_time).count();
            }
        }
        void reset() {
            running = false;
        }
};
int main() {
    Timer timer;
    timer.start();
    // Some code
    timer.stop();
    std::cout << "Elapsed time: " << timer.elapsed() << " seconds." << std::endl;
    // Continue with the timer
    timer.start();
    // Some code
    timer.stop();
    std::cout << "Total elapsed time: " << timer.elapsed() << " seconds." << std::endl;
    return 0;
}

上述代码中定义了一个名为Timer的类,其中包含了start(), stop(), elapsed(), 和 reset()这些方法。start()用于开始或恢复计时,stop()用于暂停计时,elapsed()用于获取已过去的时间,而reset()则用于重置计时器。这就像我们生活中使用的实际计时器一样,能进行开始、暂停、恢复和重置等操作。

通过以上方式,我们不仅增强了计时器的功能,更为我们的编程工作提供了更灵活的时间度量工具。


C++ std::chrono库使用指南 (实现C++ 获取日期,时间戳,计时等功能)(二)https://developer.aliyun.com/article/1465310

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
2月前
|
算法 C++ 容器
C++标准库(速查)总结
C++标准库(速查)总结
82 6
|
2月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
120 10
|
2月前
|
存储 C++ UED
【实战指南】4步实现C++插件化编程,轻松实现功能定制与扩展
本文介绍了如何通过四步实现C++插件化编程,实现功能定制与扩展。主要内容包括引言、概述、需求分析、设计方案、详细设计、验证和总结。通过动态加载功能模块,实现软件的高度灵活性和可扩展性,支持快速定制和市场变化响应。具体步骤涉及配置文件构建、模块编译、动态库入口实现和主程序加载。验证部分展示了模块加载成功的日志和配置信息。总结中强调了插件化编程的优势及其在多个方面的应用。
374 67
|
16天前
|
算法 网络协议 数据挖掘
C++是一种功能强大的编程语言,
C++是一种功能强大的编程语言,
46 14
|
7天前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
28 0
|
2月前
|
存储 C++
【C++篇】C++类和对象实践篇——从零带你实现日期类的超详细指南
【C++篇】C++类和对象实践篇——从零带你实现日期类的超详细指南
35 2
|
2月前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
83 5
|
2月前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
76 1
|
2月前
|
C++
【C++】实现日期类相关接口(三)
【C++】实现日期类相关接口
|
2月前
|
C++
C++番外篇——日期类的实现
C++番外篇——日期类的实现
148 1