【问题标题】:String to DateTime, TryParse was not enough字符串到 DateTime,TryParse 还不够
【发布时间】:2020-06-17 03:48:46
【问题描述】:

这是一个有效的方法:

        /// <summary>
        /// Checks date validity.
        /// </summary>
        /// <param name="candidate">String to check</param>
        /// <returns>Whether valid and result as a date</returns>
        private static Tuple<bool, DateTime?> ParseDate(string candidate)
        {
            DateTime result;
            if(DateTime.TryParseExact(candidate, "dd.MM.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd.M.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd.MM.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "d.M.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd.MM.yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd.M.yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd.MM.yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "d.M.yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd/MM/yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd/M/yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "dd/MM/yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result) ||
                DateTime.TryParseExact(candidate, "d/M/yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out result)
            )
            {
                return new Tuple<bool, DateTime?>(true, result);
            }

            return new Tuple<bool, DateTime?>(false, null);
        }

在那里添加大量的或分支对我来说似乎毫无用处。有什么更聪明的方法来做到这一点?我认为 DateTime.TryParse 会这样做,但它以 15.6.2020(过去的星期一)以某种方式失败并返回它不是有效日期。

是的,我知道那里有一百万个或分支丢失了。这也是我需要帮助的一个大问题。

【问题讨论】:

  • 您是否尝试过使用适当的文化进行解析?似乎"dd.M.yyyy" 应该做到了——你在调试器中尝试过吗?如果您真的想使用所有这些格式字符串,请将它们放在一个集合中并使用 foreach (您需要重新安排您的逻辑,但这不应该那么难)。此代码适用于我 (DateTime.TryParseExact(candidate, "dd.M.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out var result);),输入为 var candidate = "15.6.2020";。你会喜欢使用 - 这里的人坚持把月份数字放在第一位。
  • 是的,我没注意到。好点子。生病删除我的评论
  • 考虑将字符串分成三个部分并调用docs.microsoft.com/en-us/dotnet/api/…您可能需要特殊代码来处理 2 位数年份。
  • I thought DateTime.TryParse would do it, but it managed to somehow fail with 15.6.2020 (this past Monday) and return that it is not a valid date. 请出示该代码。

标签: c# datetime string-parsing


【解决方案1】:

有很多日期格式,有些是自定义的,这就是为什么您需要指定您将接受的有效格式。如果您可以在 UI 中验证格式或限制可接受的格式(如果日期来自某种手动输入),这将很有帮助。在 DateTime.TryParseExact 中,有一个接受字符串格式数组的重载,请参阅here

【讨论】:

    【解决方案2】:

    使用正则表达式来匹配字符串格式。像

    public bool IsStringDate(string candidate){
    
        var dateRegex = new Regex("^([0]\d|[1][0-2])\/([0-2]\d|[3][0-1])\/([2][01]|[1][6-9])\d{2}(\s([0-1]\d|[2][0-3])(\:[0-5]\d){1,2})?$");
    
        return dateRegex.Match(candidate).Success;
    }
    

    【讨论】:

      【解决方案3】:

      保持你同样的逻辑,我写了这个:

      public static bool TryParseDateTimeManyFormats(string toParse, out DateTime result)
      {
          result = default;
          foreach (var format in DateFormats)
          {
              if (DateTime.TryParseExact(toParse, format, CultureInfo.InvariantCulture, DateTimeStyles.None,
                  out result))
              {
                  return true;
              }
          }
      
          return false;
      }
      

      附有您的日期格式列表。然后我不断消除它们,直到我得到一个最小集合:

      private static readonly string[] DateFormats =
      {
          //"dd.MM.yyyy",
          //"dd.M.yyyy",
          //"dd.MM.yyyy",
          "d.M.yyyy",
          //"dd/MM/yyyy",
          //"dd/M/yyyy",
          //"dd/MM/yyyy",
          "d/M/yyyy",
          //"dd.MM.yy",
          //"dd.M.yy",
          //"dd.MM.yy",
          "d.M.yy",
          //"dd/MM/yy",
          //"dd/M/yy",
          //"dd/MM/yy",
          "d/M/yy",
      };
      

      然后我写了一个小测试工具,看起来像:

      public static void TestDateParsing()
      {
          string[] dates =
          {
              "31.1.1919",
              "22/01/1957",
              "1/2/2020",
              "03/04/1812",
              "1/2/03",
              "04/05/06",
              "30/2/2010",
              "15.6.2020",
          };
      
          foreach (var date in dates)
          {
              if (TryParseDateTimeManyFormats(date, out var result))
              {
                  Debug.WriteLine(($"[{date}] correctly parsed as {result}"));
              }
              else
              {
                  Debug.WriteLine($"Parsing [{date}] failed");
              }
          }
      }
      

      得到了这个结果(我在美国,所以我们默认使用疯狂的月-日-年格式):

      [31.1.1919] correctly parsed as 1/31/1919 12:00:00 AM
      [22/01/1957] correctly parsed as 1/22/1957 12:00:00 AM
      [1/2/2020] correctly parsed as 2/1/2020 12:00:00 AM
      [03/04/1812] correctly parsed as 4/3/1812 12:00:00 AM
      [1/2/03] correctly parsed as 2/1/2003 12:00:00 AM
      [04/05/06] correctly parsed as 5/4/2006 12:00:00 AM
      [15.6.2020] correctly parsed as 6/15/2020 12:00:00 AM
      Parsing [30/2/2010] failed
      

      这似乎不那么疯狂了。

      【讨论】:

        猜你喜欢
        • 2019-03-29
        • 1970-01-01
        • 2021-02-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-04
        • 2015-12-02
        • 1970-01-01
        相关资源
        最近更新 更多