程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#編程實踐–幫老婆計算產假方案

C#編程實踐–幫老婆計算產假方案

編輯:C#入門知識

C#編程實踐–幫老婆計算產假方案


今天中午午休時,和老婆聊天,老婆還過幾天就要請產假了,她在網上問我讓我幫她數一下該怎麼請假最劃算,老婆是個會過日子的人,面對此種要求我當然義不容辭,不過想到這個問題我的第一反應是:這個怎麼可以用數的呢?於是,我開始去了解2014年上海市最新的產假政策規定,大致概況如下:“產假加上晚育假一共128天,其中前面98天是正常產假,其中已經包括國家法定節日和雙休日,後面30天是晚育假,只包含雙休日,不包含國家法定節日,也就是說遇到國家法定節日則假期往後順延”,注意黑體粗字描述,可以知道這裡面的精打細算就體現在前面98天的正常產假。我們要做的就是盡量避免正常產假包含太多的國家法定節假日,否則用老婆的話說那就是“虧”了,注意我把“虧”字打引號,我的意思是在生活中我們不必太過於精打細算斤斤計較,如果過度了那麼就容易失去生活情趣和心靈的自由,有句話說吃虧是福。但是,在不妨礙這種前提條件下,我們還是要努力爭取,扯遠了,這個問題又不復雜,所以,我何樂而不為呢?況且,最近已經准備開始寫博了,經常看書看文章看博客,畢竟,紙上得來終覺淺,絕知此事要躬行,還是要經常實踐實踐,況且作為干這一行的,更要有開放和分享的心態,好了,廢話已經很多了,開始代碼的構思和實現。   領域   初步定位,這是一個關於時間查詢的應用,模型圍繞時間建立,假期根據月份和日號來表示(公歷和農歷),另需要提供假期規則的定義,如下(DateModels.cs):   復制代碼 using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks;   namespace HelloBaby {     // 這裡提供默認的放假集合定義     public static class DefaultHoliday     {         // 元旦1天假         public static readonly Holiday NewYearsHoliday             = new Holiday(MonthDayDate.NewYearsDay, 1);         // 春節3天假,從前一天(除夕)開始放         public static readonly Holiday SpringFestivalHoliday             = new Holiday(MonthDayDate.SpringFestival, -1, 3);         // 清明1天假         public static readonly Holiday QingMingHoliday             = new Holiday(MonthDayDate.QingMingDay, 1);         // 勞動節1天假         public static readonly Holiday LabourHoliday             = new Holiday(MonthDayDate.LabourDay, 1);         // 端午節1天假         public static readonly Holiday DragonBoatHoliday             = new Holiday(MonthDayDate.DragonBoatFestival, 1);         // 中秋節1天假         public static readonly Holiday MidAutumnHoliday             = new Holiday(MonthDayDate.MidAutumnDay, 1);         // 國慶節3天假         public static readonly Holiday NationalHoliday             = new Holiday(MonthDayDate.NationalDay, 3);           public static List<Holiday> Holidays = new List<Holiday>{             DefaultHoliday.NewYearsHoliday,             DefaultHoliday.SpringFestivalHoliday,             DefaultHoliday.QingMingHoliday,             DefaultHoliday.LabourHoliday,             DefaultHoliday.DragonBoatHoliday,             DefaultHoliday.MidAutumnHoliday,             DefaultHoliday.NationalHoliday         };     }       // 假期,包含3個成員(農歷或公歷幾月幾日?提前幾天放?共放幾天)     public struct Holiday     {         public Holiday(MonthDayDate monthDay, int startOffset, int days)             : this()         {             MonthDay = monthDay;             StartOffset = startOffset;             Days = days;         }           public Holiday(MonthDayDate monthDay, int days)             : this(monthDay, 0, days)         {         }           public MonthDayDate MonthDay { get; private set; }         public int StartOffset { get; set; }         public int Days { get; set; }           // 根據年份獲取假期具體日期枚舉         public IEnumerable<DateTime> ToDateTimeRange(int year)         {             DateTime gregorian = DateTime.Now;               if (MonthDay.Calendar == CalendarKind.LunarCalendar)                 gregorian = DateUtility.ConvertLunarYearDate(             year, MonthDay.Month, MonthDay.Day);             else                 gregorian = new DateTime(year, MonthDay.Month, MonthDay.Day);               DateTime begin = gregorian.AddDays(StartOffset);             for (int i = 0; i < Days; i++)             {                 yield return begin.AddDays((double)i);             }         }     }       // 此處使用Calendar屬性來區分歷法     // 也可以將struct改為class使用繼承的設計方式,方便擴展     public struct MonthDayDate     {         // 元旦節         public static readonly MonthDayDate NewYearsDay = new MonthDayDate(1, 1);         // 中國春節         public static readonly MonthDayDate SpringFestival =             new MonthDayDate(1, 1, CalendarKind.LunarCalendar);         // 清明節         public static readonly MonthDayDate QingMingDay = new MonthDayDate(4, 5);         // 五一勞動節         public static readonly MonthDayDate LabourDay = new MonthDayDate(5, 1);         // 端午節         public static readonly MonthDayDate DragonBoatFestival =             new MonthDayDate(5, 5, CalendarKind.LunarCalendar);         // 中秋節         public static readonly MonthDayDate MidAutumnDay =             new MonthDayDate(8, 15, CalendarKind.LunarCalendar);         // 國慶節         public static readonly MonthDayDate NationalDay =             new MonthDayDate(10, 1);           public MonthDayDate(int month, int day, CalendarKind calendar)             : this()         {             Month = month;             Day = day;             Calendar = calendar;         }           public MonthDayDate(int month, int day)             : this(month, day, CalendarKind.Gregorian)         {         }           public int Month { get; private set; }         public int Day { get; private set; }         public CalendarKind Calendar { get; private set; }           public static bool operator ==(MonthDayDate d1, MonthDayDate d2)         {             return d1.Month == d2.Month                 && d1.Day == d2.Day                 && d1.Calendar == d2.Calendar;         }           public static bool operator !=(MonthDayDate d1, MonthDayDate d2)         {             return !(d1 == d2);         }     }       public enum CalendarKind     {         // 公歷(陽歷)         Gregorian,         // 中國農歷(陰歷)         LunarCalendar     } } 復制代碼 注意,在Model裡面,我們添加了業務邏輯,比如Holiday的ToDateTimeRange方法裡面依賴了外部的農歷到公歷的轉換邏輯,這裡依賴了外部邏輯,是否屬於不良好的設計?於是我有必要聲明,此代碼為半實驗性代碼,非生產代碼。既然此處依賴一些外部方法邏輯,那麼我也把這部分代碼列出(DateUtility.cs):   復制代碼 using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks;   namespace HelloBaby {     public class DateUtility     {         /// <summary>         /// 獲取時間段枚舉         /// </summary>         public static IEnumerable<DateTime> RangeDay(       DateTime starting, DateTime ending)         {             for (DateTime d = starting; d <= ending; d = d.AddDays(1))             {                 yield return d;             }         }           /// <summary>         /// 農歷轉公歷         /// </summary>         public static DateTime ConvertLunarYearDate(int year, int month, int day)         {             ChineseLunisolarCalendar calendar = new ChineseLunisolarCalendar();               return calendar.ToDateTime(year, month, day, 0, 0, 0, 0);         }     } } 復制代碼 業務   程序寫到這裡已經完成了一大半了,接下來就是一些判斷的規則邏輯,這裡使用擴展方法來實現(DateExtensions.cs):   復制代碼 using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks;   namespace HelloBaby {     public static class DateExtensions     {         /// <summary>         /// 判斷日期是否是節假日,使用默認放假規定         /// </summary>         public static bool IsHoliday(this DateTime date)         {             return date.IsHoliday(DefaultHoliday.Holidays);         }           /// <summary>         /// 判斷日期是否是節假日,使用指定放假規定         /// </summary>         public static bool IsHoliday(       this DateTime date, IEnumerable<Holiday> holidays)         {             return holidays.Any(                 d => d.ToDateTimeRange(date.Year).Contains(date)                 );         }     }      } 復制代碼 提示:在項目的實踐中,我們盡量遵循TDD的開發模式,尤其是針對業務處理層的代碼,單元測試代碼這裡就不貼了,省略掉。   應用   好了,至此我們的領域和業務規則部分已經完成了,可以開始我們的應用了,在一個以數據為中心的年代,有了數據,我們就可以發揮想象,為所欲為,在這裡我還是簡單的回到最初的問題點上,因為雖然借此機會練練手寫寫代碼,但初衷還是要幫老婆解決問題啊,於是我的應用場景為計算98天產假裡面包含的國家法定節日,我在此主要使用LINQ查詢:   復制代碼 internal static void PrintSolutions(int days) {     var sample = DateUtility.RangeDay(         new DateTime(2014, 1, 1),         new DateTime(2015, 12, 31));       var holidayCollection = DefaultHoliday.Holidays;       var solutions =         from begin in sample         from end in sample         let range = DateUtility.RangeDay(begin, end)         where range.Count() == days         select new         {             Begin = begin,             End = end,             HolidayCount = range.Count(d => d.IsHoliday())         };       // 顯式查詢集合,避免多次查詢     // 空間換時間的典型場景啊!!!     var local = solutions.ToList();       var groups =         from all in local         group all by all.HolidayCount into g         select new          {              Holidays = g.Key,             SolutionCount = g.Count()         };       var best =         from all in local         where all.HolidayCount == 0         select all;       Console.WriteLine("group results:");     foreach (var group in groups)     {         Console.WriteLine("{0} solutions for {1} holidays",             group.SolutionCount, group.Holidays);     }       Console.WriteLine();     Console.WriteLine("best results:");     foreach (var one in best)     {         Console.WriteLine("from {0:yyyy-MM-dd} to {1:yyyy-MM-dd}",             one.Begin, one.End);     } } 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved