【问题标题】:Validate DateTime's are sequential by month验证 DateTime 是否按月顺序排列
【发布时间】:2009-08-06 19:50:07
【问题描述】:

我有一个包含 60 个DateTime 对象的列表(按升序排序),需要验证每个日期是否比列表中的前一个日期大 1 个月。

例如,以下日期列表将是有效的,因为它们以一个月为增量而没有丢失:

2009 年 1 月
2009 年 2 月
2009 年 3 月
2009 年 4 月

但是,由于缺少 2009 年 2 月,以下日期列表将无效:

2009 年 1 月
2009 年 3 月
2009 年 4 月

日期无关紧要,只考虑

有没有一种有效/漂亮的方法来做到这一点?

【问题讨论】:

    标签: c# linq performance date compare


    【解决方案1】:

    对于所有日期,如果您采用 (年 * 12 + 月),您将获得一个连续的整数列表。这可能更容易检查间隙。

    【讨论】:

      【解决方案2】:

      您可以尝试以下方法:

      int start = list.First().Year * 12 + list.First().Month;
      bool sequential = list
          .Select((date, index) => date.Year * 12 + date.Month - index)
          .All(val => val == start);
      

      这会将日期列表“转换”为代表年和月的数字,对于列表中的每个项目,该数字应递增 1。然后我们从这些项目中的每一个中减去当前索引,因此对于一个有效的列表,所有项目都将具有相同的值。然后我们将所有值与start 进行比较,这是第一个计算值。

      【讨论】:

        【解决方案3】:

        这是一个干净的检查,使用精心设计的选择器,可以根据您的用例进行正确比较:

        IEnumerable<DateTime> dates = ...;
        DateTime firstDate = dates.First();
        IEnumerable desired = Enumerable.Range(0, 60).Select(months => firstDate.AddMonths(months));
        bool correct = dates.SequenceEqual(desired, date => date.Year*12 + date.Month);
        

        使用这个自定义SequenceEqual

        public static bool SequenceEqual<T1, T2>(this IEnumerable<T1> first, IEnumerable<T1> second, Func<T1, T2> selector)
        {
            // uses the LINQ Enumerable.SequenceEqual method on the selections
            return first.Select(selector).SequenceEqual(second.Select(selector));
        }
        
        // this is also useful, but not used in this example
        public static bool SequenceEqual<T1, T2>(this IEnumerable<T1> first, IEnumerable<T1> second, Func<T1, T2> selector, IEqualityComparer<T2> comparer)
        {
            return first.Select(selector).SequenceEqual(second.Select(selector), comparer);
        }
        

        【讨论】:

          【解决方案4】:
          public bool MonthsAreSequential(IList<DateTime> dates)
          {
              if (dates.Count < 2) return true;
          
              for (int i = 0; i < dates.Count - 1; i++)
              {
                  var plusOne = dates[i].AddMonth(1);
                  var nextMonth = dates[i + 1];
                  if (plusOne .Year != nextMonth .Year 
                      || plusOne .Month != nextMonth .Month)
                      return false;
              }
              return true;
          }
          

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-08-29
          • 2021-03-04
          • 2012-09-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-25
          相关资源
          最近更新 更多