C # Programming Practice-help my wife calculate the maternity leave plan
During lunch break at noon today, I chatted with my wife. My wife has to take maternity leave in a few days. She asked me on the Internet to help her count how to ask for leave, which is the most cost-effective, my wife is a person who will live. Of course, it is incumbent on me to face this kind of requirement, but my first response to this question is: how can we use data? As a result, I began to learn about the latest maternity leave policy regulations in Shanghai in 2014. The general situation is as follows: "The total number of maternity leave and late childbearing leave is 128 days. The first 98 days are normal maternity leave, these include national statutory holidays and weekends, and the last 30 days are late childbearing holidays. They only include weekends and do not include national statutory holidays. That is to say, the holidays will be postponed in the event of national statutory holidays ", pay attention to the bold description, you can know that the above careful calculation is reflected in the previous 98 days of normal maternity leave. What we need to do is try to avoid regular maternity leave that contains too many national holidays. Otherwise, if we use our wife's words, it will be a "loss". Note that I will quote the word "loss, I mean, in our life, we don't have to worry too much about it. If we do not care too much about it, it is easy to lose the fun of life and the freedom of mind. However, without interfering with such conditions, we still have to work hard to get farther away. This problem is not complicated. So why should I be happy? Besides, I have been preparing to write blogs recently. I often read books, read articles, and read blogs. After all, I have to get a glimpse of the last word on the paper. I am sure I have to do this and I still need to practice it frequently, in addition, as a part of this line, we must have an open and sharing mentality. Well, there is already a lot of nonsense. We started to design and implement the Code. Preliminary positioning of the field. This is an application of Time query. The model is built around time, and the holiday is expressed by month and day number (Gregorian calendar and lunar calendar). In addition, you need to define holiday rules, as follows (DateModels. cs): copy the code using System; using System. collections. generic; using System. globalization; using System. linq; using System. text; using System. threading. tasks; namespace HelloBaby {// The default Holiday set is provided here. The definition of public static class DefaultHoliday {// public static readonly Holiday NewYearsHoliday = new Holiday (MonthDayDate. newYearsDay, 1 ); // Three days off during the Spring Festival. public static readonly Holiday will be available from the previous day (new Year's Eve) SpringFestivalHoliday = new Holiday (MonthDayDate. springFestival,-1, 3); // 1-day public static readonly Holiday QingMingHoliday = new Holiday (MonthDayDate. qingMingDay, 1); // one-day Holiday on Labor Day public static readonly Holiday LabourHoliday = new Holiday (MonthDayDate. labourDay, 1); // Dragon Boat Festival 1 day Holiday public static readonly Holiday DragonBoatHoliday = new Holiday (Mont HDayDate. dragonBoatFestival, 1); // one-day Mid-Autumn Festival Holiday public static readonly Holiday MidAutumnHoliday = new Holiday (MonthDayDate. midAutumnDay, 1); // public static readonly Holiday NationalHoliday = new Holiday (MonthDayDate. nationalDay, 3); public static List <Holiday> Holidays = new List <Holiday> {defaulthoocs. newYearsHoliday, DefaultHoliday. springFestivalHoliday, DefaultHoliday. qingMingHoliday, Def AultHoliday. LabourHoliday, DefaultHoliday. DragonBoatHoliday, DefaultHoliday. MidAutumnHoliday, DefaultHoliday. NationalHoliday};} // includes three members (lunar calendar or calendar day? A few days in advance? 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;} // obtain the holiday date by year. 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 );}} // The Calendar attribute is used to distinguish calendars. // you can also change struct to class and use the inherited design method, convenient extension of public struct MonthDayDate {// new Year's Day public static readonly MonthDayDate NewYearsDay = new MonthDayDate (1, 1); // China Spring Festival public static readonly MonthDayDate SpringFestival = new MonthDayDate (1, 1, calendarKind. lunarCalendar); // Tomb Sweeping Day public static readonly MonthDayDate QingMingDay = new MonthDayDate (4, 5); // May Day public static readonly Mo NthDayDate LabourDay = new MonthDayDate (5, 1); // Dragon Boat Festival public static readonly MonthDayDate DragonBoatFestival = new MonthDayDate (5, 5, CalendarKind. lunarCalendar); // Mid-Autumn Festival public static readonly MonthDayDate MidAutumnDay = new MonthDayDate (8, 15, CalendarKind. lunarCalendar); // National day public static readonly MonthDayDate NationalDay = new MonthDayDate (10, 1); public MonthDayDate (int month, int day, Cale NdarKind 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 ar {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 calendar (Gregorian calendar) Gregorian, // Chinese lunar calendar (lunar calendar) LunarCalendar} copy the code. Note: In the Model, we have added business logic. For example, the ToDateTimeRange method of Holiday is dependent on the Conversion logic from the external lunar calendar to the Gregorian calendar. Is it a poor design? So it is necessary for me to declare that this code is a semi-experimental code, not a production code. Since it depends on some external method logic, I also list this part of code (DateUtility. cs): copy the code 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> // obtain the time period enumeration // </summary> public static IEnumerable <DateTime> RangeDay (DateTime starting, dateTime ending) {for (DateTime d = starting; d <= ending; D = d. addDays (1) {yield return d ;}/// <summary> // convert the lunar calendar to the Gregorian calendar /// </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) ;}} the business program of copying the Code has completed more than half of it, the following describes some rule logic for judgment. Here we use the extension method (DateExtensions. cs): copy the code using System; using System. collections. ge Neric; using System. globalization; using System. linq; using System. text; using System. threading. tasks; namespace HelloBaby {public static class DateExtensions {// <summary> // determine whether the date is a holiday, use the default holiday rule /// </summary> public static bool IsHoliday (this DateTime date) {return date. isHoliday (defaulthoocs. holidays) ;}/// <summary> /// determines whether the date is a holiday. Use the specified holiday provision /// </summary> public static bool IsHoliday (this D AteTime date, IEnumerable <Holiday> holidays) {return holidays. any (d => d. toDateTimeRange (date. year ). contains (date) ;}} copy code tip: In project practice, we try to follow the TDD development mode, especially for the Business Processing Layer Code, the unit test code is not pasted here. The application has been completed. Now our fields and business rules have been completed. Now we can start our application. In a data-centric age, we have data, we can give full play to our imagination and do whatever we want. Here, I simply go back to the initial issue point, because although I took this opportunity to practice writing code by hand, I still wanted to help my wife solve the problem, so my application scenario is to calculate the national statutory holidays included in the 98-day maternity leave. I mainly use the LINQ query here: copy the code internal static void PrintSolutions (int days) {var sample = DateUtility. rangeDay (new DateTime (2014, 1, 1), new DateTime (2015, 12, 31); var holidayCollection = defaulthoocs. holidays; var solutions = from begin sample from end I N sample let range = DateUtility. rangeDay (begin, end) where range. count () = days select new {Begin = begin, End = end, HolidayCount = range. count (d => d. isHoliday ()}; // explicitly queries a set to avoid multiple queries. // typical scenarios of changing the space time !!! 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 );}}