C# Linq计算时差并选择最接近的时差

C# Linq计算时差并选择最接近的时差,c#,linq,datediff,C#,Linq,Datediff,我有这样一个对象列表: +-------------+------------+---------------------+ | ID | Value | Time | +-------------+------------+---------------------+ | 1 | 1 | 2019-03-07 20:05:35 | | 2 | 2 | 2019

我有这样一个对象列表:

+-------------+------------+---------------------+
| ID          | Value      | Time                | 
+-------------+------------+---------------------+
| 1           | 1          | 2019-03-07 20:05:35 |
| 2           | 2          | 2019-03-07 20:06:09 |  
| 5           | 5          | 2019-03-07 20:11:27 |
| 7           | 1          | 2019-03-07 20:13:30 |
| 8           | 0          | 2019-03-07 20:13:41 |
| 7           | 1          | 2019-03-07 20:17:00 |
| 8           | 0          | 2019-03-07 20:22:20 |
| 7           | 1          | 2019-03-07 20:23:05 |
| 8           | 0          | 2019-03-07 20:27:35 |
| 7           | 1          | 2019-03-07 20:27:37 |
| 8           | 0          | 2019-03-07 20:28:01 |
| 7           | 1          | 2019-03-07 20:37:19 |
| 8           | 0          | 2019-03-07 20:37:27 |
| 7           | 1          | 2019-03-07 20:37:54 |
| 8           | 0          | 2019-03-07 20:40:11 |
| 7           | 1          | 2019-03-07 20:44:00 |
| 8           | 0          | 2019-03-07 20:45:00 |
| 7           | 1          | 2019-03-07 20:47:41 |
| 7           | 1          | 2019-03-07 20:48:43 |
| 7           | 1          | 2019-03-07 20:48:51 |
| 8           | 0          | 2019-03-07 20:51:11 |
| 8           | 0          | 2019-03-07 20:54:46 |
| 8           | 0          | 2019-03-07 20:55:36 |
+-------------+------------+---------------------+
如何选择间隔15分钟但更接近下一次的记录

结果应该是这样的:

+-------------+------------+---------------------+
| ID          | Value      | Time                | 
+-------------+------------+---------------------+
| 1           | 1          | 2019-03-07 20:05:35 |
| 8           | 0          | 2019-03-07 20:22:20 |
| 7           | 1          | 2019-03-07 20:37:19 |
| 8           | 0          | 2019-03-07 20:51:11 |
+-------------+------------+---------------------+
如果第一次是20:05:35,下一次间隔15分钟是20:22:20。最接近的时间是20:22:20,因为它们之间的差值是00:02:14,20:17:35之间的差值是00:02:25。有什么方法可以计算差异并决定哪一个更接近选择吗?

尝试以下方法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication132
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Dates> dates = Dates.GetDates();

            var results = dates.GroupBy(x => new DateTime(x.Time.Year, x.Time.Month, x.Time.Day, x.Time.Hour, 15 * (x.Time.Minute / 15), 0).AddMinutes(15))
                .Select(x => x.OrderBy(y => x.Key.Subtract(y.Time)).First())
                .ToList();
        }
    }
    public class Dates
    {
        public int ID { get;set;}
        public int Value { get;set;}
        public DateTime Time { get;set;}

        public static List<Dates> GetDates()
        {
            string input =
                "| 1           | 1          | 2019-03-07 20:05:35 |\n" +
                "| 2           | 2          | 2019-03-07 20:06:09 |\n" +
                "| 5           | 5          | 2019-03-07 20:11:27 |\n" +
                "| 7           | 1          | 2019-03-07 20:13:30 |\n" +
                "| 8           | 0          | 2019-03-07 20:13:41 |\n" +
                "| 7           | 1          | 2019-03-07 20:17:00 |\n" +
                "| 8           | 0          | 2019-03-07 20:22:20 |\n" +
                "| 7           | 1          | 2019-03-07 20:23:05 |\n" +
                "| 8           | 0          | 2019-03-07 20:27:35 |\n" +
                "| 7           | 1          | 2019-03-07 20:27:37 |\n" +
                "| 8           | 0          | 2019-03-07 20:28:01 |\n" +
                "| 7           | 1          | 2019-03-07 20:37:19 |\n" +
                "| 8           | 0          | 2019-03-07 20:37:27 |\n" +
                "| 7           | 1          | 2019-03-07 20:37:54 |\n" +
                "| 8           | 0          | 2019-03-07 20:40:11 |\n" +
                "| 7           | 1          | 2019-03-07 20:44:00 |\n" +
                "| 8           | 0          | 2019-03-07 20:45:00 |\n" +
                "| 7           | 1          | 2019-03-07 20:47:41 |\n" +
                "| 7           | 1          | 2019-03-07 20:48:43 |\n" +
                "| 7           | 1          | 2019-03-07 20:48:51 |\n" +
                "| 8           | 0          | 2019-03-07 20:51:11 |\n" +
                "| 8           | 0          | 2019-03-07 20:54:46 |\n" +
                "| 8           | 0          | 2019-03-07 20:55:36";
            List<Dates> dates = new List<Dates>();

            string line = "";
            StringReader reader = new StringReader(input);

            while ((line = reader.ReadLine()) != null)
            {
                string[] lineArray = line.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

                Dates newDate = new Dates()
                {
                    ID = int.Parse(lineArray[0]),
                    Value = int.Parse(lineArray[1]),
                    Time = DateTime.Parse(lineArray[2])
                };

                dates.Add(newDate);
            }
            return dates;
        }
    }

}

若要在开始时间前15分钟分组,请使用此

            //tick is 100ns
            const long TICKS_PER_15_MINUTES = 15 * 60 * 10000000L; //minutes, seconds, ticks 

            DateTime minTime = dates.OrderBy(x => x.Time).First().Time;

            List<Dates> results = dates.GroupBy(x => (TICKS_PER_15_MINUTES * ((x.Time.Ticks - minTime.Ticks) / TICKS_PER_15_MINUTES) + TICKS_PER_15_MINUTES - 1))
                .Select(x => x.OrderBy(y => x.Key - y.Time.Ticks).First())
                .ToList();
//刻度为100ns
每15分钟的常量长滴答数=15*60*10000000升//分、秒、滴答声
DateTime minTime=dates.OrderBy(x=>x.Time).First().Time;
列表结果=日期.GroupBy(x=>(滴答声每15分钟*((x.Time.TICKS-minTime.TICKS)/TICKS每15分钟)+TICKS每15分钟-1))
.Select(x=>x.OrderBy(y=>x.Key-y.Time.Ticks).First()
.ToList();

最后,如果你想要最接近15分钟的时间

            //tick is 100ns
            const long TICKS_PER_15_MINUTES = 15 * 60 * 10000000L; //minutes, seconds, ticks 

            DateTime minTime = dates.OrderBy(x => x.Time).First().Time;

            List<Dates> results = dates.GroupBy(x => ((x.Time.Ticks - minTime.Ticks) % TICKS_PER_15_MINUTES) < (TICKS_PER_15_MINUTES / 2)
                ? TICKS_PER_15_MINUTES * ((x.Time.Ticks - minTime.Ticks) / TICKS_PER_15_MINUTES)
                : (TICKS_PER_15_MINUTES * ((x.Time.Ticks - minTime.Ticks) / TICKS_PER_15_MINUTES)) + TICKS_PER_15_MINUTES)
                .Select(x => x.OrderBy(y => Math.Abs( x.Key - y.Time.Ticks)).First())
                .ToList();
//刻度为100ns
每15分钟的常量长滴答数=15*60*10000000升//分、秒、滴答声
DateTime minTime=dates.OrderBy(x=>x.Time).First().Time;
列表结果=dates.GroupBy(x=>((x.Time.Ticks-minTime.Ticks)%Ticks\u每15分钟)<(Ticks\u每15分钟/2)
?每15分钟滴答声*((x.Time.TICKS-minTime.TICKS)/每15分钟滴答声)
:(每15分钟滴答声*((x.Time.TICKS-minTime.TICKS)/每15分钟滴答声)+每15分钟滴答声)
.Select(x=>x.OrderBy(y=>Math.Abs(x.Key-y.Time.Ticks)).First()
.ToList();

这似乎还可以,但我需要从20:05:35的第一条记录开始。这是我的参考/出发点。您是希望从一开始每15分钟一次,还是按时间间隔每15分钟一次?两者都可能是正确的。在很长的采样周期内,这并没有什么区别。当采样周期较短时,可能会产生差异。通常,你的间隔(15分钟)应该比采样周期短得多,这样就不会有什么区别。从开始算起,每15分钟一次,所以在这种情况下,开始时间是20:05:35,下一次是20:22:20,比20:17:00更近……嗯……也许我错过了什么,但结果中的第一次应该是20:05:35,下一次是20:22:20。。。在这个更新的代码中,第一个是20:17:00,第二个是20:28:01。。。请参阅我的文章和示例输出。您想要最近的15分钟还是接下来的15分钟?15分钟的时间是20:05:35,20:20:35,20:35:35。所以20:35:35-20:22:20=13:15,20:20:35-20:17:00=3:35,20:35:35-20:28:01=7:34。13:15大于3:35,除非您正在查找最近的而不是下一个。添加了一个答案,希望能有所帮助
            //tick is 100ns
            const long TICKS_PER_15_MINUTES = 15 * 60 * 10000000L; //minutes, seconds, ticks 

            DateTime minTime = dates.OrderBy(x => x.Time).First().Time;

            List<Dates> results = dates.GroupBy(x => ((x.Time.Ticks - minTime.Ticks) % TICKS_PER_15_MINUTES) < (TICKS_PER_15_MINUTES / 2)
                ? TICKS_PER_15_MINUTES * ((x.Time.Ticks - minTime.Ticks) / TICKS_PER_15_MINUTES)
                : (TICKS_PER_15_MINUTES * ((x.Time.Ticks - minTime.Ticks) / TICKS_PER_15_MINUTES)) + TICKS_PER_15_MINUTES)
                .Select(x => x.OrderBy(y => Math.Abs( x.Key - y.Time.Ticks)).First())
                .ToList();