DATEDIF:帮助里查不到但很好用
一个在函数列表里查无此名的函数
如果你在 Excel 的公式选项卡里点开“日期和时间”那一组,从头翻到尾也找不到 DATEDIF。在函数向导的搜索框里输入它,弹出的帮助内容多半是空的,有些版本甚至会提示该函数不可用。可只要你老老实实在单元格里敲下 =DATEDIF(A2,B2,"Y"),回车,它会给出一个完全正确的结果。这种“能用但查不到”的诡异状态,让 DATEDIF 成了 Excel 圈子里流传最广的都市传说之一,也让很多人在第一次听说它时半信半疑。
事情的起因是兼容性。DATEDIF 最早来自 Lotus 1-2-3,微软当年为了让人把表格从 Lotus 迁移到 Excel 时不至于算错日期,就把它一并塞进了函数库,却始终没有为它编写正式的帮助文档,也没有把它挂到函数列表里。二十多年过去,Lotus 早就没人用了,DATEDIF 却被留了下来,一直沿用到今天。它不需要任何新版本支持,Excel 2007、2010、2016、2019、2021 以及 Microsoft 365 里都能正常运算,可以说是本书里兼容性最好的函数之一,几乎不存在“同事打不开”的问题。
它解决的是一个非常具体的痛点:算出两个日期之间“整”的年数、月数、天数。你可能会说,两个日期相减不就是天数吗,为什么还要专门的函数?问题恰恰出在“整”这个字上。一个人 2019 年 12 月 31 日入职,到 2024 年 1 月 1 日,按天算是 1462 天,但他实际只满了 4 年零 1 天,说“工龄 4 年”才是对的,说他干了 4.003 年毫无意义。要把这种“满几年、余几个月、再余几天”的结果算出来,如果自己用 YEAR、MONTH、DAY 去拼,公式会长到让人怀疑人生,还得手动处理月份借位和闰年。DATEDIF 把这套借位逻辑封装好,一个参数切换单位,这就是它为数不多却难以被完全替代的价值。
顺带说一句,正因为没有官方文档,网上流传的 DATEDIF 教程质量参差不齐,甚至有一些把单位代码写错的示例。本文给出的六个单位和算法都在 Excel 2016 与 Microsoft 365 上实测过,可以放心抄。如果你发现某个示例在自己的电脑上结果不对,先检查日期是不是真日期,再检查版本号,八成问题出在这两处。
六个单位参数,一张表看懂

DATEDIF 的语法只有三个参数,非常朴素:=DATEDIF(开始日期,结束日期,单位)。前两个是日期,可以写成单元格引用,也可以写成 DATE(2024,11,8) 这样的嵌套结果;第三个是一个用英文引号包起来的单位代码。真正需要背下来的就是这六个代码,它们大小写不敏感,写成小写同样能识别。
| 单位代码 | 含义 | 举例(2021-03-15 到 2024-11-08) | 结果 |
|---|---|---|---|
| Y | 两个日期之间完整的整年数 | 满 3 年,第 4 年还没走完 | 3 |
| M | 两个日期之间完整的整月数 | 3 年 7 个月余 24 天 | 43 |
| D | 两个日期相差的总天数 | 直接相减也能得到 | 1334 |
| YM | 忽略年份和天数后剩余的月数 | 满 3 年之后还剩 7 个月 | 7 |
| YD | 忽略年份后剩余的天数 | 相当于搬到同一年再算天数差 | 238 |
| MD | 忽略年份和月份后剩余的天数 | 同月内 8 减 15 的借位结果 | 24 |
这张表里最常用的是 Y、YM、MD 这三个,它们组合起来刚好把一段时长拆成“几年几个月零几天”,人事、法务、财务三类表格里九成的需求都能覆盖。单位参数为 M 时算的是总月数,做租期、分期数、折旧月数时特别省事;参数为 D 时和 =结束日期-开始日期 完全等价,属于能用但没必要。YD 用得最少,它相当于把两个日期都搬到同一年里再算天数差,只有做生日倒计时或者年度周期横向对比时才派上用场。
需要提醒的是,单位参数必须加英文引号。写成 =DATEDIF(A2,B2,Y) 会被 Excel 当成名称引用,直接返回 #NAME?。这是初学者踩得最多的第一个坑,看到报错先检查有没有漏引号,基本能解决一半的问题。另外两个日期参数不能用区域引用去接多个单元格,DATEDIF 天生是单值函数,想批量算就得靠溢出或者下拉填充。
三个真实场景:工龄、账期、倒计时

第一个场景是算工龄和司龄。假设 A 列是入职日期,B 列是离职日期或者当天日期,希望结果直接显示成“4年7个月24天”这种人能读的形式,公式可以这样写:
=DATEDIF(A2,B2,"Y")&"年"&DATEDIF(A2,B2,"YM")&"个月"&DATEDIF(A2,B2,"MD")&"天"
如果只要年数用于计算年假天数,那就简化成 =DATEDIF(A2,TODAY(),"Y"),外面再套一层判断把不满一年的挡掉,比如年假规则是满 1 年给 5 天、每多 2 年加 1 天、上限 15 天,用 =MIN(15,5+INT(DATEDIF(A2,TODAY(),"Y")/2)) 就能一次算完。这里的 TODAY() 每次打开工作簿都会重算,属于易失性写法,关于它的取舍可以回头看易失函数与性能陷阱。
第二个场景是账期和逾期天数。财务同事最关心的是“这笔应收账款逾期了多少天”,用 =DATEDIF(到期日,TODAY(),"D") 就能算出正数天数,配合 IF 判断还能区分“还剩几天到期”和“已经逾期几天”,比如 =IF(到期日>=TODAY(),"未到期",DATEDIF(到期日,TODAY(),"D")&"天")。比直接用两个日期相减再改单元格格式的好处是,结果是纯数字,后续可以直接参与求和与条件统计,不用再清洗一遍格式。
第三个场景是项目里程碑倒计时。把结束日期固定在某个单元格里,用 =DATEDIF(TODAY(),结束日期,"D") 得到剩余天数,再套一层条件格式让小于 7 天的单元格整行变红。整个看板不需要任何辅助列,一行公式就能撑起来,交付日期一改,所有倒计时自动跟着变。
把上面三块串起来就是一套完整的表格。假设有一张 500 人的花名册,A 列是工号,B 列是姓名,C 列是入职日期,现在要在 D、E、F 三列分别给出司龄年数、精确到月的司龄描述、以及年假天数,可以完全不用辅助列,也不用手工核对任何一个格子。
D2 写 =DATEDIF(C2,TODAY(),"Y"),E2 写 =DATEDIF(C2,TODAY(),"Y")&"年"&DATEDIF(C2,TODAY(),"YM")&"个月",F2 写 =MIN(15,5+INT(D2/2)),三列一起往下填到第 501 行。年假公式里直接引用 D2 而不是再算一遍 DATEDIF,公式短了一截,重算也快,别人接手时也能一眼看懂逻辑。
如果还要按部门统计“司龄三年以上的人数”,就在汇总区写 =SUMPRODUCT((部门列="技术部")*(D2:D501>=3)),前提是 D 列已经是数字。千万不要在 SUMPRODUCT 里直接塞 DATEDIF 去接整列,那样每统计一次就要重算 500 次日期差,表格稍微大一点就会明显卡顿。先落一列数字,再对数字做统计,是这类表最省事也最稳的做法。
最后给 D 列套一个条件格式,大于等于 10 的填充深色,小于 1 的填充浅色,一张能直接给老板看的司龄表就完成了。整套流程里没有一次手动输入,明年打开文件时所有数字自动更新,维护成本几乎为零。
组合写法:把 DATEDIF 用出花样
DATEDIF 本身只能处理两个日期,但一旦和其他函数组合,覆盖面会突然变大。最典型的是和数组思路配合,对一整列日期批量算年龄。如果你用的是 Microsoft 365 或 Excel 2021,可以直接写 =DATEDIF(A2:A500,TODAY(),"Y"),一条公式溢出出 499 个结果,不用往下拖。这种写法背后的机制在数组溢出:一个公式填满一片格子里有完整说明。
第二种组合是和条件统计嵌套。比如要统计“工龄满 5 年但不满 10 年的人数”,可以把 DATEDIF 的结果丢进 SUMPRODUCT 里做双条件计数:=SUMPRODUCT((DATEDIF(A2:A500,TODAY(),"Y")>=5)*(DATEDIF(A2:A500,TODAY(),"Y")<10))。不过在部分老版本里 DATEDIF 不支持直接接收区域数组,遇到返回 #VALUE! 的情况就多插一列辅助列先算年数,再对辅助列做统计,稳当比炫技重要。多条件统计的更多写法见SUMPRODUCT:多条件计算的万金油。
第三种组合是处理“不足整月按整月算”的商务规则。很多合同规定租期不足整月按整月计,这时可以用 =DATEDIF(开始日期,结束日期,"M")+IF(DATEDIF(开始日期,结束日期,"MD")>0,1,0),先取整月数,再看有没有零头,有就加一。类似的变体还有“超过 15 天算一个月”,把判断里的 0 换成 15 即可。这种写法在房租摊销、设备租赁、保修期计算里出现频率极高。
第四种组合是嵌套进文本拼接做合同期摘要。把起租日、到期日、租期三段拼成一句话:="租期自"&TEXT(A2,"yyyy年m月d日")&"起,共"&DATEDIF(A2,B2,"M")&"个月",法务拿到手可以直接粘进合同正文,不用再来回核对。
再说说它和几个邻居函数的分工。日期类函数不少,容易混用,这里给出一条简单的分工原则:要“往后推一段时间”用 EDATE 或 EOMONTH,要“算两个日期之间有多长”用 DATEDIF 或 DAYS。
EDATE 的问题在于它只管加减月份,返回的是一个新的日期,不告诉你间隔有多长。比如合同签 12 个月,用 =EDATE(起租日,12) 得到到期日,这是它的主场;反过来,如果已知起租日和到期日要算实际租了几个月,那就该用 =DATEDIF(起租日,到期日,"M")。两者常常成对出现:先用 EDATE 算出到期日,再用 DATEDIF 回头校验 EDATE 有没有因为月末规则算错。
EOMONTH 负责月末对齐,像 1 月 31 日加一个月该是 2 月 28 日还是 3 月 1 日这种争议,用它就能定死规则。财务做账时经常要求“起租日统一取当月最后一天”,写法是 =EOMONTH(起租日,0),之后再交给 DATEDIF 算月数,结果才不会因为大小月差一天。
DAYS 是 Excel 2013 之后才有的函数,作用等同于 =结束日期-开始日期,只算天数,参数顺序注意是结束在前、开始在后,和 DATEDIF 恰好相反。很多人在这两个函数之间来回切换时把顺序搞反,算出来是负数还浑然不觉。记住一条就够:DAYS 的英文语义是“距离某天有多少天”,所以终点放前面;DATEDIF 的语义是“从某天开始过了多久”,所以起点放前面。
最后是 NETWORKDAYS,它算的是去掉周末和节假日之后的工作日天数,和 DATEDIF 的 Y、M、YM、MD 完全不是一回事。做考勤、排期、交付工时估算时应该选它,做年龄、工龄、账期时选 DATEDIF,别混着用。
翻车提醒:这几个坑每年都有人踩
坑一,开始日期晚于结束日期。DATEDIF 对参数顺序极其敏感,只要开始日期大于结束日期,不管用哪个单位都直接返回 #NUM!。做倒计时时如果把 TODAY() 放在第一个参数位置,等日期一过就会整列报错,稳妥的做法是外面套一层 =IF(结束日期<TODAY(),0,DATEDIF(TODAY(),结束日期,"D"))。
坑二,MD 参数的历史 bug。在部分版本里,当结束日期的日小于开始日期的日时,MD 会返回负数甚至一个莫名其妙的大数。这个 bug 微软一直没有正式修,因为它本来就是个“不存在的函数”。规避办法是别单独依赖 MD,改用日期反推:先用 =DATE(YEAR(开始日期),MONTH(开始日期)+DATEDIF(开始日期,结束日期,"M"),DAY(开始日期)) 算出满月后的对齐日期,再用结束日期减去它得到零头天数。虽然绕了一步,但结果一定正确。
坑三,日期其实是文本。从 ERP 系统或者网页复制出来的日期经常是文本格式,长得像日期但本质是字符串,DATEDIF 遇到它会返回 #VALUE!。先用 =ISNUMBER(A2) 验一下,不通过就用 DATEVALUE 或者数据选项卡里的分列功能转成真日期。判断标准很简单:把单元格格式改成常规,真日期会变成一串五位数序列号,文本则原样不动。
坑四,日期里带了时间。Excel 的日期本质是带小数的序列号,如果 A2 是 2024-11-08 18:00,B2 是 2024-11-08 09:00,看起来是同一天,实际前者更大,DATEDIF 就会报错或者少算一天。用 =INT(A2) 把时间部分抹掉再算,或者在录入时就保证日期列不带时间。
坑五,1900 年之前的日期。Excel 的日期系统从 1900-01-01 开始,更早的日期要么存成文本要么存成序列号但无法参与日期运算,DATEDIF 一律报错。处理历史档案数据时只能手动拆分年月日自己算。
常见问题
为什么我输入 DATEDIF 时 Excel 不提示参数
因为它没有正式的函数提示信息和帮助文档,属于未被记录的遗留函数。输入时不会像 SUM 那样弹出参数气泡,写完也不会有屏幕提示,甚至连自动补全都不会出现。解决办法只有靠记忆或者查表:三个参数依次是开始日期、结束日期、单位代码,单位必须用英文引号包起来。建议把六个单位抄在便签里贴在显示器边,用上两三次就自然记住了。另外要注意,微软曾经在 Excel 2016 之后尝试为它补充提示信息,但不同渠道版本表现不一致,别指望提示一定会出现。
不用 DATEDIF 还能算出整年数吗
可以。最常见的替代是 =YEAR(结束)-YEAR(开始)-(DATE(YEAR(结束),MONTH(开始),DAY(开始))>结束),括号里的比较返回 TRUE 或 FALSE,参与运算时被当成 1 或 0,相当于在生日还没到时减掉一年。另一个思路是 =INT(YEARFRAC(开始,结束,1)),第三个参数 1 表示按实际天数除以实际年份长度,比 DATEDIF 更精确,但在跨闰年时结果偶尔会差一天。两个办法都不如 DATEDIF 直观,所以能用 DATEDIF 时优先用它,除非你要规避 MD 的 bug 或者需要把公式交给使用 WPS 的同事复核。
想让结果直接显示成“3年7个月”该怎么写
用文本连接符把三段拼起来即可:=DATEDIF(A2,B2,"Y")&"年"&DATEDIF(A2,B2,"YM")&"个月"。如果想在结果为 0 时省略某一段,比如不满一年只显示月份,就在每段前面套 IF:=IF(DATEDIF(A2,B2,"Y")=0,"",DATEDIF(A2,B2,"Y")&"年")&DATEDIF(A2,B2,"YM")&"个月"。公式会明显变长,重复调用 DATEDIF 也拖慢重算,这时候就该考虑用 LET 把中间值提出来,写成先定义年数、月数两个名字,最后再拼接的形式。那条函数专门解决长公式的可读性问题,本书后面有单独一篇讲它。
表格里大量使用 DATEDIF 会不会拖慢文件
会,但影响有限。DATEDIF 本身计算量很小,真正的负担来自两点:一是把 TODAY() 写进成千上万个单元格,二是把 DATEDIF 套在 SUMPRODUCT 或数组公式里对整列重复计算。前者让每次打开文件都要重算一遍全表,后者让一次统计里调用几百次日期差。优化办法是把当前日期单独放在一个单元格里,比如 Z1 写 =TODAY(),其余公式都引用 Z1,重算范围立刻缩小;批量统计则先落一列数字再统计。五千行以内基本感觉不到差别,超过五万行就要提前规划。
能不能一次算出年月日三段并竖着排
可以。在 Microsoft 365 里可以利用数组常量把三个单位一次性传给 DATEDIF:=DATEDIF(A2,B2,{"Y";"YM";"MD"}),会溢出出三行结果,分别对应年、月、日。如果还想再拼上单位文字,就在后面用 &{"年";"个月";"天"} 连接。这条公式很适合放进个人档案卡或者合同期摘要,可惜在 Excel 2019 及更早版本里无法溢出,需要逐格写或者用 TEXTJOIN 拼成一串文本。关于版本之间的差异与降级方案,可以参考版本对照:新函数在老 Excel 里怎么办。
