以前发在EHblog的老博文,现在关闭了,准备陆陆续续搬迁一点过来。时间久了,有些文章也不一定保值了。

———————————————以下原文发表于2009-7-27———————————————

从不同的角度来看,

Excel早期版本的帮助文件中,对

参数start_date代表时间段内的第一个日期或起始日期。参数end_date代表时间段内的最后一个日期或结束日期。参数unit为所需信息的返回时间单位代码。各代码对应的含义如下:

"Y"——时间段中的整年数。

"M"——时间段中的整月数。

"D"——时间段中的天数。

"MD"——start_date与end_date日期中天数的差。忽略日期中的月和年。

"YM"——start_date与end_date日期中月数的差。忽略日期中的日和年。

"YD"——start_date与end_date日期中天数的差。忽略日期中的年。

这6个unit参数看上去极其简单,无非就是年月日的差值运算,但其实里面包含了许多玄机,下面将针对这6种unit代码分别进行详解:

以下假定start_date存放于A2单元格内,end_date存放于B2单元格内。

1,=

此参数含义为返回时间段内的整年数,

1)所谓“整年”的判断包含了两个日期值(m-d)的大小判断,假定A2与B2相差一年,如果B2的日期值小于A2的日期值,则不满一整年;如果B2的日期值大于等于A2的日期值,则可以记为一整年。

2)对于包含闰年的情况,不影响日期值大小的判断,例如A2为闰年的2月29日,则B2为闰年的2月29日及以后或非闰年的3月1日及以后都可以判断为大于等于A2日期。

综合以上算法解释,这个参数的算法可以表示为以下的公式:

=YEAR(B2)-YEAR(A2)-1+(DATE(YEAR(B2),MONTH(A2),DAY(A2))<=B2)

=YEAR(B2)-YEAR(A2)-1+(A2<=DATE(YEAR(A2),MONTH(B2),DAY(B2)))

2,=

此参数含义为返回时间段内的整月数,

要判断整月数,也是与A2、B2的所在月份及日期相关。

此参数的算法为:将B2、A2相减得到的天数记为Days1,从A2开始到B2的前一个月的所有月份的天数和值记为Days2,如果Days1大于等于Days2,则满足最后一个月的整月条件,否则则不足最后一个月的整月。

换言之,使用此参数时,首先计算前后日期之间的差值,然后以起始月到(中止月-1)之间的整月天数作为计算“整月”的依据,差值大于或等于整月天数的,函数结果就是(中止月-起始月);如果差值小于整月天数,函数结果就是(中止月-起始月-1)。

综合以上算法解释,这个参数的算法可以表示为以下的公式:

=(YEAR(B2)-YEAR(A2))*12+MONTH(B2)-MONTH(A2)-(B2-A2

3,=Datedif(A2,B2,"D")

此参数含义为返回时间段内的天数,

这个参数算法最简单,实质就是两个Date相减得到的天数差,其算法可以表示为以下的公式:

=B2-A2

4,=Datedif(A2,B2,"MD")

此参数含义为返回时间段内的天数,忽略月和年。

虽然说“忽略”月和年,但实际上当B2的day小于A2的day时,两者的日期差为负数,需要借位相减才能得到正数。如何借位,向谁借位就涉及到了两个日期的所在月份及其年份。

此参数算法包含以下几部分:

1)当B2的day大于等于A2的day时,可直接将两者的day相减得到结果。

例如A2为2003年3月4日,B2为2004年1月9日,其中的B2的day为9,A2的day为4,则函数结果为9-4=5。

2)当B2的day小于A2的day时,以B2所在日期作为基准,将B2减去Date(B2所在年份、B2的前一个月份、A2的day)所得到的差值为结果。

例如A2为2003年3月4日,B2为2004年2月3日,则将B2减去2004年1月4日的天数差作为函数结果。假如B2的月份为1月,则其前一个月份为前一年的12月。

3)此参数在Excel 2007 SP2版本中包含bug,当满足上面第二个条件且B2日期为闰年的1月份日期时,函数结果会偏大164。这个bug在Excel2003 SP3版本中不存在,但在目前尚未发布的Excel 2010中仍有这个问题存在,只不过那个版本中的差值为113。这个莫名其妙的数值如何出现的,目前暂时没搞清楚。

4)此参数包含的另一个问题可能不能算bug,但在各个版本中都存在,由于第二条算法的原因,当A2的day为29、30、31且B2的月份为3月份时,由于B2的前一个月份即2月份中没有29号、30号、31号,Date(B2所在年份、B2的前一个月份、A2的day)会由Excel自动将这样的date转换为3月1日、3月2日、3月3日,由此产生误差会出现0和负数。对于这样一个计算两个日期差的函数来说,出现负数好像有点不太合理。

例如,A2日期为2003年5月31日,B2日期为2005年3月1日,date(2005,2,31)=2005年3月3日,因此B2与此日期相减得到结果为-2。

基于第4点的问题,个人认为有以下两种算法可能会更合理一些:

I)当day(B2)

=IF(DAY(B2)-DAY(A2)>=0,DAY(B2)-DAY(A2),B2-TEXT(B2,"yyyy-m-1")+DATE(YEAR(A2),MONTH(A2)+1,1)-A2)

II)当day(B2)

=IF(DAY(B2)-DAY(A2)>=0,DAY(B2)-DAY(A2),MAX(B2-DATE(YEAR(B2),MONTH(B2)-1,DAY(A2)),0))

当然,这两种方法只是本人的建议,仅供参考。

综合以上算法解释,这个参数在不够减的时候借位是以B2为基准的,这个参数的算法可以表示为以下的公式:

=IF(DAY(B2)-DAY(A2)>=0,DAY(B2)-DAY(A2),B2-DATE(YEAR(B2),MONTH(B2)-1,DAY(A2))+164*(TEXT(DATE(YEAR(B2),MONTH(B2)+1,29),"m-d")="2-29"))

其中包含下划线的部分是对上面第三点中提到的闰年bug的模拟。如果要排除闰年的错误,则可以使用下面的公式:

=IF(DAY(B2)-DAY(A2)>=0,DAY(B2)-DAY(A2),B2-DATE(YEAR(B2),MONTH(B2)-1,DAY(A2)))

5,=Datedif(A2,B2,"YM")

此参数含义为返回时间段内的整月数,忽略日和年。

这里提到了“忽略”日,但实际与参数“M”一样,还是有关日期的相关计算。这个参数的算法实际上与参数“M”的算法一致,只是忽略其中年份差中所包含的月份数。

其算法可以表示为以下的公式,其中引用了Datedif函数的“M”参数方便公式编写:

=MOD(DATEDIF(A2,B2,"m"),12)

6,=Datedif(A2,B2,"YD")

此参数含义为返回时间段内的天数,忽略其中的年。

这个参数的算法比较复杂,情况比较多,简单地说包括以下几个重点:

1)当B2月份为3月份且B2的day大于等于A2的day时,两者相减是以A2的所在年份为基准的(如果够减,则以[A2的年份&B2的日期]与A2相减;如果不够减,则以[A2年份+1&B2的日期]与A2相减)

2)当B2月份为3月份且B2的day小于A2的day时,两者相减是以B2的所在年份为基准的(如果够减,则以B2与[B2的年份&A2的日期]相减;如果不够减,则以B2与[B2年份-1&A2的日期]相减)

3)当B2的月份不是3月份时,两者相减是以A2的所在年份为基准的,相减方式同第一条。

4)当B2的day小于A2的day,且B2日期是闰年的1月份日期,且B2与A2日期不直接够减时,存在着与“MD”参数类似的闰年bug,函数结果偏大164。这个bug在Excel2003的SP3中不存在,但在Excel 2010中依旧存在,且差值变为113。

综合以上算法解释,这个参数的算法可以表示为以下的公式(上面的文字不好理解,如果能看懂下面的公式则比较容易理解上述算法):

=IF(--(TEXT(B2,"!0!0-m-d"))>=--(TEXT(A2,"!0!0-m-d")),IF((DAY(B2)

其中包含下划线的部分为闰年bug的模拟,如果希望排除闰年的错误,可以将这部分内容去除。

以上分析了6个参数详细算法含义,由于无法得到详细的内部运算代码,因此以上分析结论全部来源于Datedif函数公式的黑箱测试。

欢迎有兴趣的朋友继续测试和分析。以下提供附件(注意使用相应版本的Excel打开附件):

附件1:Excel2007版(请用Excel 2007 SP2版本打开)

本地下载:Datedif函数测试2007版 (1414)

附件2:Excel2003版,2003版中不含闰年bug,其余算法与2007类似(请用Excel 2003 SP3版本打开)

php datedif,Datedif函数全面解析及BUG分析相关推荐

  1. 10. Android MultiMedia框架完全解析 - MediaExtractor::Create函数的解析和FslExtractor分析

    先来看看MediaExtractor所处的位置: (一)创建流程 在GenericSource.cpp的NuPlayer::GenericSource::initFromDataSource()函数中 ...

  2. 语言中拟合函数 计算aic_Go语言函数深度解析(中)

    上回函数深度解析给大家聊了一些函数的基本知识,不知道还有没有人记得,不记得赶紧回去复习! 他们是 go语言中函数的基本原理 单/多个同/不同类型参数 单/多个同/不同类型返回值 值传递,引用传递 函数 ...

  3. 18C 也不能避免 SQL 解析的 Bug

    作者简介 苏星开 云和恩墨南区交付技术顾问,曾服务过通信.能源生产.金融等行业客户,擅长 SQL 审核和优化,DataGuard 容灾等. 1 概述 在 Oracle 12.2 版本和新发布的18.0 ...

  4. c语言的point函数,C语言中friend友元函数详细解析

    C语言中friend友元函数详细解析 友元函数是可以直接访问类的私有成员的非成员函数.它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字frien ...

  5. php 立即执行函数,关于javascrip的立即执行函数的解析

    这篇文章主要介绍了关于javascrip的t立即执行函数的解析,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 概念: 立即执行函数顾名思义就是函数定义好之后立即执行. 函数表达式方式: ...

  6. C++函数重载解析细节

    Copyright(C)<C++从入门到精通-经典完整版> 函数重载解析细节 函数重载解析过程有三个步骤这些步骤可以总结如下: 1 确定为该调用而考虑的候选函数以及函数调用中的实参表属性 ...

  7. Python中sort和sorted函数代码解析

    Python中sort和sorted函数代码解析 本文研究的主要是Python中sort和sorted函数的相关内容,具体如下. 一.sort函数 sort函数是序列的内部函数 函数原型: L.sor ...

  8. Linux进程调用execve,linux内核系统调用函数do_execve()解析实例源码

    linux内核系统调用函数do_execve()解析,彻底解析内核调用用户空间代码入口函数do_execve() sys_execve() –> do_execve() /usr/src/lin ...

  9. Python文本变量与函数的解析执行,增强自动化测试数据驱动

    关注我,每天分享软件测试技术干货.面试经验,想要领取测试资料.进入软件测试学习交流群的可以直接私信我哦~~ 我们在使用Python进行自动化测试或者测试脚本开发时,通常会在代码中融入数据驱动设计,以便 ...

  10. main主函数参数解析

    默认的main函数参数 int main(int argc, char *argv[]) {// 主函数的代码逻辑return 0; } 其中,int 是主函数的返回值类型,主函数执行完后会返回一个整 ...

最新文章

  1. HtmlString类创建HTML Hepler 扩展MVC TextBox组件
  2. 计组—双端口与多模块存储器
  3. LeetCode-654. 最大二叉树
  4. RHEL7/CentOS7在线和离线安装GitLab配置使用实践
  5. 第三章 Docker 入门
  6. aix7.1安装12c执行root.sh无法启动ohasd服务案例
  7. List of Algorithms
  8. hp服务器系统时间一直变慢,怎么解决hp1010 win7打印机打印速度变慢的方法
  9. 回归分析——简单线性回归实例讲解(SPSS)
  10. linux deepin 命令行,深度Deepin操作系统中常用命令、系统命令、通用命令
  11. Sentinel-哨兵机制
  12. 解决mysql存储特殊文字(表情符号)utf8mb4
  13. c语言中反比例函数定义,初三数学反比例函数的定义知识点
  14. 金融机构业务连续性管理
  15. mysql查询总成绩高于240_Egret应用开发实践(02) MVC 模块化 - SegmentFault 思否
  16. 设计美好的服务器(6)--SEDA架构笔记
  17. “燕云十六将”之毛毛杜倩(7)
  18. AltiumDesigner 19软件安装步骤
  19. 在不解压缩的情况下修改压缩包内的文件
  20. 华为CodeCraft2018 周进展

热门文章

  1. vue 引入字体文件
  2. brew 特别慢 解决方案
  3. JAVA接口签名(Signature)实现方案
  4. android cts测试超时设置,Android的CTS测试
  5. Camrea测试-- CTS测试
  6. a-btest 数据挖掘_挖掘新的垂直鼠标-帮助我的腕管
  7. 成都Uber优步司机奖励政策(2月25日)
  8. 交换机、路由器和防火墙的原理和区别
  9. Dubbo的服务暴露过程
  10. 华为、华三交换机查看光模块收发光及光模块信息