早就萌生了寫博客的想法,一直到現在才動手,原因有多方面,歸根結底就是一個字~懶。 今天無意看到一片博文,覺得裡面說得幾點原因很對,原文地址:我們為什麼應該堅持寫博客,感謝作者,讓我有動力寫了這篇博文。其實寫博文是想記錄自己遇到的一些問題的解決思路,方便以後查閱,同時希望可以跟大家一起交流提高。 先介 ...
早就萌生了寫博客的想法,一直到現在才動手,原因有多方面,歸根結底就是一個字~懶。
今天無意看到一片博文,覺得裡面說得幾點原因很對,原文地址:我們為什麼應該堅持寫博客,感謝作者,讓我有動力寫了這篇博文。其實寫博文是想記錄自己遇到的一些問題的解決思路,方便以後查閱,同時希望可以跟大家一起交流提高。
先介紹下本人的基本情況,本人今年剛畢業,坐標上海,.NET 菜鳥一枚,第一次寫博客,有意見歡迎大家提出,大神輕噴!
好了,廢話不多說,開門見山。
一、開發背景:
最近在公司開發的系統中,需要計算工作日,就是給出一個採購周期(n天),我需要計算出在n個工作日之後的日期。開始準備去調介面(ps:找了半天發現沒有太合適的,還有吐槽下國家政府單位都沒有官方介面的),但是負責這個項目的大佬說,萬一別個的介面崩了,會影響我們自己的系統的正常運行,自己開發還是穩點,我就寫了這個功能,特此記錄下實現這個功能的思路。
二、定義:
工作日想必大家都知道,就是除去周末和每年國務院頒佈的節假日放假安排(例如:2017年部分節假日安排),其他就都是工作日(對了,差點忘記補班,這也算是工作日哦)。
三、實踐:
“廢話”說的夠多了,下麵擼起袖子開乾吧,代碼都寫了註釋。
提供了兩個公共方法,先給大家看下簡單測試的運行結果:
(1).根據傳入的工作日天數,獲得計算後的日期
(2).根據傳入的時間,計算工作日天數;
具體代碼:
1 public class HolidayHelper 2 { 3 #region 欄位屬性 4 private static object _syncObj = new object(); 5 private static HolidayHelper _instance { get; set; } 6 private static List<DateModel> cacheDateList { get; set; } 7 private HolidayHelper() { } 8 /// <summary> 9 /// 獲得單例對象,使用懶漢式(雙重鎖定) 10 /// </summary> 11 /// <returns></returns> 12 public static HolidayHelper GetInstance() 13 { 14 if (_instance == null) 15 { 16 lock (_syncObj) 17 { 18 if (_instance == null) 19 { 20 _instance = new HolidayHelper(); 21 } 22 } 23 } 24 return _instance; 25 } 26 #endregion 27 28 #region 私有方法 29 /// <summary> 30 /// 讀取文件 31 /// </summary> 32 /// <param name="filePath"></param> 33 /// <returns></returns> 34 private string GetFileContent(string filePath) 35 { 36 string result = ""; 37 if (File.Exists(filePath)) 38 { 39 result = File.ReadAllText(filePath); 40 } 41 return result; 42 } 43 /// <summary> 44 /// 獲取配置的Json文件 45 /// </summary> 46 /// <returns>經過反序列化之後的對象集合</returns> 47 private List<DateModel> GetConfigList() 48 { 49 string path = string.Format("{0}/../../Config/holidayConfig.json", System.AppDomain.CurrentDomain.BaseDirectory); 50 string fileContent = GetFileContent(path); 51 if (!string.IsNullOrWhiteSpace(fileContent)) 52 { 53 cacheDateList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DateModel>>(fileContent); 54 } 55 return cacheDateList; 56 } 57 /// <summary> 58 /// 獲取指定年份的數據 59 /// </summary> 60 /// <param name="year"></param> 61 /// <returns></returns> 62 private DateModel GetConfigDataByYear(int year) 63 { 64 if (cacheDateList == null)//取配置數據 65 GetConfigList(); 66 DateModel result = cacheDateList.FirstOrDefault(m => m.Year == year); 67 return result; 68 } 69 /// <summary> 70 /// 判斷是否為工作日 71 /// </summary> 72 /// <param name="currDate">要判斷的時間</param> 73 /// <param name="thisYearData">當前的數據</param> 74 /// <returns></returns> 75 private bool IsWorkDay(DateTime currDate, DateModel thisYearData) 76 { 77 if (currDate.Year != thisYearData.Year)//跨年重新讀取數據 78 { 79 thisYearData = GetConfigDataByYear(currDate.Year); 80 } 81 if (thisYearData.Year > 0) 82 { 83 string date = currDate.ToString("MMdd"); 84 int week = (int)currDate.DayOfWeek; 85 86 if (thisYearData.Work.IndexOf(date) >= 0) 87 { 88 return true; 89 } 90 91 if (thisYearData.Holiday.IndexOf(date) >= 0) 92 { 93 return false; 94 } 95 96 if (week != 0 && week != 6) 97 { 98 return true; 99 } 100 } 101 return false; 102 } 103 104 #endregion 105 106 #region 公共方法 107 public void CleraCacheData() 108 { 109 if (cacheDateList != null) 110 { 111 cacheDateList.Clear(); 112 } 113 } 114 /// <summary> 115 /// 根據傳入的工作日天數,獲得計算後的日期,可傳負數 116 /// </summary> 117 /// <param name="day">天數</param> 118 /// <param name="isContainToday">當天是否算工作日(預設:true)</param> 119 /// <returns></returns> 120 public DateTime GetReckonDate(int day, bool isContainToday = true) 121 { 122 DateTime currDate = DateTime.Now; 123 int addDay = day >= 0 ? 1 : -1; 124 125 if (isContainToday) 126 currDate = currDate.AddDays(-addDay); 127 128 DateModel thisYearData = GetConfigDataByYear(currDate.Year); 129 if (thisYearData.Year > 0) 130 { 131 int sumDay = Math.Abs(day); 132 int workDayNum = 0; 133 while (workDayNum < sumDay) 134 { 135 currDate = currDate.AddDays(addDay); 136 if (IsWorkDay(currDate, thisYearData)) 137 workDayNum++; 138 } 139 } 140 return currDate; 141 } 142 /// <summary> 143 /// 根據傳入的時間,計算工作日天數 144 /// </summary> 145 /// <param name="date">帶計算的時間</param> 146 /// <param name="isContainToday">當天是否算工作日(預設:true)</param> 147 /// <returns></returns> 148 public int GetWorkDayNum(DateTime date, bool isContainToday = true) 149 { 150 var currDate = DateTime.Now; 151 152 int workDayNum = 0; 153 int addDay = date.Date > currDate.Date ? 1 : -1; 154 155 if (isContainToday) 156 { 157 currDate = currDate.AddDays(-addDay); 158 } 159 160 DateModel thisYearData = GetConfigDataByYear(currDate.Year); 161 if (thisYearData.Year > 0) 162 { 163 bool isEnd = false; 164 do 165 { 166 currDate = currDate.AddDays(addDay); 167 if (IsWorkDay(currDate, thisYearData)) 168 workDayNum += addDay; 169 isEnd = addDay > 0 ? (date.Date > currDate.Date) : (date.Date < currDate.Date); 170 } while (isEnd); 171 } 172 return workDayNum; 173 } 174 #endregion 175 } 176 177 public struct DateModel 178 { 179 public int Year { get; set; } 180 181 public List<string> Work { get; set; } 182 183 public List<string> Holiday { get; set; } 184 }View Code
說明下,法定節假日我是自己用json來配置的,大家可以自己維護,或者做成自己的介面。下麵展示下json的格式,這是我自己配置的(2015-2017年),大家可以按照自己的需求來修改。
1 [ 2 { 3 "Year": "2015", 4 "Work": [ "0104", "0215", "0228", "0906", "1010" ], 5 "Holiday": [ "0101", "0102", "0103", "0218", "0219", "0220", "0221", "0222", "0223", "0224", "0404", "0405", "0406", "0501", "0502", "0503", "0620", "0621", "0622", "0903", "0904", "0905", "0927", "1001", "1002", "1003", "1004", "1005", "1006", "1007" ] 6 }, 7 { 8 "Year": "2016", 9 "Work": [ "0206", "0214", "0612", "0918", "1008", "1009" ], 10 "Holiday": [ "0101", "0207", "0208", "0209", "0210", "0211", "0212", "0213", "0404", "0501", "0502", "0609", "0610", "0611", "0915", "0916", "0917", "1001", "1002", "1003", "1004", "1005", "1006", "1007" ] 11 }, 12 { 13 "Year": "2017", 14 "Work": [ "0122", "0204", "0401", "0527", "0930" ], 15 "Holiday": [ "0101", "0102", "0127", "0128", "0129", "0130", "0201", "0202", "0501", "0529", "0530", "1001", "1002", "1003", "1004", "1005", "1006" ] 16 } 17 ]holidayConfig.json
好了,就說這麼多,由於能力有限,有寫得不好的地方,歡迎指正、補充。如果對您有幫助,請幫忙點個贊,謝謝!