到现在为止,我认为我会理解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
但是,我仍然对这种限制的原因感兴趣。也许有人也有更好的方法。
答案 0 :(得分:5)
如果不在自定义格式模式中使用日期或时间分隔符,请使用provider参数的不变区域性和每个自定义格式说明符的最宽格式。例如,如果要在模式中指定小时数,请指定更宽的形式,&#34; HH&#34;而不是更窄的形式,&#34; H&#34;。
我认为原因是它试图从左到右解析(没有回溯)。由于没有分隔符,因此无法确定日期部分的边界。
答案 1 :(得分:2)
http://msdn.microsoft.com/en-us/library/ms131044(v=vs.110).aspx
如果您不在自定义格式模式中使用日期或时间分隔符,请使用provider参数的不变文化和每个自定义格式说明符的最宽格式。例如,如果要在模式中指定小时数,请指定更宽的形式“HH”,而不是更窄的形式“H”。
答案 2 :(得分:2)
我在源代码中找到了它。这证实了活动挂图和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)
不要问我这个限制的原因 - 它就在源代码中。