如何用C++ STL实现24小时时钟并处理时段判断逻辑?
基于C++ STL的「一天中的时间」处理方案(适配C++23)
核心思路
利用C++20/23 <chrono>库的强类型时间工具,替代原生int解决类型安全问题;通过duration的比较简化跨天区间判断;同时兼容系统时钟的time_point,实现单元测试与实际场景的无缝切换。
实现方案
1. 强类型TimeOfDay封装
封装一天内的时间,基于std::chrono::hours确保类型安全,同时支持从系统时间点构造:
#include <chrono> #include <stdexcept> class TimeOfDay { public: // 从小时构造(限制0-23) constexpr explicit TimeOfDay(std::chrono::hours h) : m_hours(h) { if (h < std::chrono::hours{0} || h >= std::chrono::hours{24}) { throw std::invalid_argument("TimeOfDay must be between 0 and 23 hours"); } } // 从系统时间点转换为当地时间的小时 explicit TimeOfDay(const std::chrono::system_clock::time_point& tp) { using namespace std::chrono; const auto local_tp = current_zone()->to_local(tp); const auto dp = floor<days>(local_tp); const auto time_since_midnight = local_tp - dp; m_hours = floor<hours>(time_since_midnight); } // 获取小时数 constexpr std::chrono::hours hours() const noexcept { return m_hours; } private: std::chrono::hours m_hours; };
2. 简化时间区间判断
通过duration比较替代复杂的跨天逻辑,夜间判断直接取反早晨和傍晚的条件:
#include <string_view> constexpr bool isMorning(const TimeOfDay& time) noexcept { using namespace std::chrono; const auto h = time.hours(); return h >= hours{6} && h < hours{12}; // 覆盖6:00-11:59 } constexpr bool isEvening(const TimeOfDay& time) noexcept { using namespace std::chrono; const auto h = time.hours(); return h >= hours{18} && h < hours{22}; // 覆盖18:00-21:59 } constexpr bool isNight(const TimeOfDay& time) noexcept { // 无需处理跨天逻辑,直接取反非夜间区间 return !isMorning(time) && !isEvening(time); } constexpr std::string_view getGreetingFor(const TimeOfDay& time) noexcept { if (isMorning(time)) { return "Good morning "sv; } if (isEvening(time)) { return "Good evening "sv; } if (isNight(time)) { return "Good night "sv; } return "Hello "sv; }
3. 单元测试与实际场景适配
- 单元测试:直接构造指定小时的
TimeOfDay,支持编译期断言:
// 编译期测试早晨场景 constexpr TimeOfDay morning{std::chrono::hours{8}}; static_assert(getGreetingFor(morning) == "Good morning "sv); // 编译期测试傍晚场景 constexpr TimeOfDay evening{std::chrono::hours{19}}; static_assert(getGreetingFor(evening) == "Good evening "sv); // 编译期测试夜间跨天场景 constexpr TimeOfDay night1{std::chrono::hours{23}}; constexpr TimeOfDay night2{std::chrono::hours{3}}; static_assert(getGreetingFor(night1) == "Good night "sv); static_assert(getGreetingFor(night2) == "Good night "sv);
- 实际场景:从系统时钟获取当前时间:
#include <iostream> int main() { const TimeOfDay now{std::chrono::system_clock::now()}; std::cout << getGreetingFor(now) << "User!\n"; return 0; }
关键优势
- 类型安全:通过
std::chrono::hours限制时间范围,避免非法值(如25小时)。 - 逻辑简洁:夜间判断无需处理跨天区间,直接取反非夜间条件。
- 原生兼容:支持从
system_clock::time_point直接构造,自动转换为当地时间。 - 编译期支持:核心判断逻辑可在编译期执行,提升单元测试效率。
内容的提问来源于stack exchange,提问作者ulfben
相关产品推荐
相关产品推荐

