linux程序mktime无权限,linux中mktime算法解析

Linux源码中的mktime算法解析

我们知道,从CMOS中读出来的系统时间并不是time_t类型,而是类似于struct tm那样,年月日时分秒是分开存储的。

那么,要把它转化为系统便于处理的time_t类型,就需要算法进行转换。

我们都知道我们的公历还是比较复杂的,有大月小月,有闰年非闰年,处理起来会很麻烦。

但是Linux的源代码仅仅用了短短的几行就完成了这个复杂的转换(Gauss算法),实在令人惊奇。话不多说,先看源代码:

include/linux/time.h

None.gifstaticinlineunsignedlongmktime(unsignedintyear,unsignedintmon,

None.gifunsignedintday,unsignedinthour,

None.gifunsignedintmin,unsignedintsec)

ExpandedBlockStart.gif{

ExpandedSubBlockStart.gifif(0>=(int) (mon-=2)){/* 1..12 -> 11,12,1..10 */ExpandedSubBlockStart.gif         mon+=12;/* Puts Feb last since it has leap day */6a9c071a08f1dae2d3e1c512000eef41.png         year-=1;

ExpandedSubBlockEnd.gif    }6a9c071a08f1dae2d3e1c512000eef41.png

6a9c071a08f1dae2d3e1c512000eef41.pngreturn(((

6a9c071a08f1dae2d3e1c512000eef41.png             (unsignedlong) (year/4-year/100+year/400+367*mon/12+day)+6a9c071a08f1dae2d3e1c512000eef41.png             year*365-719499ExpandedSubBlockStart.gif          )*24+hour/* now have hours */ExpandedSubBlockStart.gif       )*60+min/* now have minutes */ExpandedSubBlockStart.gif    )*60+sec;/* finally seconds */ExpandedBlockEnd.gif}

看上去令人眼花缭乱,毫无头绪。下面就让我们对该算法作具体的分析。

先不看前面的,直接看return那句,该式整体上具有这样的结构:

T = ((X * 24 + hour) * 60 + min) * 60 + sec

这说明该算法是先算出从1970年1月1日开始的天数X,再进而求出具体的时间值T的。

因此我们重点看如何求天数X。也就是X = year/4 - year/100 + year/400 + 367*mon/12 + day + year*365 - 719499这一部分。

首先可以将上式拆成:

/*    润年判断方法:

*    判断一:能被4整除,不能被100整除,是润年

*    判断二:不满足判断一时,如果能被400整除,是润年

*/

Y = year / 4 - year / 100 + year / 400

Z = 367 * mon / 12

W = year * 365 + day

X = Y + Z + W - 719499

Y很简单,它计算了从公元元年到所求年份为止所有的闰年数。从W式看出,该算法先假设所有年都是正常年(365天),再加上闰年额外的天数(式Y)。

到现在为止都算简单,关键是Z式和X式中的那个常数719499是怎么回事,似乎莫名其妙。还有就是它们和return语句前面的那个if判断有什么关系呢?

首先要澄清一点,常数719499并不是像很多人说的那样,是0001年1月1日到1970年1月1日所经历的天数。

不信你可以随手写个脚本,将得到正确的数字:719162天。

显然719162和719499是有关系的。我们把注意力放在那个if语句上:

None.gifmon-=2;

ExpandedBlockStart.gifif(mon<=0){

6a9c071a08f1dae2d3e1c512000eef41.png    mon+=12;

6a9c071a08f1dae2d3e1c512000eef41.png    year--;

ExpandedBlockEnd.gif}

很明显,它是想把1月和2月当作上一年年底的最后两个月,让3月作为一年的第一个月。这样一来,我们可以尽量少的被闰年所影响。

按照这个假设,让我们先不管Z式是怎么来的,看看0001年1月1日时,Y + Z + W等于什么:

mon = 1月变成上一年(公元前0001年)的11月;

year减一后变成了0,因此Y = 0;

Z = 367 * 11 / 12 = 336;

W = 1 + 0 * 365 = 1;

Y + Z + W = 337。

337这个数正好等于719499 - 719162!换句话说,它是对上述假设所做的补正!于是这些式子就变成了:

Y = year / 4 - year / 100 + year / 400

Z = 367 * mon / 12

V = Z - 337

W = year * 365 + day

X = Y + W + V - 719162

再来看式Z,这个式子表面看不出任何名堂,367这个数字显然很是奇怪。那让我们穷举一下mon,看看这个式子算出的都是些什么值吧:

mon         Z

1           30

2           61

3           91

4           122

5           152

6           183

7           214

8           244

9           275

10          305

11          336

12          367

似乎看出了什么?再让我们把相邻的两个mon的Z做一下减法看看:

mon         dZ

1           30

2           31

3           30

4           31

5           30

6           31

7           31

8           30

9           31

10          30

11          31

12          31

闻出点味道了吧,很象大小月的规则。让我们回想起那个if语句作了什么,它把1月2月变成了11月和12月,3月变成了1月!还原一下看看:

mon     org-mon         dZ

1       3               30

2       4               31

3       5               30

4       6               31

5       7               30

6       8               31

7       9               31

8       10              30

9       11              31

10      12              30

11      1               31

12      2               31

怎么本来应该是大月的3月成了30天?

那好我们想想这个原理,假设今天是1月1日,那你能说你今年已经过了31天了么?显然不是,1月还没过,我们不能把它算进去。

这里同然,我们从4月看起,如果今天是愚人节,那么距离3月1日我们经过了31天。

就像前面说的,我们假设一年是从3月开始,到次年的2月结束。按照这个规则,整个式子里有问题的只有3月,理论上这里应该是0!

但是这没关系,我们把它减去就行了,于是变成:

Z = 367 * mon / 12 - 30

V = Z - 307

回头看看W式,year * 365,但是按照上面的理论,没过完的这一年不应该加进去,所以这里把它减去,再和V式合并:

V = Z + 58

W = (year - 1) * 365 + day

我们记得这个算法的一年是从3月开始的,因此少算了公元元年的1月和2月的天数:31 + 28 = 59天:(公元元年是正常年)

V = Z + 59 - 1

那么最后的这个减1是什么?还是上面那个原理,今天还没过,就不应该把它算进去!

综上,整个算法就明朗了,主要难于理解的是那个3月开始的假设以及367 * mon / 12会产生类似大小月的序列。

最后把这些式子整理并罗列一下,做为本文的结束:

None.gifY = (year - 1) * 365 + year / 4 - year / 100 + year / 400None.gifM = 367 * mon / 12 - 30 + 59None.gifD = day - 1None.gifX = Y + M + D - 719162None.gifT = ((X * 24 + hour) * 60 + min) * 60 + sec

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/442890.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 无线网卡连接网络连接不上去,【已解决】Ubuntu 10.04 无线网卡 无法连接

----------------------------------搬家声明------------------------------------------------------------------------搬家声明--------------------------------------【已解决】Ubuntu 10.04 无线网卡 无法连接【问题】新装的Ubuntu 10.04&#xff0c;其他一切正常&#…

Linux 软件包管理器的目的是什么,Linux软件包的管理--RPM包管理器

在Linux中如何安装、升级、卸载软件&#xff0c;是我们日常运维中重要的组成部分。接下来一CentOS6系统为例&#xff0c;讲解如何使用 RPM 包管理器&#xff0c;yum包管理器以及源码的方式来管理我们的软件包。一、相关的背景知识许多程序的源程序&#xff0c;例如使用C语言编写…

嵌入式linux mongodb,小白在Ubuntu安装mongoDB与mongo-c-driver

目的&#xff1a;本人从事嵌入式软件&#xff0c;项目中需要使用MongoDB&#xff0c;最终需要熟悉c-driver的API&#xff0c;小白在搭建环境有些浪费时间&#xff0c;故写这文章让与我同样状态的开发人员学习学习。在Ubuntu上的安装mongodb方法一&#xff1a;sudo apt-get ins…

湘潭大学-软件工程-选择判断题复习

说明 期末考试单选题和判断题占30分&#xff0c;单选20&#xff0c;判断10分 单选题 选错误的 B依靠松散组合的互联网大众是无法开发出高质量软件产品的 D、所有命名都应尽量使用缩写 C、采用团队的组织方式 D、软件需求一旦确定就不允许变化 以下哪一项是通过运行程序…

c语言运算符ppt,C语言知识学习运算符.ppt

C语言知识学习运算符.ppt 第三章,C语言运算符,回顾,变量和常量的含义 熟悉基本数据类型 - int、char、float 和 double 使用算术运算符 理解类型转换 熟练使用 scanf 和 printf 函数,课程目标,算术运算符 增量运算符 逻辑运算符 关系运算符 按位运算符 C的特殊运算符 --“” “…

ionic判断android版本,$ionicplatform 判断是android还是ios?

一只名叫tom的猫安装环境首先应该安装好 node.js (略)&#xff0c;然后安装cordova、ionic等sudo npm install -g cordova ionic ios-sim创建不同类型的项目目前可以用blank&#xff0c;tabs&#xff0c;sidemenu三种ionic start myApp tabs常用插件cordova plugin add com.ion…

华为鸿蒙等不急了,华为最强巨作,鸿蒙OS+六摄+麒麟985,网友:等不及了!

原标题&#xff1a;华为最强巨作&#xff0c;鸿蒙OS六摄麒麟985&#xff0c;网友&#xff1a;等不及了&#xff01;华为最强旗舰机一般公认是Mate系列&#xff0c;虽然华为跟三星一样&#xff0c;也是走双旗舰&#xff0c;Mate和P系列都是旗舰机&#xff0c;但是华为和三星有所…

华为鸿蒙2.0操作页面,华为鸿蒙2.0开面界面确认,这一变化你可懂

最近一段时间关于华为鸿蒙手机端操作系统的消息非常多&#xff0c;但是由于目前仅是测试阶段&#xff0c;我们无法全面的了解这个全新的操作系统长什么样。在操作上有何不同等等&#xff0c;在这样的前提之下很多参与内测有朋友时不时的就会放出一些信息。5月5日有人放出了华为…

android p正式版,国内首家!一加正式推送Android P正式版

近日&#xff0c;相信不少一加6的用户都收到了Android9.0也就是Android P系统的推送&#xff0c;如果没有记错的话&#xff0c;这应该是首个推送Android P稳定版的系统&#xff0c;而此前一加也是首个开放Android P公测的手机品牌&#xff0c;看来一加在系统的更新推进速度上确…

html悬停放大图片代码,html – 放大图像并在悬停时显示div

在图像悬停时,我想放大图像并显示带有透明背景的div.这是我的代码.在下面的示例中,当我将鼠标悬停在.Image类中的图像上时,我想要缩放它,并希望在div的中心显示类.mylink的链接.我能够放大悬停但是当我为.text添加样式时,它不再放大图像.HTML&#xff1a;linkCSS&#xff1a;#B…

夜间模式html,夜间模式.html

demo.dark {background-color: #363636;filter: invert(100) hue-rotate(180deg);}.dark img {filter: invert(100) hue-rotate(180deg);}Switch theme一个第三方的 GMail 的 Web 客户端。百度链接var darkSwitch falsedocument.getElementById(switch).addEventListener(clic…

html5常用插件大全,前端常用插件utils汇总

发布于 2020-03-06工具库 || 数据处理表单验证---jquery图片懒加载---JavaScript---vue---react图片预览类似朋友圈满足聊天递增图片的需求---vue文件上传---JavaScript---vue单选框/复选框相关---jquery选择框tree树形---jquery无限滚动---vue列表拖拽---vue---react元素拖曳自…

刚学计算机先学什么好,计算机语言入门先学什么?

刚想开始计算机学习的小白难免会有这样的困惑&#xff1a;计算机语言入门先学什么&#xff1f;简单来讲&#xff0c;初学者需要先了解各种计算机语言&#xff0c;熟悉计算机组成原理&#xff0c;学习数据结构与算法、数据库、基础语法等等&#xff0c;这些都是必须经历的基础学…

xml控制html样式,XML与CSS综合设置实例

XML与CSS综合设置实例HTTP代码如下&#xff1a;charset "utf-8";charset "utf-8";bookname{display:block;font-size:36px;font-weight:bold;font-family:宋体;text-align:center;}bieming{display:block;font-size:20px;font-weight:normal;font-family:宋…

幼儿园体育游戏电子计算机教案,幼儿园体育游戏教案3篇

幼儿园体育游戏教案3篇让幼儿通过各种体能游戏,锻炼走、跑、跳、爬等的能力,发展身体的灵活性和平衡能力。具有一定的竞争意识和集体荣誉感。以下是小编精心整理的幼儿园体育游戏教案的相关教案&#xff0c;老师们快来欣赏学习吧!幼儿园体育游戏教案范文一体能游戏活动目标:1、…

计算机专业的三行情书,各专业三行情书,看懂你就是全能学霸!

导读你所在的专业有哪些三行情书&#xff1f;你说工科的我不解风情&#xff0c;我说我愿意用我的专业写三行情书&#xff0c;读给你听。先等等&#xff0c;等我看明白了再给你答复。四川师范大学晒出了不少三行情书&#xff1a;仔细读&#xff0c;很多都用上了专业梗&#xff0…

评价微型计算机总线的性能指标,计算机组成原理学习笔记(3):总线

文章目录课程笔记导览附录&#xff1a;英语解释第三章 总线3.1 总线的基本概念使用总线的原因&#xff1a;总线的定义总线上信息的传送总线结构举例单总线结构面向CPU的双总线结构以存储器为中心的双总线结构框图3.2 总线的分类3.3 总线性能及性能指标总线物理实现总线特性总线…

html键盘制作,HTML手写键盘(一)

HTML手写键盘 (单密码框)先上图粘贴图片.png大致原理&#xff1a;先用css画出整个键盘 &#xff0c;并没有input框&#xff0c;如果使用input实现效果&#xff0c;则需要多个input&#xff0c;这样的后果是需要多次调用键盘&#xff0c;影响整体的体验&#xff0c;用ul li画出密…

登录页面

<!doctype html> <html><head><meta charset"utf-8"><title></title></head><link rel"stylesheet" href"../css/登录页面.css" /><body><form action"#" method"get&…

在计算机网络术语中wan的中文意思是什么,男生聊天中wan是什么意思 wan是什么的缩写...

在聊天的过程中&#xff0c;有的人喜欢发“wan”&#xff0c;这是晚安的意思吗&#xff1f;还是其他的意思&#xff1f;男生聊天中wan是什么意思&#xff1f;wan是什么的缩写&#xff1f;男生聊天中wan是什么意思&#xff1a;wan是“玩”、“晚安的晚”等字的拼音&#xff0c;根…