mktime设计原理分析

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

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)

时间: 2024-08-28 00:22:06

mktime设计原理分析的相关文章

Terracotta设计原理分析--(部分内容来自官方描述)

因为工作中历史产品采用了terracotta作为分布式缓存线性扩展平台,因此不得不提前对其原理做了相关了解,当然其中很多的设计思想和oracle.memcached的设计相似,但也有自己的亮点,那就是JVM的懒加载细粒度拷贝以及线性扩展,使得序列化对象消耗大大降低,提高CPU使用率以及内存无缝线性扩展. 我在研究terracotta的时候,没有急于去尝试环境搭建以及demo实现,首先我去了解了一下为什么之前产品为什么会选型使用它.它是什么.能做什么.和其他相似的技术相比有什么优势,最后才做了相关

MyBatis的深入原理分析之1-架构设计以及实例分析

MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简单.优雅.本文主要讲述MyBatis的架构设计思路,并且讨论MyBatis的几个核心部件,然后结合一个select查询实例,深入代码,来探究MyBatis的实现. 一.MyBatis的框架设计        注:上图很大程度上参考了iteye 上的chenjc_it所写的博文原理分析之二:框架整体设计 中的MyBatis架构体图,chenjc_it总结的非常好,赞一个! 1.接口层---和数据库交互的方式 MyBatis

kafka入门:简介、使用场景、设计原理、主要配置及集群搭建(转)

问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行"随机读写"的原因是什么? 3.kafka集群consumer和producer状态信息是如何保存的? 4.partitions设计的目的的根本原因是什么? 一.入门 1.简介 Kafka is a distributed,partitioned,replicated commit logservice.它提供了类似于JMS的特性,但是在设计实现上完全不同,此外它并不是JMS规范的实现.k

kafka producer实例及原理分析

1.前言 首先,描述下应用场景: 假设,公司有一款游戏,需要做行为统计分析,数据的源头来自日志,由于用户行为非常多,导致日志量非常大.将日志数据插入数据库然后再进行分析,已经满足不了.最好的办法是存日志,然后通过对日志的分析,计算出有用的数据.我们采用kafka这种分布式日志系统来实现这一过程. 步骤如下: 搭建KAFKA系统运行环境 如果你还没有搭建起来,可以参考我的博客: http://zhangfengzhe.blog.51cto.com/8855103/1556650 设计数据存储格式

Adaboost算法原理分析和实例+代码(简明易懂)

Adaboost算法原理分析和实例+代码(简明易懂) [尊重原创,转载请注明出处] http://blog.csdn.net/guyuealian/article/details/70995333     本人最初了解AdaBoost算法着实是花了几天时间,才明白他的基本原理.也许是自己能力有限吧,很多资料也是看得懵懵懂懂.网上找了一下关于Adaboost算法原理分析,大都是你复制我,我摘抄你,反正我也搞不清谁是原创.有些资料给出的Adaboost实例,要么是没有代码,要么省略很多步骤,让初学者

AbstractQueuedSynchronizer的介绍和原理分析(转)

简介 提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架.该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础.使用的方法是继承,子类通过继承同步器并需要实现它的方法来管理其状态,管理的方式就是通过类似acquire和release的方式来操纵状态.然而多线程环境中对状态的操纵必须确保原子性,因此子类对于状态的把握,需要使用这个同步器提供的以下三个方法对状态进行操作: java.util.concurrent.locks.Abstra

深入理解HTTP协议、HTTP协议原理分析

深入理解HTTP协议.HTTP协议原理分析 目录(?)[+] http协议学习系列 1. 基础概念篇 1.1 介绍 HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写.它的发展是万维网协会(World Wide Web Consortium)和Internet工作小组IETF(Internet Engineering Task Force)合作的结果,(他们)最终发布了一系列的RFC,RFC 1945定义了HTTP/1.0版本.其中最著名的就是RFC 26

以属性为核心驱动的 全领域通用架构设计原理 (简称:属性架构原理)

以属性为核心驱动的全领域通用架构设计原理 (简称:属性架构原理) 联系方式:13547930387 Email:[email protected] 一.个人声明 我,参加工作也有5年多了,是一名普通的不能在普通的程序员,一直在使用公司自己的产品进行开发,因此技术比较菜,此设计完全是按照自己天真的想法而设计的,如果有不合理或很搞笑的地方,请轻拍,由衷的希望大家能提出宝贵的意见: 根据此设计原理我也做了一个简单的(demo)架构来支撑和验证此理论的可行性,由于技术功底不太好,有不合理之处请大家谅解,

Chromium和WebKit的智能指针实现原理分析

C++不像Java一样,由虚拟机负责对象分配和释放.也就是说,开发人员使用C++编写代码时,要自己负责对象分配和释放.WebKit和Chromium都是使用C++开发的,因此它们也面临上述问题.在解决对象释放问题时,要做到在对象不需要时自动释放,因为手动释放会带来忘记释放或者释放后又继续使用的隐患.智能指针是实现对象自动释放的有效技术手段.本文就分析Chromium和WebKit的智能指针的实现. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 在现实中,