我有一个列表DateTime类型,我需要更接近00:00:00,06:00:00,12:00:00和18:00:00。
我正在使用for循环遍历列表,并使用一些if条件来获取其间的值。
但是,我不知道如何获得更接近的值,我也想知道是否有办法使用LINQ获得正确的结果。
TimeSpan ts1 = new TimeSpan(list[i].Item1.Hour,
list[i].Item1.Minute,
list[i].Item1.Second);
TimeSpan ts2 = new TimeSpan(list[i + 1].Item1.Hour,
list[i + 1].Item1.Minute,
list[i + 1].Item1.Second);
if (ts1.TotalHours < 00 && ts2.TotalHours > 00)
Console.WriteLine("00:00:00 {0} {1} Take: {2}", ts1, ts2, ts1);
else if (ts1.TotalHours < 06 && ts2.TotalHours > 06)
Console.WriteLine("06:00:00 {0} {1} Take: {2}", ts1, ts2, ts1);
else if (ts1.TotalHours < 12 && ts2.TotalHours > 12 )
Console.WriteLine("12:00:00 {0} {1} Take: {2}", ts1, ts2, ts1);
else if (ts1.TotalHours < 18 && ts2.TotalHours > 18)
Console.WriteLine("18:00:00 {0} {1} Take: {2}", ts1, ts2, ts1);
输出:
00:00:00 11:59:59 12:59:58 Take: 11:59:59
00:00:00 17:59:57 19:00:00 Take: 17:59:57
00:00:00 11:59:59 13:00:00 Take: 11:59:59
00:00:00 16:59:59 18:00:01 Take: 16:59:59
00:00:00 05:59:58 07:00:00 Take: 05:59:58
00:00:00 11:59:58 12:59:59 Take: 11:59:58
00:00:00 17:59:57 18:59:59 Take: 17:59:57
00:00:00 11:00:02 12:00:01 Take: 11:00:02
00:00:00 11:00:02 12:00:02 Take: 11:00:02
00:00:00 16:59:59 18:00:01 Take: 16:59:59
00:00:00 10:59:58 12:00:01 Take: 10:59:58
00:00:00 17:00:02 18:00:01 Take: 17:00:02
00:00:00 05:59:58 06:59:58 Take: 05:59:58
00:00:00 11:59:59 12:59:59 Take: 11:59:59
00:00:00 17:00:00 18:00:01 Take: 17:00:00
00:00:00 11:59:59 12:59:57 Take: 11:59:59
00:00:00 05:59:57 07:00:01 Take: 05:59:57
00:00:00 10:59:58 12:00:01 Take: 10:59:58
00:00:00 17:00:01 18:00:01 Take: 17:00:01
00:00:00 05:59:59 07:00:02 Take: 05:59:59
答案 0 :(得分:2)
您可以减去2个时间跨度。 如果差异超过12小时,则从24小时减去。
TimeSpan oneDay = new TimeSpan(24,0,0);
TimeSpan zero = new TimeSpan(0,0,0); //the timespan you want to compare against
TimeSpan diff1 = (ts1 - zero).Duration();
if (diff1.TotalHours >= 12) diff1 = oneDay - diff1;
TimeSpan diff2 = (ts2 - zero).Duration();
if (diff2.TotalHours >= 12) diff2 = oneDay - diff2;
TimeSpan closest = diff1 < diff2 ? ts1 : ts2
答案 1 :(得分:1)
我不确定您是否正在尝试这样做,但是以下方法会返回最接近给定DateTimes
的所有TimeSpan
(可以是具有相同距离的多个):< / p>
public static IEnumerable<DateTime> GetNearestToTime(TimeSpan targetTime, params DateTime[] dates)
{
TimeSpan negativeTarget = TimeSpan.FromHours(24) - targetTime;
var dateInfos = dates
.Select(dt => new
{
DateTime = dt,
MinDistance = new[] { (dt.TimeOfDay - targetTime).Duration(), (dt.TimeOfDay - negativeTarget).Duration() }.Min()
});
var distanceLookup = dateInfos.ToLookup(x => x.MinDistance);
TimeSpan min = distanceLookup.Min(x => x.Key);
return distanceLookup[min].Select(x => x.DateTime);
}
这个例子显示了难度:
Target: midnight
Date1 = 2014-11-28 02:00:00
Date2 = 2014-11-27 23:00:00
第二个DateTime
应该会在晚上11点(23点)接近午夜而不是早上2点时获胜。
这是一个带有一些日期和时间的示例以及这个边缘情况:
TimeSpan[] spans = {TimeSpan.FromHours(0), TimeSpan.FromHours(6),TimeSpan.FromHours(12),TimeSpan.FromHours(18)};
var now = DateTime.Today; // midnight
var list = new List<DateTime> { now.AddMinutes(-99), now.AddMinutes(+100), now.AddMinutes(199), now.AddMinutes(-200) };
for (int i = 0; i < list.Count; i+=2)
{
DateTime dt1 = list[i];
DateTime dt2 = list[i + 1];
IEnumerable<DateTime> nearestToMidNight = GetNearestToTime(spans[0], dt1, dt2);
Console.WriteLine("{0} nearest: {1}", spans[0], string.Join(",", nearestToMidNight));
// and so on with the other timespans...
}
输出:
00:00:00 nearest: 27.11.2014 22:21:00
00:00:00 nearest: 27.11.2014 20:41:00
答案 2 :(得分:1)
您可以检索Ticks属性的值,并将偏移量和模运算符应用于它。 这允许直接测试基础值,并避免调用对其进行冗余计算的属性或方法。
const long TicksPerSecond = 10000000L;
const long TicksPer1Hour = TicksPerSecond * 3600;
const long TicksPer3Hours = TicksPer1Hour * 3;
const long TicksPer6Hours = TicksPer1Hour * 6;
const long TicksPerDay = TicksPer1Hour * 24;
private static long GetDiffFrom6Hours(DateTime time)
{
return Math.Abs(TicksPer3Hours - (((time.Ticks % TicksPerDay) + TicksPer3Hours) % TicksPer6Hours));
}
模数运算符将24小时分成4个块,与您比较的时间相匹配。 偏移量只允许进行1次比较,而不是4次。
要通过Linq对列表进行排序,您只需执行以下操作:
var list2 = list.OrderBy(item => GetDiffFrom6Hours(item.Item1));
的问候,
丹尼尔。
答案 3 :(得分:0)
我经历了所有答案,我不得不说Dennis_E中的那个是最好最简单的。但是,我更简化了它,对于00:00:00的情况,我使用了以下代码。 06:00:00,12:00:00和18:00:00可以使用相同的逻辑。另外,如果可以使用LINQ找到解决方案,那将会很棒。
TimeSpan ts00 = new TimeSpan(00, 00, 00);
TimeSpan diff1 = (ts1 - ts00).Duration();
TimeSpan diff2 = (ts2 - ts00).Duration();
TimeSpan closest = diff1 < diff2 ? ts1 : ts2;
Console.WriteLine("00:00:00 Take: {0}\n\n", closest);