为什么DateTime.Now显示的时间总是比实际时间早,是哪里出了问题?

摘要:好久没发文章了,感觉确实该动动了。实际上已经准备了几篇内容,但是不整理到自己感觉清晰的程度,总是不想发布,因为网上零零碎碎的信息确实太多了,不必再多一份。 所以今天谈一个简单点的问题:DateTime.Now获取时间竟然不是当前时间! 原始
好久没发文章了,感觉确实该动动了。实际上已经准备了几篇内容,但是不整理到自己感觉清晰的程度,总是不想发布,因为网上零零碎碎的信息确实太多了,不必再多一份。 所以今天谈一个简单点的问题:DateTime.Now获取时间竟然不是当前时间! 原始场景使用FluentValidation框架做数据验证,顾客的出生日期与当前日期DateTime.Now.Date做对比, 对比结果就出现了标题所说的场景,Log记录大体意思是客户生日[2020-7-6]不能晚于当前日期。 而此时时间是2020-7-8。这不是怪了么!2020-7-6确实是前端传过来的没有错。 出现这个问题的时候,我的内心是崩溃的!这样说是DateTime.Now.Date获取时间不正确?What's the hell! 在说出这里面的鬼之前,先看一段代码。 1 class TimeValidation 2 { 3 /// <summary> 4 /// 最大时间值 5 /// </summary> 6 readonly DateTime _timeMax; 7 8 public TimeValidation(DateTime timeMax) 9 { 10 _timeMax = timeMax; 11 } 12 13 public bool IsTimeValid(DateTime time) 14 { 15 return time <= _timeMax; 16 } 17 } 对于这个验证类,执行以下代码返回值应该是什么呢? 1 var timeValidation = new TimeValidation(DateTime.Now); 2 bool result1 = timeValidation.IsTimeValid(now); 3 //概括目的就是:实例化验证类,用当前时间作为属性值的最大限定值, 4 //然后验证当前时间是不是有效的值, 5 //这时result1是true还是false?请先选出你的答案 最终结果当然不是true,否则就不会感觉见鬼了。在说明缘由之前,再看一段代码或许大家都能恍然大悟。 1 class TimeValidationEx 2 { 3 /// <summary> 4 /// 最大时间值表达式 5 /// </summary> 6 readonly Expression<Func<DateTime>> _timeMaxEx; 7 8 public TimeValidationEx(Expression<Func<DateTime>> timeMaxExpression) 9 { 10 _timeMaxEx = timeMaxExpression; 11 } 12 13 public bool IsTimeValid(DateTime time) 14 { 15 return time <= _timeMaxEx.Compile()(); 16 } 17 } 对于这个验证类,执行以下代码返回值应该是什么呢? 1 var timeValidation2 = new TimeValidationEx(() => DateTime.Now); 2 bool result2 = timeValidation2.IsTimeValid(now); 3 //这时result2是true还是false? 答案是true。 此时或许大家都能想到到底哪里有鬼了。 对于TimeValidation类,实例化时候传递参数DateTime.Now,本来意图是传递当前时间,但实际只是传递当前这一时刻的时间值,并赋值给了内部的_timeMax字段。 而赋值完成后,这个“当前时间”就已经是历史了(我提到的案例中就是停留在了昨天2020-7-6),而不是我们想要的当前时间了。 对于TimeValidationEx类,实例化时候传递参数是() => DateTime.Now,这是一个Expression<Func<DateTime>>类型的值(如果不了解Expression,可以单独去了解一下)。 而在验证方法里代码也是这样的: return time <= _timeMaxEx.Compile()(); 所有_timeMaxEx是一个Expression<Func<DateTime>>类型的实例,是一个Expression,而这个Expression内部是一个Func<DateTime>委托, 委托就是特殊的方法嘛,而这个方法的逻辑就是直接返回DateTime.Now的值。 相对TimeValidation类中的_timeMax字段,它在需要时候才会被调用来获取值并返回,它是“动态”的,它才是真正的获取当前时间! 总结一下: 在开发过程中,对于类似DateTime.Now这种“动态”的值一定要留神; 头脑要时刻明白,这个值只是代码执行的一瞬间获取到的,保存到任何变量以后,它就已经是固定的、过去的; 确定需要获取真正的当前值得时候,使用表达式或者委托(Expression<Func<T>>或Func<T>)。 努力工作 认真生活 持续学习 以勤补拙