4

我有一个格式为“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;
4

5 回答 5

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");
于 2012-09-13T21:18:08.147 回答
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参数。

希望这可以帮助!

于 2012-09-13T21:48:51.487 回答
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;
于 2012-09-13T21:49:20.413 回答
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;
                    }
                }
            }
于 2012-09-13T21:37:40.523 回答
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);
}
于 2012-09-13T22:24:06.600 回答