组日期与小时范围相同

时间:2017-11-07 08:35:00

标签: c#

我们说我有以下日期:

"2017-11-06 15:29", 
"2017-11-06 15:30", 
"2017-11-06 15:51", 
"2017-11-06 16:30", 
"2017-11-06 16:31"

我想将它们分组为60分钟,相对于第一项:

0: ["2017-11-06 15:29", "2017-11-06 15:30", "2017-11-06 15:51"]
1: ["2017-11-06 16:30", "2017-11-06 16:31"]

我在Grouping Contiguous Dates尝试dates.GroupWhile((previous, current) => previous.AddMinutes(60) >= current),但他们都归于同一群体。

3 个答案:

答案 0 :(得分:5)

这种方法并不是真正做你想要的,它是基于最后一个元素的分组。我想你想要这样的东西:

public static IEnumerable<IEnumerable<T>> GroupWhile<T>(this IEnumerable<T> source, Func<T, T, bool> continueSelector)
{
    using (var enumerator = source.GetEnumerator())
    {
        if (!enumerator.MoveNext())
        {
            yield break;
        }

        var currentGroup = new List<T> { enumerator.Current };
        while (enumerator.MoveNext())
        {
            var current = enumerator.Current;

            if (continueSelector(currentGroup.First(), current))
            {
                currentGroup.Add(current);
            }
            else
            {
                yield return currentGroup;
                currentGroup = new List<T> { current };
            }
        }

        yield return currentGroup;
    }
}

这将基于每个新组的第一个元素进行分组,使它们彼此相对,如果你像这样使用它,就会给你预期的结果:

dates.GroupWhile((groupDate, current) => (current - groupDate).TotalSeconds < 3600)

答案 1 :(得分:4)

您是第一次需要,然后可以使用TimeSpan.TotalHours(将double转换为int):

DateTime firstDt = dates.Min(); 
var hourGroups = dates.GroupBy(dt => (int)(dt - firstDt).TotalHours);

样品:

var dates = Enumerable.Range(1, 30).Select(i => DateTime.Now.AddMinutes(15 * i)).ToList();

和结果:

foreach (var dtGroup in hourGroups)
    Console.WriteLine(String.Join(", ", dtGroup));
07.11.2017 10:17:47, 07.11.2017 10:32:47, 07.11.2017 10:47:47, 07.11.2017 11:02:47
07.11.2017 11:17:47, 07.11.2017 11:32:47, 07.11.2017 11:47:47, 07.11.2017 12:02:47
07.11.2017 12:17:47, 07.11.2017 12:32:47, 07.11.2017 12:47:47, 07.11.2017 13:02:47
07.11.2017 13:17:47, 07.11.2017 13:32:47, 07.11.2017 13:47:47, 07.11.2017 14:02:47
07.11.2017 14:17:47, 07.11.2017 14:32:47, 07.11.2017 14:47:47, 07.11.2017 15:02:47
07.11.2017 15:17:47, 07.11.2017 15:32:47, 07.11.2017 15:47:47, 07.11.2017 16:02:47
07.11.2017 16:17:47, 07.11.2017 16:32:47, 07.11.2017 16:47:47, 07.11.2017 17:02:47
07.11.2017 17:17:47, 07.11.2017 17:32:47

答案 2 :(得分:0)

首先将字符串转换为DateTime

string[] strDates =
{
    "2017-11-06 15:29",
    "2017-11-06 15:30",
    "2017-11-06 15:51",
    "2017-11-06 16:30",
    "2017-11-06 16:31",
    "2017-11-06 16:28"
};

var dates = strDates.Select(date => DateTime.Parse(date))
    .OrderBy(date => date)  // Only needed if the original times might be unordered.
    .ToArray();

然后你可以从第一次开始按小时分组日期:

var startTicks = dates[0].Ticks;

var grouped = dates.GroupBy(date => (date.Ticks - startTicks)/TimeSpan.TicksPerHour);

这可以通过使用他们的滴答计数除以每小时的数字滴答来对时间进行分组 - 这样可以将它们全部按小时分组(但相对于列表中的第一次)。

我的测试代码打印出来:

foreach (var group in grouped)
    Console.WriteLine(string.Join(", ", group));

提供以下输出:

06/11/2017 15:29:00, 06/11/2017 15:30:00, 06/11/2017 15:51:00, 06/11/2017 16:28:00
06/11/2017 16:30:00, 06/11/2017 16:31:00