【问题标题】:Compare time values in AM , PM format in C#在 C# 中比较 AM、PM 格式的时间值
【发布时间】:2012-09-13 21:12:30
【问题描述】:

我有一个时间值列表,格式为“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;

【问题讨论】:

  • var 的使用掩盖了item 的确切类型。它们是字符串,对吧?
  • 是的..它们是字符串..我会编辑。

标签: c# .net string list


【解决方案1】:

每次运行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");

【讨论】:

    【解决方案2】:

    首先我相信数据类型是 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;
                        }
                    }
                }
    

    【讨论】:

    • 它的字符串..数据类型。请在 OP 的 foreach 循环代码中查看我的数据类型字符串。
    • 是的,但您直到后来才添加。您不能将字符串转换为日期吗?
    【解决方案3】:

    这是一个 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】:

      有趣的问题:) 我写了这个小测试程序来尝试一下。如果您认为它有意义,您应该能够根据您的需要进行调整。基本上,从一个基本日期时间开始,在相同的 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 参数。

      希望这会有所帮助!

      【讨论】:

        【解决方案5】:

        你可以自己写。解决这样的任务甚至很有趣……有时))

        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);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-23
          • 1970-01-01
          • 2015-07-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多