zoukankan      html  css  js  c++  java
  • 坑!为什么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字段,它在需要时候才会被调用来获取值并返回,它是“动态”的,它才是真正的获取当前时间

    总结一下:

    1. 在开发过程中,对于类似DateTime.Now这种“动态”的值一定要留神;
    2. 头脑要时刻明白,这个值只是代码执行的一瞬间获取到的,保存到任何变量以后,它就已经是固定的、过去的;
    3. 确定需要获取真正的当前值得时候,使用表达式或者委托(Expression<Func<T>>或Func<T>)。

    努力工作 认真生活 持续学习 以勤补拙

  • 相关阅读:
    刷题总结——table(ssoi)
    算法复习——差分约束(ssoi种树)
    刷题总结——谈笑风生(主席树+dfs序的应用)
    刷题总结——序列操作(权值线段树套树状数组)
    刷题总结——shortest(ssoi)
    算法总结——主席树(poj2104)
    刷题总结——路径(ssoi)
    刷题总结——鸭舌(ssoi)
    刷题总结——电影(ssoi)
    刷题总结——随机图(ssoi)
  • 原文地址:https://www.cnblogs.com/dinggeonly/p/13277051.html
Copyright © 2011-2022 走看看