.NET平台下很多功能是根据本地化配置来的,如果没有很好的注意这些就会出现错误,年少无知的时候总会写出一些糟糕的代码,更不幸的是那样糟糕的时期还挺高产的,现在想挽救得付出很大的代价。
曾今看过这样一段C/C++代码:
#define ture true #define flase false #define viod void
当时就懵逼了,原来还能这么玩,当然这并不是什么好的技巧,不值得Get,纯属拿出来开下玩笑。
然而,就在今天我遇上了一个严重的问题,关于DateTime的ToString方法的问题!!!
比如下面这段测试代码:
1 var dt = new DataTable(); 2 dt.Columns.Add("FTime", typeof(DateTime)); 3 dt.Rows.Add(DateTime.Now); 4 5 var value1 = dt.Rows[0][0]; 6 var formatTime1 = Convert.ToDateTime(value1); 7 var formatTime2 = Convert.ToDateTime(value1.ToString());
其中第7行代码在特定情况下会失败,报异常 该字符串未被识别为有效的 DateTime。
什么情况下呢?
修改了本地的日期格式,也就是当我本机设置日期格式为此格式时,DateTime 类型 ToString(不指定format的情况下),虽然很多情况下,我们经常会ToString("yyyy-MM-dd HH:mm:ss"),当时就如以上的测试代码中,从DataTable读出来的值是object,还需要强转一下(请暂时忽略DBNull的情况),然而从我之前的代码来看,我并没有强转,再指定format去ToSting(),按照以上设置ToString()后得到是 ,然而此时我再通过 Convert.ToDateTime("2016/1/5/星期二 16:43:43") 时就会报异常了,即使用Convert.ToDateTime(value1.ToString(), DateTimeFormatInfo.CurrentInfo) 依然无法解决问题。
然后就产生了这样的想法:把ToString()的默认格式改掉!
这样我不用改之前写下的不合代码啦!
这样我就不用每次ToString都指定成 yyyy-MM-dd HH:mm:ss (其他自定义时间格式在我们目前的框架下保存到MySql中是有些问题的,惭愧)!
于是,我就研究了一下 DateTimeFormatInfo.CurrentInfo ↓↓↓
用了个非常笨的办法,就一个个改这里面字段的值,然后在即时窗口里面用 DateTime.Now.ToString() 测试。
经测试发现,影响的关键在于generalLongTimePattern!!!
然而,写代码时才发现 generalLongTimePattern 是访问不到的,甚至通过属性 GeneralLongTimePattern 都无法给其设置值,我想可能是通过其他的方法来设置,但徘徊了一会MSDN和StackOverFlow都没有找到答案。
不过这并不是问题,既然我可以在Visual Studio 中可以修改它的值:
那么我用反射依然可以做到!
于是就有了以下这段代码:
//输出未修改前本地化设置的ToString结果 Console.WriteLine(DateTime.Now); //还真没测出DateTimeFormatInfo.CurrentInfo是NULL的情况,但是预防一下 if (DateTimeFormatInfo.CurrentInfo != null) { var type = DateTimeFormatInfo.CurrentInfo.GetType(); var field = type.GetField("generalLongTimePattern", BindingFlags.NonPublic | BindingFlags.Instance); //我怂!! if (field != null) field.SetValue(DateTimeFormatInfo.CurrentInfo, "yyyy-MM-dd HH:mm:ss"); }
测试运行结果:
至此,偷懒大功告成,回去玩PS4咯~~~~~
我猜其中必有槽点,您发现了但说无妨!