簡體   English   中英

從列表中將時間更接近00:00:00、06:00:00、12:00:00和18:00:00的最佳方法

[英]Best way to get closer time to 00:00:00, 06:00:00, 12:00:00 and 18:00:00 from list

我有一個列表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

您可以減去2個TimeSpans。 如果相差超過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

我不確定這是否是您要嘗試的操作,但是以下方法將返回最接近給定TimeSpan所有DateTimes (可以是多個,且距離相同):

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應該贏,因為晚上(23H)的晚上11點比早上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

您可以檢索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));

問候,
丹妮爾

我仔細研究了所有答案,不得不說,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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM