【问题标题】:.NET / C# - Get the next semi-week end date [closed].NET / C# - 获取下一个半周结束日期 [关闭]
【发布时间】:2019-11-25 22:14:14
【问题描述】:

我有以下代码,它模拟从星期六开始的一周,然后将一周分为两部分,如果给定日期是星期六至星期二,则返回星期二,否则返回星期五,但是,我觉得我在做某事错了,而且代码可以简化,但我不知道如何。

private static DateTime SemiWeeklyEndDate(DateTime date)
{
    if (((7 + (date.DayOfWeek - DayOfWeek.Saturday)) % 7) <= ((7 + (DayOfWeek.Tuesday - DayOfWeek.Saturday)) % 7))
        return date.AddDays((((int)DayOfWeek.Tuesday - (int)date.DayOfWeek + 7) % 7));

    return date.AddDays((((int)DayOfWeek.Friday - (int)date.DayOfWeek + 7) % 7));
}

【问题讨论】:

  • 如果你有工作代码,这可能更适合codereview
  • 我是这里的新手,我想得到一些反馈,为什么这个问题被关闭了。
  • 我认为问题在于“这可以简化吗?”因为问题是主观的(只需看看不同的回答)。如果你能把它变成一个客观的问题,比如“这可以用更少的模运算来完成吗”,你会很好。否则,如果是“嘿,请帮我看一下,欢迎 cmets”,那么您应该将其发布到 codereview

标签: c# .net datetime


【解决方案1】:

您可以使用本地函数创建更具可读性的内容:

private static DateTime SemiWeeklyEndDate(DateTime date)
{
    int DaysBetween(DayOfWeek from, DayOfWeek to) => (to - from + 7) % 7;
    int DaysToEndOfWeek(DayOfWeek from) => DaysBetween(from, DayOfWeek.Saturday);

    var pastMidWeek = DaysToEndOfWeek(date.DayOfWeek) <= DaysToEndOfWeek(DayOfWeek.Tuesday);

    var daysOffset =
        pastMidWeek
            ? DaysBetween(DayOfWeek.Tuesday, date.DayOfWeek)
            : DaysBetween(DayOfWeek.Friday, date.DayOfWeek);

    return date.AddDays(daysOffset);
}

我认为这个版本传达了你所追求的行为,没有过多的模数数学。

【讨论】:

  • 对,这很明显......我想知道逻辑中是否有可以简化的东西
  • 那么@NetMage 的答案对你来说是完美的。
  • 我已经更新以更好地传达逻辑。
【解决方案2】:

您可以通过根据内置 DOW 值计算一周中每一天的适当偏移量来简化整个事情:

| DOW       | Value | Offset | TUE | FRI |
| Saturday  | 6     |  3     |  3  |  6  |
| Sunday    | 0     |  2     |  2  |  5  |
| Monday    | 1     |  1     |  1  |  4  |
| Tuesday   | 2     |  0     |  0  |  3  |
| Wednesday | 3     |  2     |  6  |  2  |
| Thursday  | 4     |  1     |  5  |  1  |
| Friday    | 5     |  0     |  4  |  0  |

这原来是一个简单的双模公式:

private static DateTime SemiWeeklyEndDate(DateTime date) => date.AddDays((9 - (int)date.DayOfWeek) % 7 % 4);

公式推导:

到星期二为止,你有

((DayOfWeek.Tuesday - date.DayOfWeek) + 7) % 7
((2 - date.DayOfWeek) + 7) % 7
(9 - date.DayOfWeek) % 7

上面给出了 TUE 列。

到周五为止,你有

((DayOfWeek.Friday - date.DayOfWeek) + 7) % 7
((5 - date.DayOfWeek) + 7) % 7
(12 - date.DayOfWeek) % 7

它给出了上面的 FRI 列。将 TUE 和 FRI 与 Offset 进行比较,我们发现我们可以对 TUE 再应用一个 mod 来获得 Offset。

此方法 (EndDate) 和原始 (OrigEndDate) 的输出示例:

StartDate       EndDate         OrigEndDate
Sat 11/30/19    Tue 12/03/19    Tue 12/03/19
Sun 12/01/19    Tue 12/03/19    Tue 12/03/19
Mon 12/02/19    Tue 12/03/19    Tue 12/03/19
Tue 12/03/19    Tue 12/03/19    Tue 12/03/19
Wed 12/04/19    Fri 12/06/19    Fri 12/06/19
Thu 12/05/19    Fri 12/06/19    Fri 12/06/19
Fri 12/06/19    Fri 12/06/19    Fri 12/06/19

当然,您可以只使用数组将DayOfWeek 映射到偏移量:

private static int[] DOWToOffsetMap = new[] { 3, 2, 1, 0, 2, 1, 0 };    
private static DateTime SemiWeeklyEndDate2(DateTime date) => date.AddDays(DOWToOffsetMap[(int)date.DayOfWeek]);

【讨论】:

  • 抱歉,该函数没有返回正确答案。我错过了什么吗?
  • @User2585 当我使用这个函数和你的函数时,我得到的结果是一样的吗?
  • 你是对的,很好的答案,不知道为什么有人投了反对票
  • @User2585 仅供参考,如果您想用存储换取性能,我添加了一个数组映射版本。
【解决方案3】:

这就是我喜欢做这类问题的方式

            DateTime jan1 = new DateTime(DateTime.Now.Year, 1, 1);
            DateTime firstSaturday = jan1.AddDays(6 - (int)jan1.DayOfWeek);

            DateTime today = DateTime.Now.Date;
            int daysFromSemiWeekBegin = today.Subtract(firstSaturday).Days % 14;

            DateTime semiWeekEnd = (daysFromSemiWeekBegin == 0) ? today : today.AddDays(14 - daysFromSemiWeekBegin);

【讨论】:

    猜你喜欢
    • 2022-12-11
    • 2021-01-18
    • 2010-11-19
    • 2018-10-05
    • 1970-01-01
    • 1970-01-01
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多