【问题标题】:Is there a faster way to check if this is a valid date?有没有更快的方法来检查这是否是有效日期?
【发布时间】:2010-05-17 13:06:09
【问题描述】:

有没有更快的方法来简单地捕获如下异常?

try
{
    date = new DateTime(model_.Date.Year, model_.Date.Month, (7 * multiplier) + (7 - dow) + 2);
}
catch (Exception)
{
    // This is an invalid date
}

【问题讨论】:

  • 什么意思,更快?除非您的日期无效,否则此代码运行得非常快。或者您是在问是否有办法用更少的代码做到这一点?

标签: c# performance datetime


【解决方案1】:
String DateString = String.Format("{0}/{1}/{2}", model_.Date.Month, (7 * multiplier) + (7 - dow) + 2),model_.Date.Year);

DateTime dateTime;
if(DateTime.TryParse(DateString, out dateTime))
{
    // valid
}

正如 GenericTypeTea 所指出的,这段代码的运行速度不会比你现在的快。但是,我相信您会提高可读性。

【讨论】:

  • DateTime.TryParse 无论如何都会在内部抛出异常,这不会更快。
  • @GenericTypeTea - 这是错误的。 DateTime.TryParse() not 在内部抛出异常!将其视为 DateTime.Parse() 使用 DateTime.TryParse() 来首先决定是否需要抛出异常会更准确。
  • @Joel Coehoorn - 刚刚启动反射器来看看,我已经在这种误解下工作了很长一段时间。谢谢你纠正我。
  • -1 - 如果您的区域设置不是月/日/年,这将不起作用!
  • 我们为什么要尝试 DateTime.TryParse 一个 DateTime? model_.Date 显然是一个 DateTime... :)
【解决方案2】:

如果您的目标是避免使用异常,您可以编写自定义验证方法:

public bool IsValidDate(int year, int month, int multiplier, int dow)
{
    if (year < 1 | year > 9999) { return false; }

    if (month < 1 | month > 12) { return false; }

    int day = 7 * multiplier + 7 - dow;
    if (day < 1 | day > DateTime.DaysInMonth(year, month)) { return false; }

    return true;
}

这与您使用的 DateTime 构造函数执行大部分相同的验证 - 它只省略检查结果 DateTime 是小于 DateTime.MinValue 还是大于 DateTime.MaxValue。

如果您主要获得良好的值,那么总体上这可能会更慢:DateTime.DaysInMonth 必须做很多与 DateTime 构造函数相同的事情,因此它会增加所有好的日期的开销。

【讨论】:

  • 这正是我所需要的,没有区域设置问题
【解决方案3】:

嗯...这样想:model_ 类有一个 DateTime 属性

model_.Date

,因此无需验证年份和月份。唯一棘手的部分是月份中的哪一天:

(7 * multiplier) + (7 - dow) + 2

所以验证这一点的一种非常快速有效的方法(比投掷和捕捉更好)是使用 DateTime.DaysInMonth 方法:

if ((multiplier <= 4) && 
    (DateTime.DaysInMonth(model_.Date.Year, model_.Date.Month) < 
        (7 * multiplier) + (7 - dow) + 2))
{
    // error: invalid days for the month/year combo...
}

另一个好处是您不需要实例化一个新的 DateTime 来验证此信息。

P.S. 更新了代码以确保 multiplier 为 =5 都会使 DaysInMonth 测试失败...

【讨论】:

  • +1,我只是看了一下问题并考虑发布此问题。只是懒惰以任何其他方式。扔掉 .NET 国家的心态处于最佳状态。
  • +1 如果算法的速度确实是一个问题(问题仍然有点不清楚),一个保护子句检查乘数
【解决方案4】:

编辑:糟糕! DateTime.TryParse 不会在内部引发异常。我在说我的臀部!总之……

DateTime.TryParse() 将在内部引发异常,并导致与您的问题中的代码相同的结果。如果速度很重要,您必须编写自己的方法。

这可能看起来像更多代码,但我认为如果您预计会出现大量错误,它会更快:

public bool GetDate(int year, int month, int day, out DateTime dateTime)
{
    if (month > 0 && month <= 12)
    {
        int daysInMonth = DateTime.DaysInMonth(year, month);
        if (day <= daysInMonth)
        {
            dateTime = new DateTime(year, month, day);
            return true;
        }
    }
    dateTime = new DateTime();
    return false;
}

我上面的示例不会处理所有情况(即我不处理年份),但它会为您指明正确的方向。

【讨论】:

  • 为什么这会比 TryParse() 更快?
  • 对于返回bool 并且具有Nullable&lt;DateTime&gt;类型的输出变量的方法对我来说似乎有点多余(为什么不只是DateTime?)。 ..
  • 老实说,我是在对 DateTime.TryParse 的误解下操作的,并认为它在内部引发了异常。我已经深入研究了反射器并看到了它的实际作用,如果每次日期都是完美的,TryParse 可能会更快。但是,我相信如果有更多不正确的日期,这种方法会更快......所以如果要检查大量垃圾,这种方法会更好,但如果不正确的日期是边缘情况,那么 TryParse 会更好。
【解决方案5】:

验证日期的最快方法是单行:

static bool IsValidDate(int year, int month, int day) =>
             !(year < 1 || year > 9999 ||
            month < 1 || month > 12 ||
            day < 1 || day > DateTime.DaysInMonth(year, month));

使用 DateTime 构造函数或任何解析函数或任何异常处理程序都会减慢验证速度。仅当您想验证字符串时才首选 TryParse。

【讨论】:

    【解决方案6】:

    DateTime.TryParse方法

    【讨论】:

      【解决方案7】:

      但有一件事:例外是针对特殊情况的。 Bogoformatted 字符串不是例外,而是预期的,因此 TryParse 更合适。

      使用 try/catch 来检查有效性是对异常的误用和误解,尤其是使用 catch-all catch(后者已经让我花费数小时来寻找某些东西为什么不起作用,而且很多次)。

      【讨论】:

        【解决方案8】:

        我不知道更快,但是

        DateTime.TryParse()
        

        应该做同样的事情。

        如果有人能告诉我这是否比问题中描述的方式更快(就处理器时间而言),我会很感兴趣。

        【讨论】:

          【解决方案9】:

          如果解析机制没有更快,那么您可以使用稍微详细一点的方法来直接检查模型对象的属性以获取有效值。

          【讨论】:

            猜你喜欢
            • 2017-02-28
            • 2016-10-28
            • 1970-01-01
            • 2010-11-25
            • 2012-03-15
            • 1970-01-01
            • 2013-08-13
            • 1970-01-01
            • 2013-01-09
            相关资源
            最近更新 更多