C++ 如何检测一个周末是否有两次约会? 问题
给定两个日期时间,C++ 如何检测一个周末是否有两次约会? 问题,c++,datetime,c++11,C++,Datetime,C++11,给定两个日期时间,dt0和dt1(可能出现故障),有什么算法可以确定两个日期之间是否至少有24小时的周末(周六、周日)? 假设有一个dayofweek()函数,它为SUN返回0,为MON返回1,等等 注意:这个问题很容易以直线段的形式进行几何可视化,但我暂时无法进行计算 解决方案 下面的解决方案适用于UTC,但适用于DST将失败 weekdayno()未包括实现:SUN==0、MON==1等 isWeekday()也没有显示,但是一旦您有了dayofweek() 二进制运算符-()实现也未显示
dt0
和dt1
(可能出现故障),有什么算法可以确定两个日期之间是否至少有24小时的周末(周六、周日)?
假设有一个dayofweek()
函数,它为SUN返回0,为MON返回1,等等
注意:这个问题很容易以直线段的形式进行几何可视化,但我暂时无法进行计算
解决方案
下面的解决方案适用于UTC,但适用于DST将失败
未包括实现:SUN==0、MON==1等weekdayno()
也没有显示,但是一旦您有了isWeekday()
dayofweek()
- 二进制
实现也未显示,但我们只需将这两个实例转换为UNIX时间(自Epoch以来的秒数),并取其差得出两个运算符-()
之间的秒数日期时间
hh()
mm()
只是分别返回小时、分钟和秒的常量访问器ss()
- 查询stackoverflow以了解查看问题的各种方法
- 你永远不会有太多的单元测试:需要它们来清除奇怪的边缘用例
- 如果可能,使用可视化来查看问题
- 当您查看细节(例如DST)时,看似微不足道的问题实际上可能有点棘手
- 保持解决方案尽可能简单,因为您的代码很可能会更改:为了修复bug/新的测试用例,或者为了添加新功能(例如使其适用于DST)。尽可能保持可读性和易懂性:与开关/案例相比,更喜欢算法
- 勇敢地去尝试:不断地尝试解决方案,直到有事情发生。使用单元测试,以便能够持续重构。编写简单的代码需要做很多工作,但最终还是值得的
static const size_t ONEDAYINSECS = (24 * 60 * 60);
DateTime
DateTime::nextSatMorning() const
{
// 0 is SUN, 6 is SAT
return *this + (6 - weekdayno()) * ONEDAYINSECS -
(((hh() * 60) + mm())*60 + ss());
}
DateTime
DateTime::previousSunNight() const
{
return *this - ((weekdayno() - 1 + 7)%7) * ONEDAYINSECS -
(((hh() * 60) + mm())*60 + ss());
}
bool
DateTime::straddles_24HofWeekend_OrMore( const DateTime& newDt ) const
{
const DateTime& t0 = min( *this, newDt );
const DateTime& t1 = max( *this, newDt );
// ------------------------------------
//
// <--+--F--+--S--+--S--+--M--+-->
// t0 ^ ^ t1
// +---->+ +<----|
// | |
// +<--nSecs-->+
// edge0 edge1
//
// ------------------------------------
DateTime edge0 = t0.isWeekday() ? t0.nextSatMorning() : t0;
DateTime edge1 = t1.isWeekday() ? t1.previousSunNight() : t1;
return (edge1 - edge0) > ONEDAYINSECS;
}
我能想到的解决这个问题的最愚蠢的方法是:复制较小的datetime值,不断添加到它,直到它大于另一个datetime值(较大的一个),或者dayofweek()不再等于0或7。然后检查您添加的总时间值是否小于24小时 一个稍微不那么愚蠢的方法是检查它是一个周末,加上24小时的时间,然后检查一次,以确保它是一个周末,仍然少于第二个日期时间 只要您的功能能够找到白天,夏令时就不应该真正发挥作用。此图可能有助于:
SAT SUN
|---------|---------|
a---------b
a---------b
...
a---------b
以结构化的方式进行处理:哪些是简单/边缘情况?一般情况是什么 我能想到的简单案例(注意,因为您已经强制
t0
为较低的值,我假设如下):
t1-t0
小于1天,则返回falset1-t0
为>=6天,则返回true(在任何给定的6天块中,周末时间始终为24小时,即使是从周日开始)t0
和t1
都取dayofweek(),并进行一些检查(这是平均情况)。我们现在可以在这里特别便宜,因为我们知道t0
只比t1
早5天
编辑:删除我的条件,因为有讨厌的小边缘案件,我没有考虑。无论如何,我推荐的解决方案仍然是可行的,我不会在这里这么做。这个网站用C#计算工作日,这有帮助吗 不-这是我正在建设的图书馆的一部分,没有任何限制,从头开始写这篇文章会很乏味,因为人们必须考虑不同时区和地点的夏令时,在其他不规则的日历中,@JamesMcNellis+1指出DST问题:一旦我也想到了基本算法,我会注意它们,但我处理的是日期时间,而不仅仅是日期,所以这有点棘手-另一种可能性是,如果我能检测到工作日和周末之间t0和t1范围内的所有边界,并将我的时间线分为工作日、周末、工作日、周末、工作日、周末等。。。然后,我可以计算工作日段的长度和周末段的长度。我认为这可能有点接近……您的日期时间应该是一个大值,例如自1970年1月1日UTC 00:00:00以来的秒数。如果你是自己编造的,也可能会有同样令人困惑的事情。我如何在内部实现datetime在这里不会有什么不同。然而,dst是一个问题-例如,两个日期可能是周六上午9点和周日上午9点,但它们之间的间隔可能只有23小时或多达25小时-因此任何类型的日期时间算法都可能变得棘手-解决这一问题的一种方法是要求所有日期都是UTC或在没有dst的时区,但这有点像逃避现实+1赞成-可视化肯定会有帮助:实际上你给了我一个便宜的把戏-如果我给a加上24小时,它小于b,我就完成了(根据a的位置做了一点调整)。。。我会想得更多一些
SAT SUN
|---------|---------|
a---------b
a---------b
...
a---------b