计算入职时间的时间算法
前段时间,项目中有个需要计算员工入职时间的功能,规则是这样的,入职当天开始算一天,显示效果是大于一年的算一年,不足一年的显示多少天,比如是1年300天。这个需求看上去吧,还是很简单的,原本以为10多分种就可以搞定,其实吧确实不复杂,但是涉及时间的计算,还真不是10多分钟搞定的,前前后后试了三种计算方法,最后才搞定,这种不起眼的小功能说不准以后还能用上,故记录一下。
先说说这三种计算方法吧:
第一种、先计算从入职到当前共计多少天再除以365 得到多少年再 % 求余下的天数,算法本身没有什么问题,但是没有考虑闰年的情况,不能满足功能需求。
第二种、同样先计算从入职到当前共计多少天,再用当天年份向前逐年前推,判断是否是闰年,如果是闰年共天数减366,如果是平年减365 ,最后判断剩余的天数满不满一年,如果不满足一年则停止不再向前推,剩下的就是天数部分。这个方法逻辑上没什么问题,但是在处理2月29前或29后,多一天,少一天上面没有搞清楚,最后感觉还是可能有问题,最后放弃。
第三种、这个方法分三部分来计算,首先计算入职当年共计多少天,再计算当前已过了多少年,之后再计算现在这一年又过了多少天,最后再用第一步计算的天数和第三步计算的天数相加,得到天数再判断是否满足一年,满足一年,计算的年数加1,剩余的是天数。
第三种方法,逻辑上是通的,需要特殊处理的也只是最后一步,所以选择了第三种方法,现将第三种计算方法代码粘出来,如果哪位博友发现什么问题,希望可以指正出来。
1 /// 第一段 计算入职当年剩余几天(包含当天) 2 /// 第二段 计算入职当年到今年多少年 3 /// 第三段 计算今天是今年第几天 4 /// 分成三段计算 最后合并 第一段和第三段的天数,再判断是否大于一年,如果大于一年则整数年加1 再算之后剩余的天数 5 /// <param name="entryDate"></param> 6 /// <param name="currentDate"></param> 7 /// <param name="years"></param> 8 /// <param name="days"></param> 9 /// <returns></returns> 10 public string GetEntryDays3(DateTime entryDate, DateTime currentDate, out int years, out int days) 11 { 12 days = 0; 13 years = 0; 14 15 string description = ""; 16 17 //第一段天数 18 int days1 = (int)new DateTime(entryDate.Year, 12, 31).Subtract(entryDate).TotalDays + 1; 19 20 //第二段年数 21 int years1 = currentDate.Year - (entryDate.Year + 1); 22 23 //第三段天数 24 int days2 = (int)currentDate.Subtract(new DateTime(currentDate.Year, 1, 1)).TotalDays; 25 26 int days3 = (days1 + days2); 27 28 //入职闰年 闰年 现在闰年 29 if (IsLeap(entryDate.Year) 30 && IsLeap(currentDate.Year)) 31 { 32 if (days3 >= 365) 33 { 34 years1 = years1 + 1; 35 days3 = days3 - 365; 36 } 37 } 38 39 //入职闰年 现在平年 40 if(IsLeap(entryDate.Year) 41 &&!IsLeap(currentDate.Year)) 42 { 43 if(entryDate >= new DateTime(entryDate.Year, 3, 1)) 44 { 45 days3 = days3 + 1; 46 } 47 48 if (days3 >= 365) 49 { 50 years1 = years1 + 1; 51 days3 = days3 - 365; 52 } 53 } 54 55 //入职平年 现在闰年 56 if(!IsLeap(entryDate.Year) 57 && IsLeap(currentDate.Year)) 58 { 59 if(currentDate <= new DateTime(currentDate.Year, 2, 29)) 60 { 61 days3 = days3 + 1; 62 } 63 64 if (days3 >= 365) 65 { 66 years1 = years1 + 1; 67 days3 = days3 - 365; 68 } 69 } 70 71 //入职平年,现在平年 72 if(!IsLeap(entryDate.Year)&& 73 !IsLeap(currentDate.Year)) 74 { 75 days3 = days3 + 1; 76 if (days3 >= 365) 77 { 78 years1 = years1 + 1; 79 days3 = days3 - 365; 80 } 81 } 82 83 if (days3 == 365) 84 { 85 years1 = years1 + 1; 86 days3 = days3 - 365; 87 } 88 if (days3 == 366) 89 { 90 years1 = years1 + 1; 91 days3 = days3 - 366; 92 } 93 94 years = years1; 95 days = days3; 96 97 if (years > 0) 98 { 99 description += years + " 年"; 100 } 101 102 if (days > 0) 103 { 104 description += days + " 天"; 105 } 106 107 return description; 108 }
计算效果如下:(也为了把规则描述得更清晰)
入职: 2000-2-29 现在:2020-2-29 结果:20 年1 天
入职: 2015-3-1 现在:2018-3-1 结果:3 年1 天
入职: 2017-1-2 现在:2019-1-3 结果:2 年2 天
入职: 2016-2-29 现在:2020-2-28 结果:4 年