当前位置: 首页 > article >正文

C++日期和时间库

目录

1.引用

2.chrono库

2.1.Duration

2.2.Clock

2.3.TimePoint

2.4.Calendar(c++20)

3.ctime库

4.常见用法

4.1. 获取当前系统时间戳

4.2.计算时间间隔

4.3.格式化输出

4.4.字符串转化为时间戳

4.5.时间戳转为time_point类型

4.6.字面量使用

5.总结


1.引用

        unix timestamp(时间戳): 时间戳是计算中广泛使用的日期和时间表示形式。它通过自1970年1月1(Unix 纪元)00:00:00 UTC以来经过的秒数(秒是毫秒、微妙、纳秒的总称)来测量时间,没有因闰秒而进行调整。

        C++中处理时间的库主要包括<chrono><ctime>。

2.chrono

  <chrono>库是C++11引入的一个标准库,专门用于处理时间点、时间间隔和时钟操作。它提供了高精度的时间点和时长表示,以及时间相关的函数和操作。C++20新增Calendar。

        主要包含以下四种类型:

  • Duration:表示一个时间间隔,单位可以是秒、毫秒、微秒等。
  • Time Point:表示一个时间点,通常基于某个时钟。
  • Clock:提供当前时间,通常有三种时钟类型:系统时钟(system_clock)、高精度时钟(high_resolution_clock)和稳定时钟(steady_clock)。
  • Calendar(c++20)

2.1.Duration

        Duration(时间间隔):表示一段时间的长度,这个类模板是时间间隔的抽象表示,可以存储任何时间单位的间隔,比如秒、毫秒、分钟等。std::chrono::duration 允许程序员进行时间间隔的计算,比如加法、减法、比较等,并且可以与时间点(如 std::chrono::time_point)结合使用来表示具体的时间。

        std::chrono::duration 模板类接受两个参数:

  1. rep:表示时间间隔的数值类型,通常是整数类型,如 intlong 或 long long
  2. period:表示时间间隔的单位,是一个编译时常量表达式,通常是 std::ratio 类型。std::ratio 是一个模板类,用于表示两个整数的比率。标准库中定义了几个常用的 std::ratio 类型的别名,如 std::nano(表示纳秒,即10^-9秒)、std::micro(表示微秒,即10^-6秒)、std::milli(表示毫秒,即10^-3秒)、std::seconds(表示秒)、std::minutes(表示分钟)、std::hours(表示小时)等。
//define in std::chrono namspace
/// `chrono::duration` represents a distance between two points in time
template<typename _Rep, typename _Period = ratio<1>>
class duration;
//库中预先定义了常用的时间长度

//示例
std::chrono::duration<int, std::milli> duration1(500);
std::chrono::duration<double, std::nano> duration2(1.5);
std::chrono::duration<int, std::micro> duration3 = duration1 + duration2; // 表示501.5微秒

std::chrono::duration<int, std::milli> duration4 = duration1 * 2; // 表示1000毫秒
std::chrono::duration<double, std::milli> duration5 = duration2 / 2; // 表示0.75毫秒

为了方便使用,标准库为常见的时间单位提供了 std::chrono::duration 的特化版本:

  • 纳秒(nanoseconds):std::chrono::nanoseconds
  • 微秒(microseconds):std::chrono::microseconds
  • 毫秒(milliseconds):std::chrono::milliseconds
  • 秒(seconds):std::chrono::seconds
  • 分钟(minutes):std::chrono::minutes
  • 小时(hours):std::chrono::hours

这些特化版本简化了时间单位的表示,使得程序员无需手动指定 rep 和 period 参数。

示例如下:

#include <iostream>  
#include <chrono>  
  
int main() {  
    // 定义一个表示5秒的duration  
    std::chrono::duration<int, std::ratio<1>> five_seconds(5);  
      
    // 定义一个表示200毫秒的duration  
    std::chrono::milliseconds two_hundred_milliseconds(200);  
      
    // 将秒转换为毫秒  
    auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(five_seconds);  
      
    std::cout << "5秒等于 " << milliseconds.count() << " 毫秒。" << std::endl;  
      
    return 0;  
}

在这个例子中,我们定义了两个 std::chrono::duration 对象,一个表示5秒,另一个表示200毫秒。然后,我们使用 std::chrono::duration_cast 将5秒转换为毫秒,并输出结果。

2.2.Clock

  • 时钟(clock):表示一个可以测量时间的设备,提供了当前时间点(now)和时间点之间的差值(time_since_epoch)等方法。chrono库提供了三种时钟,分别是:
    • 系统时钟(system_clock):表示当前系统范围的实时日历时钟,通常与系统的钟同步。它可以用于表示日期和时间,以及与其他系统交互。
    • 稳定时钟(steady_clock):表示一个单调递增的时钟,不受系统时间的调整或修改影响。它可以用于测量时间间隔,以及实现定时器和延时等功能。
    • 高分辨率时钟(high_resolution_clock):表示一个具有最高精度的时钟,通常是系统时钟或稳定时钟的别名(using high_resolution_clock = system_clock;)。它可以用于测量极短的时间间隔,以及实现性能分析等功能。
  • now --成员函数,放回当前时钟的时间点

1) std::chrono::system_clock

它表示系统范围的实时时钟。这个时钟类提供了访问系统当前时间点的功能,并且允许将时间点转换为 time_t 类型(通常用于表示日历时间)以及进行时间点之间的算术运算。使用 std::chrono::system_clock::now() 可以获取当前的系统时间点,返回类型是 std::chrono::system_clock::time_point

示例代码:

#include <iostream>  
#include <chrono>  
#include <ctime>  
  
int main() {  
    // 获取当前系统时间点  
    auto now = std::chrono::system_clock::now();  
      
    // 将当前系统时间点转换为 time_t 类型  
    std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);  
      
    // 将 time_t 类型转换为 tm 结构,用于格式化输出  
    std::tm* now_tm = std::localtime(&now_time_t);  
      
    // 输出当前时间  
    std::cout << "当前时间是: "   
              << (now_tm->tm_year + 1900) << "-"   
              << (now_tm->tm_mon + 1) << "-"   
              << now_tm->tm_mday << " "   
              << now_tm->tm_hour << ":"   
              << now_tm->tm_min << ":"   
              << now_tm->tm_sec   
              << std::endl;  
      
    // 创建一个表示10秒后的时间点  
    auto ten_seconds_later = now + std::chrono::seconds(10);  
      
    // 输出10秒后的时间(注意:这里只是简单地将秒数加上,没有考虑闰秒等复杂情况)  
    std::time_t ten_seconds_later_time_t = std::chrono::system_clock::to_time_t(ten_seconds_later);  
    std::tm* ten_seconds_later_tm = std::localtime(&ten_seconds_later_time_t);  
    std::cout << "10秒后的时间是: "   
              << (ten_seconds_later_tm->tm_year + 1900) << "-"   
              << (ten_seconds_later_tm->tm_mon + 1) << "-"   
              << ten_seconds_later_tm->tm_mday << " "   
              << ten_seconds_later_tm->tm_hour << ":"   
              << ten_seconds_later_tm->tm_min << ":"   
              << ten_seconds_later_tm->tm_sec   
              << std::endl;  
      
    return 0;  
}

在这个例子中,我们获取了当前的系统时间点,并将其转换为 time_t 类型,然后格式化为人类可读的日期和时间格式输出。接着,我们创建了一个表示当前时间点之后10秒的新时间点,并同样进行了格式化输出。需要注意的是,这里的10秒后的时间计算是简单的秒数相加,并没有考虑诸如闰秒等复杂的时间调整情况。

2) std::chrono::steady_clock

它表示一个稳定的、单调递增的时钟。这个时钟类的主要特点是它不受系统时间调整(如用户手动更改系统时间)的影响,因此非常适合用于测量时间间隔,例如性能分析、计时器等场景。使用 std::chrono::steady_clock::now() 可以获取当前的稳定时间点,返回类型是 std::chrono::steady_clock::time_point

示例如下:

#include <iostream>  
#include <chrono>  
  
int main() {  
    // 记录开始时间  
    auto start = std::chrono::steady_clock::now();  
      
    // 在这里执行一些代码,例如循环计算  
    for (int i = 0; i < 1000000; ++i) {  
        // 一些计算或操作  
    }  
      
    // 记录结束时间  
    auto end = std::chrono::steady_clock::now();  
      
    // 计算执行时间并转换为毫秒  
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);  
      
    // 输出执行时间  
    std::cout << "Execution time: " << duration.count() << " milliseconds" << std::endl;  
      
    return 0;  
}

在这个例子中,我们使用 std::chrono::steady_clock 来测量一个循环计算代码段的执行时间,并将结果转换为毫秒后输出。由于 std::chrono::steady_clock 的稳定性和单调性,我们可以确保测量得到的时间间隔是准确的。

3) std::chrono::steady_clock

它旨在提供一个具有最高可用精度的时钟。然而,需要注意的是,std::chrono::high_resolution_clock 并不总是代表实际的最高分辨率时钟,而是代表在当前实现中可用的最高分辨率时钟。换句话说,它的行为可能因编译器和平台而异。使用 std::chrono::high_resolution_clock::now() 可以获取当前的高精度时间点,返回类型是 std::chrono::high_resolution_clock::time_point

示例如下:

#include <iostream>  
#include <chrono>  
  
int main() {  
    // 记录开始时间  
    auto start = std::chrono::high_resolution_clock::now();  
      
    // 在这里执行一些代码,例如循环计算  
    for (int i = 0; i < 1000000; ++i) {  
        // 一些计算或操作  
    }  
      
    // 记录结束时间  
    auto end = std::chrono::high_resolution_clock::now();  
      
    // 计算执行时间并转换为纳秒(注意:这里可能会因为精度问题而有所偏差)  
    auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);  
      
    // 输出执行时间(转换为毫秒以便更易于理解,尽管我们是以纳秒为单位测量的)  
    std::cout << "Execution time: " << duration.count() / 1e6 << " milliseconds" << std::endl;  
      
    return 0;  
}

在这个例子中,我们使用 std::chrono::high_resolution_clock 来测量一个循环计算代码段的执行时间,并将结果转换为毫秒后输出(尽管我们实际上是以纳秒为单位测量的,但为了方便理解,我们将其转换为毫秒)。然而,需要注意的是,由于 std::chrono::high_resolution_clock 的精度可能受到硬件和操作系统的限制,因此测量得到的时间可能会有一定的偏差。

2.3.TimePoint

  • 时间点(time_point):表示一个特定时刻,由一个时钟和一个时间间隔组成。例如,std::chrono::system_clock::now()表示系统时钟的当前时间点,std::chrono::steady_clock::now()表示稳定时钟的当前时间点,等等。chrono库还提供了一些常用的时间点别名,如std::chrono::system_clock::time_pointstd::chrono::steady_clock::time_pointstd::chrono::high_resolution_clock::time_point等。
  • time_since_epoch 返回到epoch的时间间隔Duration

2.4.Calendar(c++20)

  • 日期类,用来对日期时间进行比较。
  using namespace std::chrono_literals;
  //使用字面量 ""y ""d(C++20) 
  auto ymd1 = 2023y / std::chrono::November / 10d; // 2023-11-10
  auto ymd2 = 2023y / std::chrono::September / 10d; // 2023-9-10
  if(ymd1 > ymd2) {
 // ymd1 > ymd2
    std::cout << "ymd1 > ymd2" << std::endl;
  }

3.ctime库

<ctime>库提供了与时间相关的类型和函数,包括对time_t类型的操作,以及转换时间和日期的函数。它使用time_t类型来表示时间点,并提供了将时间转换为字符串的函数。

  1. 核心类型

    • clock_t:用于表示从程序启动以来经过的CPU时间。
    • time_t:表示从Unix纪元(1970年1月1日00:00:00 UTC)以来的秒数。
    • tm结构:表示本地或格林威治标准时间的结构。
  2. 常用函数

    • time(NULL):获取当前时间,返回time_t类型的值。
    • localtime(&time_t):将time_t类型的时间转换为本地时间tm结构。
    • gmtime(&time_t):将time_t类型的时间转换为UTC时间tm结构。
    • asctime(&tm):将tm结构转换为字符串形式。
    • strftime(char*, size_t, const char*, const tm*):格式化时间。
  3. 常见用法

    • 获取当前时间并转换为本地时间:std::tm* local_time = std::localtime(&now);
    • 格式化输出时间:char buffer[80]; std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local_time);

示例如下:

#include <iostream>  
#include <ctime>  
  
int main() {  
    // 获取当前时间的 time_t 表示  
    time_t currentTime = time(nullptr);  
      
    // 将 time_t 转换为 tm 结构体  
    tm* localTime = localtime(&currentTime);  
      
    // 打印日期和时间  
    std::cout << "Current date and time: "  
              << (localTime->tm_year + 1900) << '-'  
              << (localTime->tm_mon + 1) << '-'  
              << localTime->tm_mday << ' '  
              << localTime->tm_hour << ':'  
              << localTime->tm_min << ':'  
              << localTime->tm_sec  
              << std::endl;  
      
    return 0;  
}

请注意,tm_year 成员表示自1900年以来的年数,因此需要加上1900来得到实际的年份。同样地,tm_mon 成员表示月份(从0开始计数),因此需要加上1来得到实际的月份。

4.常见用法

4.1. 获取当前系统时间戳

  //获取系统时间戳,实例化系统时钟
  std::chrono::system_clock clock;
  std::chrono::system_clock::time_point now = clock.now();
  std::chrono::_V2::system_clock::duration d = now.time_since_epoch();
  //纳秒单位时间戳
  std::cout << "timestamp: " << d.count() << std::endl;
  //转化为秒单位
  std::chrono::seconds t = std::chrono::duration_cast<std::chrono::seconds>(d);
  std::cout << "sec: " << t.count() << std::endl;
 
 
//简化写法
//  std::chrono::system_clock clock;
//  auto t = std::chrono::duration_cast<std::chrono::seconds>(
//  			clock.now().time_since_epoch()).count();
//  std::cout << "sec: " << t << std::endl;

4.2.计算时间间隔

  const auto start = std::chrono::high_resolution_clock::now();
  //do something
  std::this_thread::sleep_for(std::chrono::seconds(1));
  const auto end = std::chrono::high_resolution_clock::now();

  auto duration = start - end;
  //1000118000ns 1000ms 1s 
  std::cout << duration.count() << "ns " << 
    std::chrono::duration_cast<std::chrono::milliseconds>(duration).count()<<  "ms " <<
    std::chrono::duration_cast<std::chrono::seconds>(duration).count() << "s " <<
    std::endl;

4.3.格式化输出

  auto now = std::chrono::system_clock::now();
  std::time_t now_c = std::chrono::system_clock::to_time_t(now);
  //cur time Thu Nov  9 23:42:38 2023
  std::cout << "cur time " << std::ctime(&now_c) << std::endl;
  //或者转化为当地时间
  //自定义格式输出
  tm * t = std::localtime(&now_c);
	char buffer[80];
	std::strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", t);
   //cur time: 2023-11-09 23:42:38
  std::cout << "cur time: " << buffer << std::endl;

4.4.字符串转化为时间戳

time_t GetUnixSecFromStr(const std::string &raw_time) {
	std::istringstream ss(raw_time);
	std::tm tm{};
	
	ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S"); //ex:2023-12-22 19:22:23
	return std::mktime(&tm);
}

4.5.时间戳转为time_point类型

time_t time;
auto t_point = std::chrono::system_clock::from_time_t(time);

4.6.字面量使用

  //使用字面量 c++20 ""y ""d  c++11 支持 ""h ""min ""s ""ms ""us
  using namespace std::chrono_literals;//在此空间定义字面量
  auto s = 60s; // 相当于std::chrno::seconds(60)
  std::cout << "sec: " << s.count() << std::endl;
  auto min = 1min; // 相当于std::chrono::minutes(1):
  std::cout << "min: " << min.count() << std::endl;

5.总结

       std::chrono时间库在不同平台上都具备良好的兼容性,无论是Windows、Linux还是其他操作系统,都可以使用该库进行时间处理,使代码具备良好的可移植性。该库提供了丰富的时间单位和精度选项,适应不同场景下的时间计算需求。无论是秒、毫秒、微秒还是纳秒的时间单位,都可以很方便地应用于代码中。而且std::chrono时间库提供了不同类型的时钟,如系统时钟(system_clock)、稳定时钟(steady_clock)和高分辨率时钟(high_resolution_clock),可以根据具体需求选择合适的时钟类型。

进一步学习和参考C++ std::chrono时间库的推荐资源:

  1. 官方文档:可以查阅C++标准库的官方文档,其中包含了std::chrono时间库的详细说明和示例代码。官方文档可以帮助深入了解每个类、函数和成员的用法和语义。
  2. C++ Reference:C++ Reference是一个权威的C++参考网站,提供了std::chrono时间库的详细文档和示例代码。可以在该网站上查找特定类、函数或成员,并了解它们的用法和示例。
  3. 推荐书籍:《C++ Concurrency in Action: Practical Multithreading》和《Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14》。

http://www.kler.cn/a/377861.html

相关文章:

  • 知乎信息流广告推广开户流程及攻略!
  • 从 vue 源码看问题 — vue 编译器的解析
  • 深入Pillow:处理图像下载中的意外挑战
  • 从0开始搭建一个生产级SpringBoot2.0.X项目(八)SpringBoot 使用Redis
  • 群控系统服务端开发模式-应用开发-业务架构逻辑开发第一轮测试
  • 在线PDF转图片网站
  • Java 数据结构及其在日常业务中的应用!
  • 【代码随想录Day57】图论Part08
  • Rust语言有哪些数据类型?
  • linux super键是什么_linux终端的快捷命令汇总
  • Linux上本地部署KubeSphere与cpolar实现远程管理和监控集群
  • 在centos中安装cmake
  • JVM 类加载机制详解
  • redis详细教程(7.哨兵)
  • 为数据集而生的 SQL 控制台
  • 私有化视频平台EasyCVR视频汇聚平台接入RTMP协议推流为何无法播放?
  • 【LeetCode】每日一题 2024_11_2 使两个整数相等的位更改次数(位运算/模拟)
  • OPENAI官方prompt文档解析
  • 基于知识引导提示的因果概念提取(论文复现)
  • linux 系统扩容
  • (二 上)VB 2010 设计初步
  • Apache Hive 通过Docker快速入门
  • 华为OD机试真题-组装最大可靠性设备-2024年OD统一考试(E卷)
  • Linux下安装Redis基本步骤
  • 总结一些高级的SQL技巧
  • 收音机天线的耦合方式