码迷,mamicode.com
首页 > 其他好文 > 详细

mktime设计原理分析

时间:2015-04-30 10:37:16      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:

代码分析很多,这里不细讲,着重分析其中一些设计技巧:

static inline unsigned long mktime (unsigned int year, unsigned int mon,
    unsigned int day, unsigned int hour,
    unsigned int min, unsigned int sec)
{
    if (0 >= (int) (mon -= 2)) {    /* 1..12 -> 11,12,1..10 */
         mon += 12;      /* Puts Feb last since it has leap day */
         year -= 1;
    }

    return (((
             (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
             year*365 - 719499
          )*24 + hour /* now have hours */
       )*60 + min /* now have minutes */
    )*60 + sec; /* finally seconds */
}

第一个有趣的地方是,将1、2月前移。为什么这么做呢?

举个例子:2012/12/23,这一天,怎么计算0001/01/01到这一天的闰年数呢?

year/4 - year/100 + year/400


这个式子的确是正确的,可以正确计算出闰年数,但是我们真正计算的不是闰年数,而是闰年增加的天数。由于是2012/02/23,没有经过二月,所以在计算由于闰年增加的天数的时候不能计算2012年的,因此要对上式进行纠正:

year/4 - year/100 + year/400 - 1

因此在计算闰年对整个天数的影响的时候需要考虑是否经过了2月,就引入了判断条件,实现更为复杂了。

设计者巧妙地将1、2月前移,规避掉了这个问题。现在每年是从三月开始的,2012/02对应2011/12,2012/03对应2012/01,这里就天然规避掉了上述问题,可以保证

year/4 - year/100 + year/400

计算增加的天数必然是正确的。


第二个有趣的地方是这个式子:367*mon/12,367是什么鬼?

带入不同的mon计算下:

30、61、91、122、152、183、214、244、275、305、336、367

算一算序列前后的差值:

30、31、30、31、30、31、31、30、31、30、31、31

对比一下正常的每月天数(2月按30算):

31、30、31、30、31、30、31、31、30、31、30、31

刚好就是正常月份天数循环左移一个月的结果,很神奇有木有!!

这样就好解释367*mon/12的意思了,还是举个例子说明:

计算2012/02/23,先前移2011/12/23,367*mon/12的值为367,367-30-1=336,这就表示前十一个月(实际是2011/03/23-2012/02/23)已经经过的天数(-30是去掉多加的367*1/12,-1是因为不能算今天,这两个计算体现在719499中)。


这里又有一个巧妙的地方:由于2月现在到了最后面,2011/12/23(真实日期2012/02/23),所以就可以不考虑闰年不闰年的问题了,336+day=359。如果日期是2011/12/29(真实日期2012/02/29),336+day=365,结果完全正确。

看到这里,有没有觉得有什么不对的?嗯,对,完全没有输入合法性判断,输入日期2011/02/29和2011/03/01结果会是一样的。

由于这个函数主要是内核用来转换其他时间结构的,比如struct tm,输入合法性在其他地方应该是有判断,但是如果是自己要使用这么一个函数,务必注意检测下输入的合法性。(虽然也可以计算出结果,但未免有些奇怪,不排除是调用者写错了;除了格式正确外,还要记得判断计算不要溢出了哦)。

PS:标准库<time.h>也有个转换函数:time_t mktime(struct tm *timeptr)

mktime设计原理分析

标签:

原文地址:http://blog.csdn.net/zycamym/article/details/45371163

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!