转载地址:https://www.cnblogs.com/cndccm/p/11974754.html

原创地址:https://blog.csdn.net/chinaeran/article/details/43601699

昨天呢,刚刚阅读了这个代码,大部分都还可以看懂,有一两个地方属实难懂,但细细思来,方知博主此代码超神奇。简直巧妙至极。

所以来细细解析一下此代码。

话不多说。我们先来看一下原文。

#include <stdio.h>
#include <stdlib.h>

int day_diff(int year_start, int month_start, int day_start
, int year_end, int month_end, int day_end)
{
int y2, m2, d2;
int y1, m1, d1;

m1 = (month_start + 9) % 12;
y1 = year_start - m1/10;
d1 = 365y1 + y1/4 - y1/100 + y1/400 + (m1306 + 5)/10 + (day_start - 1);

m2 = (month_end + 9) % 12;
y2 = year_end - m2/10;
d2 = 365y2 + y2/4 - y2/100 + y2/400 + (m2306 + 5)/10 + (day_end - 1);

return (d2 - d1);
}

int main(void)
{
printf("%d\n", day_diff(2015, 1, 1, 2015, 1, 8));
printf("%d\n", day_diff(2015, 1, 29, 2015, 2, 9));

return 0;
}

这里呢是原文代码。

可以看到非常简短,接下来,就让你真正见识到这个代码的巧妙之处。

接下来我们先来看一下楼主的解析

算法解析:

该算法总体思想是计算给定日期到 0年3月1日的天数,然后相减,获取天数的间隔。

m1 = (month_start + 9) % 12; 用于判断日期是否大于3月(2月是判断闰年的标识),还用于纪录到3月的间隔月数。

y1 = year_start - m1/10; 如果是1月和2月,则不包括当前年(因为是计算到0年3月1日的天数)。

d1 = 365y1 + y1/4 - y1/100 + y1/400 + (m1306 + 5)/10 + (day_start - 1);

其中 365*y1 是不算闰年多出那一天的天数,y1/4 - y1/100 + y1/400  是加所有闰年多出的那一天,

(m2*306 + 5)/10 用于计算到当前月到3月1日间的天数,306=365-31-28(1月和2月),5是全年中不是31天月份的个数

(day_start - 1) 用于计算当前日到1日的间隔天数
————————————————

我们由简到繁,慢慢分析:

其中关于最后的 (day_start - 1)就不用多说了吧。

我们主要来讲讲没别的地方。

先来看这里:

d1 = 365*y1 + y1/4 - y1/100 + y1/400

本文思路在这在说一下:即计算每个日期距离0年三月一日的相差天数,在做差即得两日期之间天数。

好了言归正传所谓闰年四年一闰,百年不闰,四百又多一闰。

我们从0年3月一日开始算到我们输入哪一年的3月一日截止先计算整年的天数总和。

0年的二月已过。所以考虑从1年到截止年的闰年个数。

用y1/4算出可被4整除的年数,我们记为疑是闰年年数。后我们减去y1/100,去掉其中的不是闰年年数,但是由于四百年又多一闰所以我们又加上了y1/400;

这样就可以完美的算出所经过的年的总天数,关于这里的年数还涉及后面的(- m1/10)一项,这个我们后面来细细解答,这里是本文最巧妙的地方之一,,先留个悬念哈。

好了我们接着往下看。

m1 = (month_start + 9) % 12;

这个就比较巧妙了,需要与

(m1*306 + 5)/10和(- m1/10)两项结合来分析。这里就到了作者算法最为精妙的部分了,不得不说这个代码真的神奇。

OK,继续。来看(- m1/10),和m1 = (month_start + 9) % 12;的结合。

先来看,怎么样才能让余数大于10呢,1,2,这两个结果对吧。如果是m1大于10 的话呢,可知年数会减一。

简单点来说呢就是用计算年总天数的计算到当年3月一号的天数总和,

如果当年不到三月,即1,2月,我们就往前推一年,计算到上一年的3月一号的天数,

至于多出来的天数我们接着看,别急。

县来看如果是1,n那么结果就是10,

即为一月份,意思是距离上一年的3月一号过去了10个月,对吧,

即上一年的3,4,5,6,7,8,9,10,11,12

其中一共有多少天呢,其中3.5.7.8.10.11位31天每月。

即结果为30*10+6

带入 (m1*306 + 5)/10即得真的为306;是不是很神奇。

我们将这个公式一一带入算一下。

下面呢 ,我们先看m1.再看月份,再看天数。

2,,,,,余11,4,5,6,7,8,9,10,11,12,1对吧,带入刚好为337;

3,,,,,余00

4,,,,,余13带入得31

5,,,,,余二3,4带入61;

6,,,,,余三3,4,5带入92

7,,,,,余四3,4,5,6带入122

8.,,,,,余五3,4,5,6,7带入153

9,,,,,余六,3,4,5,6,7,8带入184

10,,,,,余七,3,4,5,6,7,8,9滴入214

11,,,,,余8,3,4,5,6,7,8,9,10带入245

12,,,,,余9,,3,4,5,6,7,8,9,10,11带入275

OK,是不是发现都对,是不是很神奇。

我也这样觉得,我来为大家分析其玄妙之处

先来分析月份问题。

随余数的增加月份为3 4 5 6 7 8 9 10 11 12 1

先来看为31天的月份有,3 5 7 8 9 10 12 1

看一下其中大部分30,31天的月份间隔,对吧,

简单看一下即可看出由于306后面的6的原因及后面5的作用下

我们把它稍微化简一下化为(m1300+5+m16)/10

m1*300的我们直接滤掉

(5+6*m1)/10;

可以看到

1得1

2得1

3得2

最容易的得知的就是每加二回多一天即上面的初步规律30,31间隔出现

其中有两个特例,7到8,12到2

包含7,和7,8月份的余数分别为5,6

可以得出符合,

再看1到12你会发现一样符合,

到底为什么呢

看6

多出来的6是最最中心的地方

月份每加一,在其原来的31,30紧挨着变化的情况下会多出来一个1

而当月份为5,10时,会凑乘5,而后再过一个月,按30,31来看为 偶数,是30天,不过由于6多出来的五和多一月多出来的6结合,又会造就一个31天,而且和前一个31天还是挨着的

所以,7月到8月的特例就包含了。

再看12月到1月的情况12月时余数为10,一月为11.

是不是又凑成一个5,后面一加有多出来一天。

OK,本次解析到此结束,

慢慢领悟此代码的玄妙之处吧

再见。嘿嘿

再次声明

代码不是我的

转载自https://blog.csdn.net/chinaeran/article/details/43601699

个人作品, 如有错误,请指出; 如要转载,请注明出处。 三克油。。

关于计算两日期之间经过多少天的超巧妙算法(转载)相关推荐

  1. 计算两日期之间差多少天----日期格式为:yyyy-mm-dd

    计算两日期之间差多少天 日期格式为yyyy-mm-dd //计算日期差值的方法: //计算日期差值的方法: function getDaysBetween(dateString1, dateStrin ...

  2. Python计算两日期之间排除节假日与非上班时间的工作时间

    Python计算两日期之间排除节假日与非上班时间的工作时间 前言 一.基本思路 二.代码示例 总结 文章目录 前言 一.基本思路 二.代码示例 总结 前言 工作中遇见需要写UDF计算事项办理时间的需求 ...

  3. java 跨年 周计算公式_如何跨年计算 两日期之间相隔的周数 with java8 time API

    ===============================2016年9月版 分割线======================================== 之前版本的我太simple了.. ...

  4. java:通过Calendar类正确计算两日期之间的间隔

    在开发Android应用时偶然需要用到一个提示用户已用天数的功能,从实现上来看无非就是持久化存入用户第一次使用应用的时间firstTime(通过SharedPreferences .xml.sqlit ...

  5. 通过Calendar类正确计算两日期之间的间隔

    在开发时需要用到一个提示用户已用天数的功能,从实现上来看无非就是持久化存入用户第一次使用应用的时间firstTime(通过SharedPreferences .xml.sqlite等),当用户再次使用 ...

  6. 【excel】利用NETWORKDAYS.INTL函数计算两日期之间的工作日时间

    语法 NETWORKDAYS.INTL(start_date, end_date, [weekend], [holidays]) start_date 和 end_date:必需,要计算其差值的日期. ...

  7. python时间计算_python计算两日期之间工作日时长

    1. 原因:使用dateutil的rrule时,计算速度比较慢 def axx(): from dateutil import rrule received_time = datetime.datet ...

  8. MySql计算两日期时间之间相差的天数,秒数,分钟数,周数,小时数

    计算两日期时间之间相差的天数,秒数,分钟数,周数,小时数,这里主要分享的是通过MySql内置的函数 TimeStampDiff() 实现. 函数 TimeStampDiff() 是MySQL本身提供的 ...

  9. Oracle 计算两日期间隔月数

    Oracle 计算两日期之间月数 实际应用中,有时候会计算两日期间隔天数.月数.如直接相减,可能会出问题,如: select 202110-202106 from dual; 结果为:4 看似正确,但 ...

最新文章

  1. 独家|OpenCV 1.2 如何用OpenCV扫描图像、查找表和测量时间(附链接)
  2. 高可用keepalived实例
  3. 用数据驱动思想来设计游戏-读《游戏编程精粹1》
  4. angularjs 导出excel php,AngularJS 导出Excel指令
  5. JAVA Swing——设置JButton按钮样式
  6. 为什么说 Java 是按值传递的?
  7. 微软项目管理[EPM]数据库应用举例2: 取得一个项目的某大纲代码的值
  8. hibernate与jpa_将JPA Hibernate与OptaPlanner集成
  9. 每秒处理1000万用户请求…云上架构如何实现高性能和高可用
  10. IT项目经验和难点分享
  11. Arcgis Android 基本概念 - 浅谈
  12. paip.数组以及集合的操作uapi java php python总结..
  13. SQL 删除重复数据,重复数据只保留ID最小的行
  14. 【自制线系列】Schneider HMI 与 PLC 通信线制作教程
  15. 网络应用程序体系结构
  16. 计算机无纸化考试知识点,2012重庆无纸化考试《会计电算化》知识点:计算机软件...
  17. IDEA直接查找快捷键来修改这个快捷键
  18. linux系统启动设置mac,Apple表示新款Mac将阻止Linux启动
  19. Android App屏幕旋转要点
  20. xshell 基本操作命令

热门文章

  1. 取消idea双击shift键时出现的全局搜索
  2. 地名翻译混乱 广东省质监局出台规范
  3. 第十五届全国大学生智能汽车竞速比赛规则 (预览)
  4. 博弈Ai官网ChatGPT4和3.5的真实功能测评
  5. VW 80000-2021版,最新发行,(3.5 吨以下汽车电气和电子部件试验项目标,试验条件和试验要求),大众标准
  6. 给tr标签设置外边距
  7. qt 获得系统输入法列表_2020法考主观题机考模拟系统入口(正式开通)!
  8. 7-9 集合相似度 (25分)
  9. vue使用ts 引入组件_vue项目中使用ts(typescript)入门教程
  10. 数学在计算机专业中的应用,高等数学在计算机专业教学中的应用