缩短日期时间条件检查

4
if ((DateTime.Now.DayOfWeek != DayOfWeek.Friday && DateTime.Now.DayOfWeek != DayOfWeek.Saturday) &&
((DateTime.Now.Hour >= 10 && DateTime.Now.Hour < 13) || (DateTime.Now.Hour >= 20 && DateTime.Now.Hour < 23)))

我需要缩短这个条件,您有什么建议吗?

2
为什么你必须这样做?虽然不是很简短,但确实直接了当。 - DonBoitnott
1
...但这并不是非常易读的,这对于更容易理解代码很重要。 - MUG4N
3
你可以将 DayOfWeek 检查减少为:(Int32)DateTime.Now.DayOfWeek < 5。这样翻译更加通俗易懂,但没有改变原意。 - DonBoitnott
1
@Sayse 我同意你的观点,逻辑不能缩短,但是可以通过选择具有自我解释性名称的子方法来提高可读性。如果您正确命名方法,则不需要注释。 - MUG4N
@DonBoitnott 但是这样你就会面临魔术数字的问题,我认为与枚举比较更加“干净”(我知道这个问题是关于缩短的)。 - Master117
显示剩余3条评论
5个回答

4

好的,您可以编写一个扩展方法:

public static bool BoundsCheck(this DateTime d, int min, int max, int min2, int max2)
{
    return (d.DayOfWeek != DayOfWeek.Friday &&
        d.DayOfWeek != DayOfWeek.Saturday &&
        d.Hour >= min &&
        d.Hour < max) ||
        (d.Hour >= min2 && d.Hour < max2);
}

然后像这样调用它:

if (DateTime.Now.BoundsCheck(10, 13, 20, 23))...

1
+1 对于扩展方法,虽然你的参数名称可以更清晰明了。 - deltree
1
@deltree,谢谢!我会购买它们可能需要更好的命名,但是说实话,我甚至不知道该如何命名它们,因为我真的不知道OP在这里做什么。:D - Mike Perrenoud
也许可以重构一下,接收一个日期时间范围列表,比如星期五10-13点,星期五20-23点等。 - deltree
@deltree,我不这么认为。整数正在边界检查“Hour”。 - Mike Perrenoud
其实我认为你的逻辑和问题本身不符。OP 检查天数是否在两个时间段内。 - deltree

4

这样更简洁吗?或许是,但在我看来更重要的是它更易读和易维护:

var now = DateTime.Now;
var notAllowedDays = new[] { DayOfWeek.Friday, DayOfWeek.Saturday };
var allowedHours = Enumerable.Range(10, 3).Concat(Enumerable.Range(20, 3));
if(!notAllowedDays.Contains(now.DayOfWeek) && allowedHours.Contains(now.Hour))
{

} 

恐怕当你不是 Linq 大师时,可读性部分就会死掉 :) - DonBoitnott
这是一个合理的解决方案,但我个人更喜欢原始条件语句。 - evanmcdonnal
1
我更喜欢使用“now”变量,因为每次检查之间会经过纳秒,所以这更准确。 - deltree
1
@deltree:是的,Now也是一个相对昂贵的“属性”。它甚至需要使用IO访问:https://dev59.com/f2TWa4cB1Zd3GeqPFJ-F#10900267 - Tim Schmelter
1
在我看来,如果允许或不允许同时包含天数和小时数,那么代码会更易读、易懂。这样就少了思考的过程 :) 但这只是挑剔而已。 - Boris B.
@BorisB.:同意!不过,我尽可能地保持接近原帖的逻辑……而且我太懒了,没想打出除了 DayOfWeek.Friday, DayOfWeek.Saturday 以外的所有天数;-) - Tim Schmelter

4
您可以更改使用的小时数。
(DateTime.Now.Hour % 12) +1 >= 10 && (DateTime.Now.Hour % 12) +1 < 13

也许甚至可以不进行第二次检查。 我认为你不能比寻找其他方法更好地改进它,比如其他答案。 更新:我测试了上面的方法是错误的,但这个方法更加残忍且有效。
var check = (DateTime.Now.Hours - 10 % 12) % 10;
 var checkV = (DateTime.Now.Hours >= 10 && check < 3);

测试代码

for (int i = 0; i < 24; i++)
{
    var check = (i - 10 % 12) % 10;
    bool checkV = (i >= 10 && check < 3);
    Console.WriteLine(i.ToString() + ": " + checkV.ToString());
 }
 Console.ReadKey();

更新2 完整的缩短代码

if(   (int)DateTime.Now.DayOfWeek < 5 && 
           DateTime.Now.Hours >= 10 && 
         ((DateTime.Now.Hours - 10 % 12) % 10) < 3)

我只是在检查我的逻辑,看起来有点不对劲哈哈 - Sayse
@deltree - 我是正确的,它是错误的,所以我变得更加恶魔 ;) - Sayse
你说得对,这更加棘手了。我再也不理解它了。 - deltree
@deltree - 确保小时数大于等于10(下限检查),然后是魔鬼般的部分:(将小时数减去10,得到除以12的余数,再将结果除以10得到的余数,对于10-12和20-23,返回0、1或2,这比3小...个人而言,我喜欢原始代码在OP问题中。 - Sayse
@Sinros:我不知道混淆是你的目标 ;) 顺便说一下,这被称为代码高尔夫,甚至有一个专门解决此类难题的StackExchange 网站:http://codegolf.stackexchange.com/ - Tim Schmelter
@TimSchmelter - 我的目标是回答“缩短这个条件”的问题...在尝试这个之前,我已经点赞了你的答案:P,我看过codegolf,但问题似乎总是偏向于更短的编写语言。 - Sayse

2
if (!this.ItsPartyDay() && (this.ItsLunchTime() || this.ItsDinnerTime()))
{
    ...
}

private bool ItsPartyDay()
{
    return (Int32)DateTime.Now.DayOfWeek >= 5;
}

private bool ItsLunchTime()
{
    return (DateTime.Now.Hour >= 10 && DateTime.Now.Hour < 13);
}

private bool ItsDinnerTime()
{
    return (DateTime.Now.Hour >= 20 && DateTime.Now.Hour < 23);
}

这就是重构的乐趣所在。 - deltree

0

我认为没有合理的解决方案,但有几个想法。可以使用别名来代替 DateTimeDayOfWeek。另一个选项是在条件语句之前将所有这些值赋给变量。

所以你可以这样做:

 string fri = DayOfWeek.Friday;
 string sat = DayOfWeek.Saturday;

然后在条件语句中使用它们。或者;

 using dt = DateTime;

然后你可以执行dt.Now.DayOfWeek

我个人不建议这样做。你并没有真正缩短条件语句,而是进行了重构。如果在一个类中有很多这样的语句,那么可能值得权衡一下,否则就不必了。

编辑:Michael Perrenoud提出的扩展方法建议是一个合理的解决方案,而且效果非常好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接