前段時間,項目中有個需要計算員工入職時間的功能,規則是這樣的,入職當天開始算一天,顯示效果是大於一年的算一年,不足一年的顯示多少天,比如是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 年