DateTime.TryParseExact 未按预期工作

发布于 2024-11-05 02:49:11 字数 954 浏览 4 评论 0原文

谁能解释为什么以下代码片段返回 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”说明符A单位数字日期的格式不带前导零。

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

Can anyone explain why the following snippet returns true?

According to the docs for The "d" custom format specifier, "A single-digit day is formatted without a leading zero." So why doesn't TryParseExact fail when I give it a single-digit day with a leading zero?

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

UPDATE

I think maybe I was unclear originally. What I am really trying to get at is: Why does TryParseExact accept some values that don't match exactly? from all of the documentation I have seen, 'd' matching '01' and '1' is just as much a bug as if 'MM' matched 'March' as well as '03'. The issue here isn't that the values are equivalent, its that they don't match the format.

The relevant snippets of documentation are:

  • From TryParseExact: The format of the string representation must match a specified format exactly.

  • From The 'd' Specifier: A single-digit day is formatted without a leading zero.

It seems abundantly clear to me that '01' has a leading 0, and therefore doesn't exactly match 'd'.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

冧九 2024-11-12 02:49:11

来自 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”集中在一起。

From the .NET 4 source in DateTimeParse.ParseByFormat():

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
    {...}

The parser lumps "d" and "dd" together.

平生欢 2024-11-12 02:49:11

看来这种行为是设计使然的,我认为它的工作方式是为了与其他字符串格式选项保持一致。

采取以下示例:

//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.如果没有,在我的示例中 TryParseExact 中转换回 DateTime 将会失败,这绝对不是预期的行为。

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

It appears that behavior is by design, and I think it works that way to be consistent with other string formatting options.

Take the following example:

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

In the first part, ToString() outputs a two digit day for October 12th, because it wouldn't make much sense to just write out a single digit day (and which digit would it pick, the 1 or the 2?). So since the "d" represents one OR two digit days when converting to a string, it would have to work the same way when converting back to DateTime. If it didn't, the conversion back to DateTime in TryParseExact in my example would fail, and that would definitely not be an expected behavior.

I would say that if you really need to match a d/MM/yyyy format exactly, you could probably use a regex to validate the string and then pass it through Parse, TryParse or TryParseExact (depending on how good your regex is, since it would have to handle leap years, 30/31 days, etc if you wanted to use Parse).

呢古 2024-11-12 02:49:11

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

I'd say it doesn't fail because TryParseExact is smart enough to know that '01' == '1'.

Saygoodbye 2024-11-12 02:49:11

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

TryParseExact is just trying to be flexible in this case I guess. But the "d" vs "dd" should and would work as advertised when you are converting date to string using a format specifier.

塔塔猫 2024-11-12 02:49:11

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

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

Because a single 'd' means that your DateTime value will be converted to as short value as possible, i.e. without leading zero if there's no necessity for it. I suppose it shouldn't fail when you're converting from string to DateTime because the main purpose of TryParseExact's format string is to help to convert to DateTime, i.e. it serves like a hint, it's not intended to validate string format.

You can use RegEx if you still need hardcore string format validation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文