DateTime.TryParseExact not working as expected

烈酒焚心 提交于 2019-12-05 01:08:34

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.

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).

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

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!