Skip to content

C++ 日期 & 时间

C++ 提供了多种处理日期和时间的方式,包括 C 风格的时间函数和 C++11 引入的<chrono>库。

1. C 风格的时间函数

C 风格的时间函数定义在<ctime>头文件中。

1.1 获取当前时间

cpp
#include <iostream>
#include <ctime>

int main() {
    time_t now = time(nullptr);
    std::cout << "当前时间(时间戳): " << now << std::endl;

    return 0;
}

1.2 将时间戳转换为可读格式

cpp
#include <iostream>
#include <ctime>

int main() {
    time_t now = time(nullptr);

    // 转换为本地时间
    struct tm* local_time = localtime(&now);

    // 格式化输出
    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local_time);
    std::cout << "本地时间: " << buffer << std::endl;

    return 0;
}

1.3 常用的时间函数

函数描述
time(nullptr)获取当前时间的时间戳
localtime(&now)将时间戳转换为本地时间
gmtime(&now)将时间戳转换为 UTC 时间
strftime(buffer, size, format, tm)格式化时间
asctime(tm)将时间转换为字符串
ctime(&now)将时间戳转换为字符串

示例

cpp
#include <iostream>
#include <ctime>

int main() {
    time_t now = time(nullptr);

    // asctime
    std::cout << "asctime: " << asctime(localtime(&now));

    // ctime
    std::cout << "ctime: " << ctime(&now);

    // strftime
    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local_time);
    std::cout << "strftime: " << buffer << std::endl;

    return 0;
}

2. C++11 <chrono>

<chrono>库是 C++11 引入的,提供了更现代、更类型安全的时间处理方式。

2.1 时钟

<chrono>库提供了三种时钟:

时钟描述
std::chrono::system_clock系统时钟,表示当前时间
std::chrono::steady_clock稳定时钟,单调递增
std::chrono::high_resolution_clock高精度时钟

示例

cpp
#include <iostream>
#include <chrono>

int main() {
    // 获取当前时间
    auto now = std::chrono::system_clock::now();

    // 转换为时间戳
    auto timestamp = std::chrono::system_clock::to_time_t(now);
    std::cout << "当前时间: " << std::ctime(&timestamp);

    return 0;
}

2.2 时间点

时间点表示特定的时间点。

cpp
#include <iostream>
#include <chrono>

int main() {
    // 获取当前时间点
    auto now = std::chrono::system_clock::now();

    // 获取过去的时间点
    auto past = now - std::chrono::hours(1);

    // 转换为时间戳
    auto timestamp = std::chrono::system_clock::to_time_t(past);
    std::cout << "一小时前的时间: " << std::ctime(&timestamp);

    return 0;
}

2.3 时间段

时间段表示时间的长度。

cpp
#include <iostream>
#include <chrono>

int main() {
    // 定义时间段
    std::chrono::hours h(1);
    std::chrono::minutes m(30);
    std::chrono::seconds s(45);
    std::chrono::milliseconds ms(500);
    std::chrono::microseconds us(100);
    std::chrono::nanoseconds ns(50);

    std::cout << "1 小时 = " << h.count() << " 小时" << std::endl;
    std::cout << "30 分钟 = " << m.count() << " 分钟" << std::endl;
    std::cout << "45 秒 = " << s.count() << " 秒" << std::endl;
    std::cout << "500 毫秒 = " << ms.count() << " 毫秒" << std::endl;
    std::cout << "100 微秒 = " << us.count() << " 微秒" << std::endl;
    std::cout << "50 纳秒 = " << ns.count() << " 纳秒" << std::endl;

    return 0;
}

2.4 时间段的运算

cpp
#include <iostream>
#include <chrono>

int main() {
    // 时间段的加法
    auto total = std::chrono::hours(1) + std::chrono::minutes(30);
    std::cout << "1 小时 30 分钟 = " << std::chrono::duration_cast<std::chrono::minutes>(total).count() << " 分钟" << std::endl;

    // 时间段的减法
    auto diff = std::chrono::hours(2) - std::chrono::minutes(30);
    std::cout << "2 小时 - 30 分钟 = " << std::chrono::duration_cast<std::chrono::minutes>(diff).count() << " 分钟" << std::endl;

    return 0;
}

2.5 时间段的转换

cpp
#include <iostream>
#include <chrono>

int main() {
    // 定义 1 小时
    std::chrono::hours h(1);

    // 转换为分钟
    auto minutes = std::chrono::duration_cast<std::chrono::minutes>(h);
    std::cout << "1 小时 = " << minutes.count() << " 分钟" << std::endl;

    // 转换为秒
    auto seconds = std::chrono::duration_cast<std::chrono::seconds>(h);
    std::cout << "1 小时 = " << seconds.count() << " 秒" << std::endl;

    return 0;
}

3. 计算时间差

3.1 使用 C 风格的时间函数

cpp
#include <iostream>
#include <ctime>

int main() {
    time_t start = time(nullptr);

    // 模拟耗时操作
    volatile int dummy = 0;
    for (int i = 0; i < 1000000000; i++) {
        dummy += i;
    }
    // 使用dummy变量防止编译器优化
    (void)dummy;

    time_t end = time(nullptr);
    double elapsed = difftime(end, start);

    std::cout << "耗时: " << elapsed << " 秒" << std::endl;

    return 0;
}

3.2 使用 <chrono>

cpp
#include <iostream>
#include <chrono>

int main() {
    auto start = std::chrono::high_resolution_clock::now();

    // 模拟耗时操作
    volatile int dummy = 0;
    for (int i = 0; i < 1000000000; i++) {
        dummy += i;
    }
    // 使用dummy变量防止编译器优化
    (void)dummy;

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

    std::cout << "耗时: " << duration.count() << " 毫秒" << std::endl;

    return 0;
}

4. 格式化时间

4.1 使用 strftime

cpp
#include <iostream>
#include <ctime>

int main() {
    time_t now = time(nullptr);
    struct tm* local_time = localtime(&now);

    char buffer[80];

    // 格式化为 YYYY-MM-DD HH:MM:SS
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local_time);
    std::cout << "格式化时间: " << buffer << std::endl;

    // 格式化为 MM/DD/YYYY
    strftime(buffer, sizeof(buffer), "%m/%d/%Y", local_time);
    std::cout << "格式化时间: " << buffer << std::endl;

    // 格式化为 Weekday Month Day HH:MM:SS Year
    strftime(buffer, sizeof(buffer), "%A %B %d %H:%M:%S %Y", local_time);
    std::cout << "格式化时间: " << buffer << std::endl;

    return 0;
}

4.2 strftime 格式说明符

说明符描述示例
%Y四位数的年份2026
%m两位数的月份(01-12)03
%d两位数的日期(01-31)15
%H24 小时制的小时(00-23)14
%M分钟(00-59)30
%S秒(00-60)45
%A星期几的完整名称Friday
%B月份的完整名称March
%I12 小时制的小时(01-12)02
%pAM 或 PMPM

5. 示例:综合运用

现在,让我们看一个综合运用各种时间操作的例子:

cpp
#include <iostream>
#include <ctime>
#include <chrono>

int main() {
    // C 风格的时间函数
    std::cout << "C 风格的时间函数:" << std::endl;
    time_t now = time(nullptr);
    std::cout << "当前时间(时间戳): " << now << std::endl;

    struct tm* local_time = localtime(&now);
    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", local_time);
    std::cout << "本地时间: " << buffer << std::endl;
    std::cout << std::endl;

    // C++11 <chrono> 库
    std::cout << "C++11 <chrono> 库:" << std::endl;
    auto chrono_now = std::chrono::system_clock::now();
    auto timestamp = std::chrono::system_clock::to_time_t(chrono_now);
    std::cout << "当前时间: " << std::ctime(&timestamp);
    std::cout << std::endl;

    // 时间段
    std::cout << "时间段:" << std::endl;
    std::chrono::hours h(1);
    std::chrono::minutes m(30);
    std::chrono::seconds s(45);
    std::cout << "1 小时 = " << h.count() << " 小时" << std::endl;
    std::cout << "30 分钟 = " << m.count() << " 分钟" << std::endl;
    std::cout << "45 秒 = " << s.count() << " 秒" << std::endl;
    std::cout << std::endl;

    // 时间段的运算
    std::cout << "时间段的运算:" << std::endl;
    auto total = h + m;
    std::cout << "1 小时 + 30 分钟 = " << std::chrono::duration_cast<std::chrono::minutes>(total).count() << " 分钟" << std::endl;
    std::cout << std::endl;

    // 时间段的转换
    std::cout << "时间段的转换:" << std::endl;
    auto minutes = std::chrono::duration_cast<std::chrono::minutes>(h);
    auto seconds = std::chrono::duration_cast<std::chrono::seconds>(h);
    std::cout << "1 小时 = " << minutes.count() << " 分钟" << std::endl;
    std::cout << "1 小时 = " << seconds.count() << " 秒" << std::endl;
    std::cout << std::endl;

    // 计算时间差
    std::cout << "计算时间差:" << std::endl;
    auto start = std::chrono::high_resolution_clock::now();

    // 模拟耗时操作
    volatile int dummy = 0;
    for (int i = 0; i < 1000000000; i++) {
        dummy += i;
    }
    // 使用dummy变量防止编译器优化
    (void)dummy;

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    std::cout << "耗时: " << duration.count() << " 毫秒" << std::endl;

    return 0;
}

5. C++20 <chrono> 库的新特性

C++20 扩展了 <chrono> 库,添加了日历库和时区支持等新特性。

5.1 日历库

C++20 引入了日历库,用于处理日期相关的操作:

cpp
#include <iostream>
#include <chrono>

int main() {
    // 使用 C++20 日历库
    using namespace std::chrono;

    // 获取当前日期
    auto today = floor<days>(system_clock::now());
    auto ymd = year_month_day{today};

    std::cout << "当前日期: "
              << static_cast<int>(ymd.year()) << "-"
              << static_cast<unsigned>(ymd.month()) << "-"
              << static_cast<unsigned>(ymd.day()) << std::endl;

    // 日期计算
    auto tomorrow = today + days{1};
    auto ymd_tomorrow = year_month_day{tomorrow};

    std::cout << "明天日期: "
              << static_cast<int>(ymd_tomorrow.year()) << "-"
              << static_cast<unsigned>(ymd_tomorrow.month()) << "-"
              << static_cast<unsigned>(ymd_tomorrow.day()) << std::endl;

    return 0;
}

5.2 时区支持

C++20 还添加了时区支持:

cpp
#include <iostream>
#include <chrono>

int main() {
    // 使用 C++20 时区库
    using namespace std::chrono;

    // 获取当前时间(UTC)
    auto now = system_clock::now();

    // 转换为本地时间
    auto local_now = zoned_time{current_zone(), now};

    std::cout << "本地时间: " << local_now << std::endl;

    // 转换为其他时区
    try {
        auto nyc_now = zoned_time{"America/New_York", now};
        std::cout << "纽约时间: " << nyc_now << std::endl;

        auto tokyo_now = zoned_time{"Asia/Tokyo", now};
        std::cout << "东京时间: " << tokyo_now << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "时区错误: " << e.what() << std::endl;
    }

    return 0;
}

小结

C++ 日期和时间包括:

  1. C 风格的时间函数

    • time(nullptr):获取当前时间的时间戳
    • localtime(&now):将时间戳转换为本地时间
    • strftime(buffer, size, format, tm):格式化时间
  2. C++11 <chrono>

    • 时钟:std::chrono::system_clockstd::chrono::steady_clockstd::chrono::high_resolution_clock
    • 时间点:表示特定的时间点
    • 时间段:表示时间的长度
  3. 计算时间差

    • 使用 C 风格的时间函数:difftime()
    • 使用 C++11 <chrono> 库:std::chrono::duration_cast<>
  4. 格式化时间

    • 使用 strftime 格式化时间

关键概念:

  • 时间戳:表示从某个固定时间点(通常是 1970 年 1 月 1 日)到现在的秒数
  • 时间点:表示特定的时间点
  • 时间段:表示时间的长度
  • 格式化时间:将时间转换为可读的字符串

掌握日期和时间的处理对于编写需要处理时间的程序非常重要。在后续章节中,我们将学习 C++ 的基本输入输出。