DateTime.ParseExact,包含7位数字/一个月或两位数月份

到目前为止,我认为我会理解DateTime.ParseExact如何工作,但这是令人困惑的。 为什么跟随行返回false

 DateTime.TryParseExact("2013122", "yyyyMdd", CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out lastUpdate) 

月份也可以有两位数。 在我看来,它应该能够理解它意味着2013年1月22日。为什么我走错了路? 我错过了什么或者是否有简单的解决方法?


同时我正在使用这种不太优雅的解决方法,但有效:

 public static DateTime? ParseDate_yyyyMdd(String date) { if (date == null) return null; date = date.Trim(); if (date.Length < 7) return null; if (date.Length == 7) date = date.Insert(4, "0"); DateTime dt; if (DateTime.TryParseExact(date, "yyyyMMdd", CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out dt)) return dt; return null; } 

给出我想要的结果:

 DateTime? date = ParseDate_yyyyMdd("2013122"); Console.Write(date.ToString()); // 01/22/2013 

但是,我仍然对这种限制的原因感兴趣。 也许有人也有更好的方法。

从MSDN文档 :

如果不在自定义格式模式中使用日期或时间分隔符,请使用provider参数的不变区域性和每个自定义格式说明符的最宽格式。 例如,如果要在模式中指定小时数,请指定较宽的forms“HH”,而不是较窄的forms“H”。

我认为原因是它试图从左到右解析(没有回溯)。 由于没有分隔符,因此无法确定日期部分的边界。

http://msdn.microsoft.com/en-us/library/ms131044(v=vs.110).aspx

如果不在自定义格式模式中使用日期或时间分隔符,请使用provider参数的不变区域性和每个自定义格式说明符的最宽格式 。 例如,如果要在模式中指定小时数,请指定较宽的forms“HH”,而不是较窄的forms“H”。

我在源代码中找到了它。 这证实了活动挂图和Mark Sturgill的答案。

在某处调用内部ParseByFormat,它会计算(在您的情况下)’M’:

  // System.DateTimeParse private static bool ParseByFormat(ref __DTString str, ref __DTString format, ref ParsingInfo parseInfo, DateTimeFormatInfo dtfi, ref DateTimeResult result) { ... case 'M': num = format.GetRepeatCount(); if (num <= 2) { if (!DateTimeParse.ParseDigits(ref str, num, out newValue2) && (!parseInfo.fCustomNumberParser || !parseInfo.parseNumberDelegate(ref str, num, out newValue2))) { result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null); return false; } } 

下一个调用不是很有趣,除了ParseDigits调用中的2个小数字:

  // System.DateTimeParse internal static bool ParseDigits(ref __DTString str, int digitLen, out int result) { if (digitLen == 1) { return DateTimeParse.ParseDigits(ref str, 1, 2, out result); } return DateTimeParse.ParseDigits(ref str, digitLen, digitLen, out result); } 

但现在我们来到有趣的部分:

  // System.DateTimeParse internal static bool ParseDigits(ref __DTString str, int minDigitLen, int maxDigitLen, out int result) { result = 0; int index = str.Index; int i; for (i = 0; i < maxDigitLen; i++) { if (!str.GetNextDigit()) { str.Index--; break; } result = result * 10 + str.GetDigit(); } if (i < minDigitLen) { str.Index = index; return false; } return true; } 

这意味着(已经回答):

如果不使用最大位数且下一个字符也是数字,则格式无效。 这是以下返回true的原因:

 DateTime.TryParseExact("20131-22", "yyyyM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out lastUpdate) 

不要问我这个限制的原因 - 它只是在源代码中。