Skip to content

Ch 7: 日期与时间

  • 掌握 chrono 库的基本用法
  • 处理时间戳和 Duration
  • 使用时钟类型
  • 理解时区处理

datetime 是 Python 处理时间的标准方式:

from datetime import datetime, timedelta, timezone
# 当前位置时间
now = datetime.now()
utc_now = datetime.now(timezone.utc)
# 构造时间
dt = datetime(2024, 1, 15, 12, 30, 45)
# 时间戳(秒)
timestamp = now.timestamp()
# 从时间戳构造
from_ts = datetime.fromtimestamp(timestamp)
# 时间运算
later = dt + timedelta(days=7, hours=3)
earlier = dt - timedelta(weeks=1)
diff = later - dt # timedelta 对象
# 格式化
formatted = dt.strftime("%Y-%m-%d %H:%M:%S")
# "2024-01-15 12:30:45"
# 解析
parsed = datetime.strptime("2024-01-15", "%Y-%m-%d")
from datetime import timedelta
# 创建
td = timedelta(days=7, hours=3, minutes=30, seconds=15)
# 属性
td.days # 7
td.seconds # 3*3600 + 30*60 + 15 = 12615
td.total_seconds() # 7天的总秒数
# 运算
td1 = timedelta(days=3)
td2 = timedelta(days=5)
td3 = td1 + td2 # 8天
td4 = td2 - td1 # 2天
td5 = td1 * 2 # 6天

chrono 是 C++ 处理时间的标准库:

#include <chrono>
#include <ctime>
#include <format>
#include <iostream>
int main() {
// 当前时间
auto now = std::chrono::system_clock::now();
// Duration - 时间段
using namespace std::chrono;
seconds sec(42);
milliseconds ms(1000);
microseconds us = ms * 1000;
// Duration 转换
auto total_ms = std::chrono::duration_cast<milliseconds>(sec);
// 42000 ms
// 时间点
auto tp = std::chrono::system_clock::now();
// time_t 转换
std::time_t t = std::chrono::system_clock::to_time_t(now);
// tm 转换
std::tm* tm = std::localtime(&t);
// 格式化 (C++20)
std::string formatted = std::format("{:%Y-%m-%d %H:%M:%S}", *tm);
std::cout << formatted << std::endl;
return 0;
}
#include <chrono>
// 1. Duration - 时间段
using namespace std::chrono;
// 预定义类型
seconds s = 42;
milliseconds ms = s * 1000;
microseconds us = std::chrono::duration_cast<microseconds>(s);
minutes m = std::chrono::duration_cast<minutes>(s);
// 2. Time Point - 时间点
auto now = std::chrono::system_clock::now();
// 3. Clocks - 时钟
// system_clock - 系统时钟,可调
// steady_clock - 单调时钟,不受系统时间调整
// high_resolution_clock - 高精度时钟
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
// 创建 Duration
seconds s1(42);
seconds s2 = 42s; // C++14 字面量
milliseconds ms = 1000ms;
// 转换
seconds from_ms = std::chrono::duration_cast<seconds>(ms);
// 算术运算
seconds total = s1 + s2;
seconds doubled = s1 * 2;
seconds halved = s1 / 2;
// 比较
if (s1 < s2) { /* ... */ }
// 获取数值
std::cout << s1.count() << " seconds" << std::endl;
// 睡眠
std::this_thread::sleep_for(seconds(1));
return 0;
}
类型定义Python timedelta
std::chrono::nanoseconds10⁻⁹ 秒microseconds
std::chrono::microseconds10⁻⁶ 秒milliseconds
std::chrono::milliseconds10⁻³ 秒-
std::chrono::seconds1 秒seconds
std::chrono::minutes60 秒minutes
std::chrono::hours3600 秒hours
std::chrono::days86400 秒days
std::chrono::weeks604800 秒weeks
时钟说明Python 等价
system_clock系统真实时间,可调datetime
steady_clock单调时钟,不受系统时间调整time.monotonic
high_resolution_clock高精度时钟time.perf_counter
#include <chrono>
#include <iostream>
int main() {
using namespace std::chrono;
// system_clock - 适合显示给用户
auto sys_now = system_clock::now();
std::time_t t = system_clock::to_time_t(sys_now);
std::cout << std::ctime(&t) << std::endl;
// steady_clock - 适合测量时间间隔
auto start = steady_clock::now();
// ... 做些工作 ...
auto end = steady_clock::now();
auto elapsed = end - start;
std::cout << "Elapsed: "
<< duration<double, std::milli>(elapsed).count()
<< " ms" << std::endl;
return 0;
}
import time
# 方法1: time.time()
start = time.time()
# ... 工作 ...
end = time.time()
print(f"Elapsed: {end - start:.3f}s")
# 方法2: time.perf_counter()(更高精度)
start = time.perf_counter()
# ... 工作 ...
end = time.perf_counter()
print(f"Elapsed: {end - start:.6f}s")
# 方法3: timeit
import timeit
result = timeit.timeit('"-".join(str(n) for n in range(100))',
number=10000)
print(f"Elapsed: {result:.3f}s")
#include <chrono>
#include <iostream>
// 方法1: steady_clock
auto start = std::chrono::steady_clock::now();
// ... 工作 ...
auto end = std::chrono::steady_clock::now();
auto elapsed = end - start;
std::cout << "Elapsed: "
<< std::chrono::duration<double, std::milli>(elapsed).count()
<< " ms" << std::endl;
// 方法2: system_clock
auto wall_start = std::chrono::system_clock::now();
// ... 工作 ...
auto wall_end = std::chrono::system_clock::now();
// 高精度方式
template<typename Func>
auto measure(Func f) {
auto start = std::chrono::high_resolution_clock::now();
f();
auto end = std::chrono::high_resolution_clock::now();
return end - start;
}
auto dur = measure([]() {
// ...
});
from datetime import datetime
dt = datetime(2024, 1, 15, 12, 30, 45)
# strftime - 格式化
formatted = dt.strftime("%Y-%m-%d %H:%M:%S")
formatted = dt.strftime("%B %d, %Y") # "January 15, 2024"
formatted = dt.strftime("%a %b %d") # "Mon Jan 15"
# strptime - 解析
parsed = datetime.strptime("2024-01-15", "%Y-%m-%d")
#include <chrono>
#include <format>
#include <iostream>
#include <ctime>
int main() {
std::time_t t = std::time(nullptr);
std::tm* tm = std::localtime(&t);
// C++20 格式化
std::cout << std::format("{:%Y-%m-%d %H:%M:%S}", *tm) << std::endl;
std::cout << std::format("{:%B %d, %Y}", *tm) << std::endl;
std::cout << std::format("{:%a %b %d}", *tm) << std::endl;
// 手动格式化(C++17 之前)
char buf[100];
std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
std::cout << buf << std::endl;
return 0;
}
PythonC++说明
%Y%Y四位年份
%m%m月份
%d%d日期
%H%H小时(24制)
%M%M分钟
%S%S秒
%B%B月份全名
%b%b月份缩写
%a%a星期缩写
from datetime import datetime, timezone, timedelta
# UTC
utc = datetime.now(timezone.utc)
# 本地时间
local = datetime.now() # 本地时区
# 转换
from zoneinfo import ZoneInfo
ny = datetime.now(ZoneInfo("America/New_York"))
# 手动时区
tz = timezone(timedelta(hours=8))
china = datetime(2024, 1, 15, 12, tzinfo=tz)
#include <chrono>
#include <format>
int main() {
using namespace std::chrono;
// C++20 支持时区
auto now = system_clock::now();
// 转换为 time_t
auto t = system_clock::to_time_t(now);
// 转换为 UTC tm
std::tm utc_tm = *std::gmtime(&t);
// 转换为本地 tm
std::tm local_tm = *std::localtime(&t);
// C++20 chrono 支持时区(需要 <chrono> + <format>
// 很多编译器尚未完全支持
return 0;
}
  • std::chrono 是 C++ 时间库
  • system_clock 对应 datetime
  • steady_clock 用于测量时长
  • C++20 std::format 格式化时间
  • 时区支持在 C++20 引入,但编译器支持不完整

下章预告:ch08 数学与随机数。