代码之家  ›  专栏  ›  技术社区  ›  Brandon

在不知道年份的情况下使用datetime.typarseexact

  •  6
  • Brandon  · 技术社区  · 15 年前

    我有一个方法(有时)采用字符串的格式 "dddd MMMM dd" (2004年1月4日星期一)需要解析为日期时间。我有时会说,因为它也可能被传进来 "Today" "Tomorrow" 作为价值。

    处理这个问题的代码非常简单:

    if (string.Compare(date, "Today", true) == 0)
        _selectedDate = DateTime.Today;
    else if (string.Compare(date, "Tomorrow", true) == 0)
        _selectedDate = DateTime.Today.AddDays(1);
    else
        _selectedDate = DateTime.Parse(date);
    

    这项工作一直持续到12月中旬。你们中的一些人可能已经发现了问题所在。

    这在新年的任何一天都会失败,错误是:

    “字符串未被识别为有效的日期时间,因为星期几不正确。”

    它正在通过 "Monday January 04" 2010年有效,2009年无效。

    所以我的问题是:有没有办法为今年或下一年设定年份?现在,作为一个快速而肮脏的解决方案,我有:

    if (!DateTime.TryParseExact(date, "dddd MMMM dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out _selectedDate))
        if (!DateTime.TryParseExact(date + " " + (DateTime.Now.Year + 1), "dddd MMMM dd yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out _selectedDate))
            throw new FormatException("That date is not valid.");
    

    因此,它将尝试使用当前年份对其进行分析,如果不成功,它将使用下一年再次进行分析。如果在那之后失败了,那就假设这是一个无效的日期,因为我只需要提前1年担心,但是如果有人有更灵活的解决方案,我会感激的。(注意,我不需要担心验证传入的日期,它将对当前或下一年有效)。

    1 回复  |  直到 15 年前
        1
  •  8
  •   Brandon    15 年前

    首先,您的单元测试应该已经捕获到了这一点。您可能需要重新访问为此方法编写的测试,以从中学习如何更全面地涵盖您的功能。

    第二,你为什么要使用 String.Compare 而不是 String.Equals ?我认为以下内容更具可读性:

    date.Equals("Today", StringComparison.InvariantCultureIgnoreCase);
    

    我认为它能更清楚地读出正在发生的事情(尤其是当我们不必记住决赛的时候) bool 参数表示输入 比较字符串 )

    现在,来了解你问题的核心。您的方法非常好,并且非常清楚地表达了逻辑。不过,我会做一个小的重构:

    public DateTime ParseInThisYearOrNextYear(string s, out DateTime dt)
    {
        if (!Parse(s, "dddd MM dd", out dt))
        {
            if (!Parse(s + " " + DateTime.Now.Year + 1, "dddd MM dd yyyy", out dt))
            {
                throw new FormatException();
            }
        }
    
        return dt;
    }
    
    bool Parse(string s, string format, out DateTime dt)
    {
        return DateTime.TryParseExact(
            s,
            format,
            CultureInfo.InvariantCulture,
            DateTimeStyles.None,
            out dt
        );
    }
    

    这将您的方法分为两个不同的功能块,并防止重复您自己的操作。( CultureInfo.InvariantCulture DateTimeStyles.None )使测试和维护更加容易。(您可能需要比 Parse ;我选择了一个简短的滚动条,以防止滚动条出现在此处的代码窗口中。)

    最后一个警告是(不知道系统的详细信息),您可能还需要考虑检查上一年!想象一下以下情况:

    1. 输入为“12月31日星期四”(2009年有效)。
    2. 该系统将于1月1日跨越边界进入2010年。
    3. 代码执行并检查2010年和2011年,两者都失败。

    只是一些需要考虑的事情,这取决于你的系统的性质。