C#:谨慎 DateTime.Now 带来的危险

这几天在做考勤处理相关的项目,在界面上放了开始日期和结束日期两个 DateTimePicker 控件,并都设置格式(Format)为 Short,再放置一个按钮 Button1,这样用户点击这个按钮时就对选择的时间段进行数据分析处理。为了节省时间,我把开始日期和结束日期分别设置为 向前15天到当前日期:

 

dtpBeginTime.Value = DateTime.Now.AddDays(-15);
dtpEndTime.Value = DateTime.Now;// 因为 DateTimePicker控件默认为当前时间,因此我就没有再设置,当然我设置后也测试过结果一样

 

 

然后处理的时候我就这样取天数了:

 

TimeSpan ts = EndTime.Value-BeginTime.Value;
int dayCount = (int)Math.Ceiling(ts.TotalDays) + 1;// 加1是因为开始日期那天也是要处理的。

 

然后我随便测试了几次就交给技术支持去测试了。过不久反馈来了:

处理的时候老是多了一天。

 

比如 今天是 21 号,那么默认 begintime 就是 21-15=6 号,总天数是 15+1=16 天,按他的意思应该变成了 17 天,但是事实上并不如此,我处理的时候也是 16天呀,那是哪里出了问题了呢?正在我百思不得其解的时候,我在处理界面上手工把开始日期改到 7号,按推算  21-7=14,再加1应该是15天,而处理过程中却是16天!那这多出的一天是怎么来的了?

我再次打开窗口,不做任何改动运行处理,结果还是 16天!仔细想想,是不是默认日期出了问题了?

 

现在我把默认值改成(只取日期部分):

 

dtpBeginTime.Value = DateTime.Now.Date.AddDays(-15);
dtpEndTime.Value 
= DateTime.Now.Date;

 

 

豁然开朗!前途一片光明!这样不管有没有手工改动过,处理天数完全正确的。

 

回忆一下,原来 DateTime.Now 这里包含时间,估计手工改开始日期的时候,微软就把时间部分去掉了,直接改成 2010-10-6 0:0:0 这个时间了。这样一处理,当然就有可能多出这么变态的一天!

版权声明 作者:夏荣全
邮箱:lyout(at)163.com
扣扣:249775085
本文版权归作者所有,转载请注明出处:http://www.cnblogs.com/lyout/
posted @ 2010-10-21 14:42 里沃特 阅读(1489) 评论(11) 编辑 收藏

 回复 引用 查看   
#1楼 2010-10-21 14:54 Spring.Cheung      
DateTime.Now.Date改成DateTime.Today也是可以的
看来 DateTime.Now.Date 还是蛮有必要的。

 回复 引用 查看   
#3楼[楼主] 2010-10-21 15:07 里奥特      
引用Spring.Cheung:DateTime.Now.Date改成DateTime.Today也是可以的


是可以,一样的。

 回复 引用 查看   
#4楼[楼主] 2010-10-21 15:08 里奥特      
引用吉日嘎拉 不仅权通用权限:看来 DateTime.Now.Date 还是蛮有必要的。


对,要不然几千人的工厂差一天就差远了。。
感谢支持~

 回复 引用 查看   
#5楼 2010-10-21 16:54 徐少侠      
引用代码:
int dayCount = (int)Math.Ceiling(ts.TotalDays) + 1;
你这里干嘛要使用Ceiling?
我觉得是这里的逻辑错了
你现在去掉这个ceiling试试结果还对不对?
我估计现在这个ceiling已经没有用了。

不过如果不修改你的默认值代码,而是去修改那个ceiling也是能解决问题的
反向求值,到地板上去


 回复 引用 查看   
#6楼[楼主] 2010-10-21 18:01 里奥特      
引用徐少侠:
引用代码:
int dayCount = (int)Math.Ceiling(ts.TotalDays) + 1;
你这里干嘛要使用Ceiling?
我觉得是这里的逻辑错了
你现在去掉这个ceiling试试结果还对不对?
我估计现在这个ceiling已经没有用了。

不过如果不修改你的默认值代码,而是去修改那个ceiling也是能解决问题的
反向求值,到地板上去



你可以去试一下,我已经试过了,TotalDays 是 double 型,取出来的值1天大概是 0.99999...之类的数字,如果直接 (int) 转换的话会变成0天。

 回复 引用 查看   
#7楼 2010-10-21 18:53 徐少侠      
不是有个加1在后面的么?
不会是0天的

 回复 引用 查看   
#8楼 2010-10-21 19:32 卡通一下      
楼主,我觉得这是你理解的问题,而不是什么“危险”,呵呵!

首先在程序启动时,两个DateTimePicker控制的日期之差确实是15天;也就是说dtpEndTime.Value = 2010-10-21 19:00;dtpBeginTime.Value = 2010-10-06 19:00,如果程序启动后,你手工将dtpBeginTime.Value的值调整,那么它的时、分将会归零,也就会多出“日期之差 + 时、分”。

如果你将两个同时手工调整,那就又会正确了,因为两个时间的时、分都被归零了。

另外,你改后的写法也可能出错,这样写似乎更好:
dtpEndTime.Value = DateTime.Now.Date;
dtpBeginTime.Value = dtpEndTime.Value.AddDays(-15);

 回复 引用 查看   
#9楼[楼主] 2010-10-22 08:44 里奥特      
引用徐少侠:
不是有个加1在后面的么?
不会是0天的


可是有两天。

 回复 引用 查看   
#10楼[楼主] 2010-10-22 08:45 里奥特      
@卡通一下
似乎是我理解的问题,但我相信这个会很N多人会犯的错误。

 回复 引用 查看   
#11楼 2010-11-10 16:30 單純的狼      
路过,学习!