我正在从STL中寻找一个解决方案来处理“一天中的时间”。我正在做一个简单的单元测试练习,行为取决于当前时间是早上、晚上还是晚上。
在第一次迭代中,我使用了一个不起眼的整数来代替某个“时间对象”:
using TimeOfDay = int;
constexpr bool isBetween(TimeOfDay in, TimeOfDay min, TimeOfDay max) noexcept {
return in >= min && in <= max;
}
constexpr bool isMorning(TimeOfDay in) noexcept {
return isBetween(in, 6, 12); }
constexpr bool isEvening(TimeOfDay in) noexcept {
return isBetween(in, 18, 22);
}
constexpr bool isNight(TimeOfDay in) noexcept {
return isBetween(in, 22, 24) || isBetween(in, 0, 6);
}
constexpr string_view getGreetingFor(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;
}
这是可行的,但有几个气味:
int
不是表示24小时时钟的正确类型isNight()
需要进行不必要的复杂比较,这是由于换行(22-06)- 理想情况下,我希望能够实际使用系统时钟进行一些测试。
std::chrono::system_clock::now()
返回一个std::chrono::time_point
,所以我的理想类型应该是可以与time_point
相比的类型,或者是可以从time_point
轻松构造的类型。
任何指点都将不胜感激!
(我正在Visual Studio中使用C最新版本(预览C工作草案,因此大致为C++23))
3条答案
按热度按时间xpszyzbs1#
首先假设您要查找的是 * 本地 * 时间。
chrono::system_clock
代表UTC。因此,我推荐一个helper函数,该函数接受std::chrono::system_clock::time_point
并返回一个std::chrono::system_clock::duration
,它代表从最近的本地午夜开始经过的时间:chrono::current_zone()
返回一个指向您的计算机当前设置的chrono::time_zone
的指针。它用于将system_clock::time_point
转换为 localtime_point
。此本地time_point
是一个chrono::time_point
,但具有表示“本地时间”的不同时钟。表达式
floor<days>(time)
将time_point
截断为精度days
,这实际上为您提供了一个指向最近经过的当地午夜的指针。从time
中减去该值将得到自当地午夜以来的chrono::duration
。此duration
将与tp
具有相同的精度。此函数不能被设置为
constexpr
,因为将UTC转换为本地时间的规则掌握在您的政治家手中,并且可能会发生变化(在许多国家/地区,一年两次!)。现在可以这样写
isMorning
(et al):并这样称呼它:
在我看来,
isNight
的逻辑没有问题,isBetween
的代码也可以保持原样(采用TimeOfDay
的新定义)。isr3a4wc2#
如果你说的是一天中的时间,与日期分离,使用
std::chrono::duration
。对于整数小时,有别名std::chrono::hours
。另请参阅
std::chrono::hh_mm_ss
大概是这样的:
See it on coliru
monwx1rj3#
“时间”应该存储在
std::chrono::duration
中。要只分离任何duration
的h/m/s信息,可以执行以下操作:同样,您可以分离具有相同接口的
time_point
的h/m/s信息:然后可以使用helper类
hh_mm_ss
来检查信息:要检查一个
duration
是否在另外两个时间之间,你可以这样做:您还可以通过
using namespace std::chrono_literals
或using namespace std::literals
启用文字:对于
isEvening
中的 Package ,您可以执行类似以下的操作:isBetween(in + 12h - days{1}, 10h, 18h)
,但我认为你现在所拥有的有一个更干净,更容易遵循的逻辑。如果需要,这可以很容易地转换回
time_point
: