4

「09.00AM、12.00 PM、03.00PM」などの形式の時間値のリストがあります。これをListTimesと呼びます。同じ形式の「​​xx.xxAM/ PM」の単一の時間値(testTimeValue)があります。関数に渡していること。この'testTimeValue'をListTimesの各項目と比較し、それに最も近い時間を返す関数が必要です。例:上記のシナリオで、関数に01.00 PMを渡すと、03.00PMが返されます。

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

まず、データ型が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

興味深い問題:)私はそれを試すためにこの小さなテストプログラムを書きました。あなたがそれが理にかなっていると思うなら、あなたはそれをあなたのニーズに適応させることができるはずです。基本的に、基本日時から開始し、同じ24時間以内にランダムに1つの「テスト」を生成し、次にランダムに追加の時間を生成して、テスト値との差が最も小さいものを確認します(この場合はと比較されるものになります)。

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

自分で書くことができます。そのようなタスクを解決するのも楽しいです...時々))

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 に答える