11

谁能解释为什么以下代码段返回 true?

根据“d”自定义格式说明符的文档,“一位数日的格式没有前导零。” 那么,当我给它一个带前导零的个位数日期时,为什么 TryParseExact 不会失败?

DateTime x;
return DateTime.TryParseExact
(
    "01/01/2001",
    @"d\/MM\/yyyy",
    null,
    System.Globalization.DateTimeStyles.None,
    out x
);

更新

我想也许我最初并不清楚。我真正想要了解的是:为什么 TryParseExact 接受一些不完全匹配的值?从我看到的所有文档中,'d' 匹配 '01' 和 '1' 就像 'MM' 匹配 'March' 和 '03' 一样是一个错误。这里的问题不在于这些值是等价的,而是它们与格式不匹配。

相关的文档片段是:

  • TryParseExact字符串表示的格式必须与指定的格式完全匹配。

  • 来自'd' 说明符一位数的日期格式不带前导零。

对我来说,'01' 的前导 0 似乎非常清楚,因此与 'd' 不完全匹配。

4

5 回答 5

8

来自 DateTimeParse.ParseByFormat() 中的 .NET 4 源代码:

case 'd':
    // Day & Day of week 
    tokenLen = format.GetRepeatCount();
    if (tokenLen <= 2) { 
        // "d" & "dd" 

        if (!ParseDigits(ref str, tokenLen, out tempDay)) { 
            if (!parseInfo.fCustomNumberParser ||
                !parseInfo.parseNumberDelegate(ref str, tokenLen, out tempDay)) {

                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                return (false); 
            }
        } 
        if (!CheckNewValue(ref result.Day, tempDay, ch, ref result)) { 
            return (false);
        }
    }
    else
    {...}

解析器将“d”和“dd”混为一谈。

于 2011-05-06T01:28:34.437 回答
3

似乎行为是设计使然,我认为它的工作方式与其他字符串格式选项一致。

举个例子:

//Convert DateTime to string
string dateFormat = "d/MM/yyyy";
string date1 = new DateTime(2008, 10, 5).ToString(dateFormat);
string date2 = new DateTime(2008, 10, 12).ToString(dateFormat);

//Convert back to DateTime
DateTime x1, x2;
DateTime.TryParseExact(date1, dateFormat, null, System.Globalization.DateTimeStyles.None, out x1);
DateTime.TryParseExact(date2, dateFormat, null, System.Globalization.DateTimeStyles.None, out x2);

Console.WriteLine(x1);
Console.WriteLine(x2);

在第一部分中,ToString()输出 10 月 12 日的两位数日期,因为只写出一位数日期没有多大意义(它会选择哪个数字,1 还是 2?)。因此,由于“d”在转换为字符串时代表一位或两位数的天数,因此在转换回DateTime. 如果没有,在我的示例中转换回DateTimeinTryParseExact将失败,这绝对不是预期的行为。

我想说,如果你真的需要完全匹配 ad/MM/yyyy 格式,你可能会使用正则表达式来验证字符串,然后将其传递给ParseTryParse或者TryParseExact(取决于你的正则表达式有多好,因为它必须处理如果您想使用闰年、30/31 天等Parse)。

于 2011-05-06T01:21:47.263 回答
0

我会说它不会失败,因为TryParseExact它足够聪明,知道'01' == '1'。

于 2011-05-06T01:04:17.137 回答
0

TryParseExact我想在这种情况下只是想保持灵活性。但是,当您使用格式说明符将日期转换为字符串时,“d”与“dd”应该并且会像宣传的那样工作。

于 2011-05-06T00:58:50.373 回答
0

因为单个 'd' 意味着您的 DateTime 值将被转换为尽可能短的值,即如果没有必要,则不前导零。我想当您从字符串转换为 DateTime 时它不应该失败,因为 TryParseExact 的格式字符串的主要目的是帮助转换为 DateTime,即它的作用类似于提示,它不是为了验证字符串格式。

如果您仍然需要核心字符串格式验证,您可以使用RegEx 。

于 2011-05-06T01:22:42.857 回答