【问题标题】:Periodicity of events 2 [closed]事件的周期性 2 [关闭]
【发布时间】:2012-02-26 12:41:29
【问题描述】:

我之前的问题有很多缺点。我会再试一次,给出一个代码以及为什么它不起作用。

例如,我们有每 3 个月举办一次的活动。事件有 DateStart、DataEnd 和 Periodicity。
例如,我们有一条记录:

start = 02/23/2012 22:00:00;
end = 12/31/2012 23:30:00;
periodicity = 3;

当当前月份 = 二月、五月、八月、十一月时,方法必须返回 true。

代码:

public bool MonthPeriodicityChecker (DateTime start, DateTime end, DateTime dateToCheck, int periodicity)
{
     var monthDiff = dateToCheck.Month - startDate.Month;
     return (monthDiff-1) % periodicity == 0;
}

如果 dateToCheck 中的月份等于 4 月、7 月、10 月,则此代码返回 true。跳过第一个月。

更新:

该死,对不起。除此之外,我还有汇总日期的循环。这个循环从 1 开始,并将这个 1 添加到start。下一个日期是 2 月 24 日。因此,在我的程序中不会打印二月(也检查了月份的数字(23))。对不起,谢谢。

【问题讨论】:

  • 您的代码遇到了什么问题?你在期待什么,而发生了什么?您的另一个问题可能已关闭,因为它更多的是“为我解决问题”而不是“帮助我解决我的问题”。
  • 你和那个你那个代码的人谈话有什么问题?
  • @simchona:当它关闭时,我正在回答这个问题。我试图推动 OP 写出可以清楚回答的问题。该问题没有任何问号。
  • @BryanWatts 我不知道你看过 OP 的另一个问题;你的第一条评论比那更具修辞性。编辑旧的可能会有所帮助,因为这个可能是骗子?

标签: c#


【解决方案1】:

如果您希望它在 2 月、5 月、8 月和 11 月触发,则不应从差值中减去一个。只需使用:

return (monthDiff % periodicity) == 0;

当月份相同时(二月),0 % 3 == 0。当您离开三个月的倍数时(例如八月),6 % 3 == 0

我不确定 C#,但某些语言在取负数的模数时并不像您期望的那样,所以我会加倍安全:

public bool MonthPeriodicityChecker (DateTime start, DateTime end,
    DateTime dateToCheck, int periodicity)
{
    var monthDiff = dateToCheck.Month - startDate.Month + 12; // make positive
    return (monthDiff % periodicity) == 0;
}

但是,请记住,由于您在计算中只使用了一年中的月份,因此如果您运行超过 12 个月并且您的周期不是分成 12 个月,这可能不会按预期工作干净利落。

例如,从 2010 年 12 月开始,每五个月一次。

  • 2010 年 12 月还可以,因为差异为零:0 % 5 == 0
  • 2011 年 5 月还可以,因为 5 月和 12 月之间的差是五个月:5 % 5 == 0
  • 2011 年 10 月还可以,因为 10 月和 12 月之间相差十个月:10 % 5 == 0
  • 2012 年 3 月不是好的。三月和十二月之间的差异是三个月,而不是现实中的十五个月:3 % 5 == 3

这样做的结果是,你将在每年的 5 月、10 月和 12 月开火。

您可以通过确保将年份考虑在内来解决这个小问题(如果它对您来说是个问题),例如:

public bool MonthPeriodicityChecker (DateTime start, DateTime end,
    DateTime dateToCheck, int periodicity)
{
    // assuming Month returns 1-12 here which is the case for C# I think.
    var monthDiff = (dateToCheck.Year * 12 + dateToCheck.Month - 1)
        - (startDate.Year * 12 + startDate.Month - 1);
    return (monthDiff % periodicity) == 0;
}

这也消除了添加 12 以获得正数的需要,因为前进的年份将确保(从 12 月到 1 月的跳跃现在会给你 1 而不是 -11),假设 dateToCheck.Month 将始终大于或等于startDate.Month

如果dateToCheck 有可能更少 startDate,您可能需要先检查一下,然后在上述函数的第一步中返回 false。

【讨论】:

    【解决方案2】:

    您可以通过生成该范围内的所有日期来执行此操作,然后查看其中是否有任何日期与dateToCheck 属于同一月份。首先,获取月份:

    private IEnumerable<DateTime> GetDatesInRange(DateTime start, DateTime end, int periodicity)
    {
        var current = start;
    
        do
        {
            yield return current;
    
            current += TimeSpan.FromMonths(periodicity);
        }
        while(current <= end)
    }
    

    然后,看看是否有同月:

    public bool MonthPeriodicityChecker(DateTime start, DateTime end, DateTime dateToCheck, int periodicity)
    {
        return GetDatesInRange(start, end, periodicity).Any(date => date.Month == dateToCheck.Month);
    }
    

    【讨论】:

      【解决方案3】:

      你的月份减法不好。如果从 12 月更改为 1 月会发生什么?

      这个方法怎么样:

             public bool monthPeriodicityChecker(DateTime start, DateTime end, dateToCheck, periodicity)
              {
                  if ((dateToCheck < start) || (dateToCheck > start))
                      return false;
      
                  int monthDiff = 0; 
                  while (startDate.AddMonths(1) < dateToCheck)
                  {
                      monthDiff++
                      // i'm sure there is a speedier way to calculate the month difference, but this should do for the purpose of this example 
                  }
      
                  return (monthDiff) % periodicity == 0;
              };
      

      【讨论】:

      • 你好,Anastasiosyal。您的代码返回与我的代码相同的结果。
      • 我更喜欢@paxdiablo 的回答,我已经编辑了答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-25
      • 2013-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-16
      相关资源
      最近更新 更多