诡异的DateTime.TryParseExact方法

老赵在介绍Routing扩展的WebCast中出了点“小状况”,即将DateTime.ToString(“yyyy-MM-dd”)修改为DateTime.ToString(“yyyy/MM/dd”)后,页面中仍然显示为yyyy-MM-dd样式的日期格式。相信看过WebCast的同学都还记得吧。我不解,将老赵代码中DateTimeFotmatter的Formate属性修改为yyyy/MM/dd,在页面中输入yyyy-MM-dd样式的日期,仍然没有抛出任何异常。这是怎么回事?难道日期转换失灵了吗?

老赵在做日期转换时,使用了DateTime.TryParseExact,那么我们就来看看这个TryParseExact是否在正常工作。

DateTime output;
DateTime.TryParseExact("2009-06-04", "yyyy/MM/dd", null, DateTimeStyles.None, out output);
Console.WriteLine(output.ToString());

以上代码的输出结果果然让人大跌眼镜,日期居然能正确转换!

image

难道TryParseExact的第二个参数format没有作用吗?将/改成.,居然又不能转换了:

image

看来是/这个符号的问题。请出Reflector,将mscorlib.dll反编译,找到DateTime.TryParseExact方法,一步一步跟进去。发现如果该方法的IFormatProvider参数为null,将获取当前线程的CultureInfo的DateTimeFormat属性作为IFormatProvider,然后在DateTimeParse.ParseByFormat方法中,遇到format参数的/字符时,会比较输入日期字符串的当前字符是否为当前DateTimeFormatInfo的DateSeperator,如果是,则返回true,即允许转换,如果不是则返回false。

CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
Console.WriteLine(cultureInfo.DateTimeFormat.DateSeparator);

而以上代码输出的恰恰为-,也就是说当前线程的区域信息中,日期分隔符即为-,因此,转换得以成功。

如果您使用

DateTimeFormatInfo dtfi = new CultureInfo("zh-CN", false).DateTimeFormat;
DateTime output;
DateTime.TryParseExact("2009-06-04", "yyyy/MM/dd", dtfi, DateTimeStyles.None, out output);
Console.WriteLine(output.ToString());

则转换失败,因为在初始化CultureInfo时,第二个参数为false意味着不使用用户选定的区域性设置,而使用默认的设置,这时的DateSeparator为/

至此,谜底全部解开。

// 小贴士:遇到.NET Framework内部实现的问题时,使用Reflector反编译类库并查看源代码的方式,往往可以解决您的问题:)

posted @ 2009-06-04 15:40  麒麟.NET  阅读(12277)  评论(2编辑  收藏  举报