在C#中比较AM,PM格式的时间值

时间:2012-09-13 21:12:31

标签: c# .net string list

我有一个时间值列表,格式为“09.00 AM,12.00 PM,03.00 PM”等等。小时称之为ListTimes .. 我有一个时间值(testTimeValue)与我传递给函数的格式“xx.xx AM / PM”相同。 我希望函数将此'testTimeValue'与ListTimes中的每个项进行比较,并返回最接近它的时间。例如:在上面的场景中,如果我将01.00 PM传递给该函数,它应该返回03.00 PM。

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;

5 个答案:

答案 0 :(得分: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 :(得分: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;
                    }
                }
            }

答案 2 :(得分: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参数。

希望这有帮助!

答案 3 :(得分: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;

答案 4 :(得分: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);
}