2012-09-13 21 views
4

我有一個時間值列表,其格式爲「09.00 AM,12.00 PM,03.00 PM」etc..lets稱爲ListTimes .. 我有一個單一的時間值( testTimeValue),格式爲「xx.xx AM/PM」,並傳遞給函數。 我希望函數將這個'testTimeValue'與ListTimes中的每個項目進行比較,並返回最近的時間。例如:在上面的場景中,如果我將01.00 PM傳遞給該函數,則應該返回03.00 PM。比較AM,PM格式在C#中的時間值

foreach (string item in listItems) 
{ 
    //I need to consider the time formats in AM and PM and do a 
    //proper comparison and return the closest in original format.           
} 

return closestTimeValue; 
+0

使用'var'掩蓋'item'的確切類型。他們是絃樂隊,對吧? –

+0

是的..他們是字符串..我會編輯。 – ZVenue

回答

5

對於每個時間,運行DateTime.ParseExact

List<string> listTimes = new List<string>() { "09.00 AM", "12.00 PM", "03.00 PM" }; 
string testTimeString = "01.00 PM"; 
DateTime testTime = DateTime.ParseExact(testTimeString, "hh.mm tt", CultureInfo.InvariantCulture); 
DateTime closestTime = DateTime.MinValue; 
TimeSpan closestDifference = TimeSpan.MaxValue; 

foreach (string item in listTimes) 
{ 
    DateTime itemTime = DateTime.ParseExact(item, "hh.mm tt", CultureInfo.InvariantCulture); 
    TimeSpan itemDifference = (itemTime - testTime).Duration(); 

    if (itemDifference < closestDifference) 
    { 
     closestTime = itemTime; 
     closestDifference = itemDifference; 
    } 
} 

return closestTime.ToString("hh.mm tt"); 
1

首先我信任的數據類型爲datetime

  List<DateTime> dates = new List<DateTime>(); 
      dates.Add(DateTime.Parse("9/11/2001 1:00 PM")); 
      dates.Add(DateTime.Parse("9/11/2001 10:00 AM")); 
      dates.Add(DateTime.Parse("9/11/1002 3:00 PM")); 
      DateTime dateComp = DateTime.Parse("9/11/2001 11:00 AM"); 
      DateTime? dateClosest = null; 
      foreach (DateTime dt in dates) 
      { 
       if (dateClosest == null) dateClosest = dt; 
       else 
       { 
        if((dateComp.Subtract(dt).TotalMilliseconds) < 
         dateComp.Subtract((DateTime)dateClosest).TotalMilliseconds) 
        { 
         dateClosest = dt; 
        } 
       } 
      } 
+0

它的字符串..數據類型。請參閱OP中foreach循環代碼中的我的數據類型字符串。 – ZVenue

+0

是的,但你直到後來才添加。你不能將字符串轉換爲日期? – Paparazzi

+0

是的..我補充說,有人指出後..對不起.. – ZVenue

1

有趣的問題:)我寫了這個小測試程序來嘗試一下。如果您認爲它有道理,您應該能夠適應您的需求。基本上,從一個基準日期時間開始,在同一個24小時內生成一個隨機的「測試」,然後隨機生成一堆附加時間,然後看看哪一個與測試值有最小的差異(在你的情況下成爲比較的人)。

List<DateTime> times = new List<DateTime>(); 

Random rnd = new Random(); 
int hourCount = (24 * 60) - 1; 

DateTime dtBase = DateTime.Parse("01/01/2012 12:00 AM"); 
DateTime dtTest = dtBase.AddMinutes(rnd.Next(0, hourCount)); 

Console.WriteLine("Base: " + dtBase.ToString()); 
Console.WriteLine("Test: " + dtTest.ToString()); 
Console.WriteLine(); 

for (int i = 0; i < 24; i++) { 
    times.Add(dtBase.AddMinutes(rnd.Next(0, hourCount))); 
} 

times.Sort(); 

TimeSpan lastSpan = TimeSpan.MaxValue; 
DateTime dtMatch = DateTime.Now; 

foreach (DateTime dt in times) { 
    Console.Write(" " + dt.ToString()); 
    var diff = (dtTest - dt).Duration(); 
    if (diff < lastSpan) { 
     lastSpan = diff; 
     dtMatch = dt; 
    } 
    Console.WriteLine(); 
} 

Console.WriteLine(); 
Console.WriteLine("Closest match to {0:hh:mm tt} => {1:hh:mm tt} ({2})", dtTest, dtMatch, lastSpan); 

樣本輸出運行:

Base: 1/1/2012 12:00:00 AM 
Test: 1/1/2012 3:28:00 AM 

1/1/2012 1:03:00 AM 
1/1/2012 2:51:00 AM 
1/1/2012 2:52:00 AM 
1/1/2012 3:22:00 AM 
1/1/2012 4:30:00 AM 
1/1/2012 4:36:00 AM 
1/1/2012 5:50:00 AM 
1/1/2012 5:55:00 AM 
1/1/2012 6:50:00 AM 
1/1/2012 7:05:00 AM 
1/1/2012 7:17:00 AM 
1/1/2012 8:53:00 AM 
1/1/2012 9:25:00 AM 
1/1/2012 11:59:00 AM 
1/1/2012 12:22:00 PM 
1/1/2012 12:51:00 PM 
1/1/2012 2:04:00 PM 
1/1/2012 3:01:00 PM 
1/1/2012 3:26:00 PM 
1/1/2012 4:19:00 PM 
1/1/2012 6:15:00 PM 
1/1/2012 11:02:00 PM 
1/1/2012 11:28:00 PM 
1/1/2012 11:50:00 PM 

Closest match to 03:28 AM => 03:22 AM (00:06:00) 

所以你的情況的實際功能是這樣的:

DateTime GetClosestTime(DateTime testTimeValue, List<DateTime> listItems) { 

    TimeSpan lastSpan = TimeSpan.MaxValue; 
    DateTime dtMatch = DateTime.Now; 

    foreach (DateTime dt in listItems) { 
     var diff = (testTimeValue - dt).Duration(); 
     if (diff < lastSpan) { 
      lastSpan = diff; 
      dtMatch = dt; 
     } 
    } 

    return dtMatch; 
} 

假設你已經比較於其他位置的時候,您可以將其重寫爲省略testTimeValue參數。

希望這會有所幫助!

1

這裏有一個LINQ的版本,雖然這比Guvante的回答慢:

List<string> ListTimes = new List<string>() { "09.00 AM", "12.00 PM", "03.00 PM" }; 
string testTimeString = "01.00 PM"; 
DateTime testTime = DateTime.ParseExact(testTimeString, "hh.mm tt", CultureInfo.InvariantCulture); 

return ListTimes 
    .Select(x => new 
    { 
     Time = x, 
     Difference = (DateTime.ParseExact(x, "hh.mm tt", CultureInfo.InvariantCulture) - testTime).Duration() 
    }) 
    .OrderBy(x => x.Difference) 
    .First().Time; 
1

你可以自己寫。解決這樣的任務甚至是有趣的)...有時))

static void Main(string[] args) 
{  
    var listTimes = new string[] {"09.00 AM", "12.00 PM", "03.00 AM"}; 
    const string testTimeValue = "02.00 PM"; 
    Console.WriteLine(CompareFunction(listTimes, testTimeValue)); 
} 


public static string CompareFunction(IEnumerable<string> listTimes, string testTimeValue) 
{ 
    double minDiff = double.MaxValue; 
    string result = string.Empty; 

    foreach(string listTime in listTimes) 
    { 
      double difference = GetDifference(listTime, testTimeValue); 
      if(difference < minDiff) 
      { 
       minDiff = difference; 
       result = listTime; 
      } 
    } 
    return result; 
} 

private static double GetDifference(string time1, string time2) 
{ 
    return Math.Abs(ConvertStringTime(time1).TotalMinutes - ConvertStringTime(time2).TotalMinutes); 
} 

private static TimeSpan ConvertStringTime(string time) 
{ 
    Regex validationRegex = new Regex(@"\d\d.\d\d AM|PM"); 
    if(!validationRegex.IsMatch(time)) throw new FormatException("Input time string was not in correct format"); 

    Regex hoursRegex = new Regex(@"\d\d."); 
    Regex minutesRegex = new Regex(@".\d\d"); 
    bool postMeridiem = time.Contains("PM"); 

    string hstring = hoursRegex.Match(time).ToString().Replace(".", string.Empty); 
    string mstring = minutesRegex.Match(time).ToString().Replace(".", string.Empty); 

    double h = postMeridiem ? double.Parse(hstring) + 12 : double.Parse(hstring); 
    double m = double.Parse(mstring); 

    return new TimeSpan(0, (int)h, (int)m, 0); 
}