C# Add days to a given date
我第一眼就要做一些简单的锻炼,但结果却很难做到。我需要一个日期作为输入,还需要给它添加一些天,这些天也是从用户输入中获取的。我已经做了一些函数和一些简单的计算,现在我有了从日期(01,010001是零)开始的所有天数,例如:
第一年1月第二年(01.01.0002)+0天等于365天。如果我在其中添加一些天,它也会正确计算:01.01.0002+12天=387。它也计算闰年。现在我有了totaldays,我只需要将其转换为正常的日/月/年格式。
我不允许使用日期时间
这是我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | private static int[] daysPerMonth = new int[12]; private static int days; private static int months; private static int years; private static int add; private static void Main() { Console.Write("Enter day :"); int.TryParse(Console.ReadLine(), out days); Console.Write("Enter Month :"); int.TryParse(Console.ReadLine(), out months); Console.Write("Enter Year :"); int.TryParse(Console.ReadLine(), out years); Console.Write("Enter days to add :"); int.TryParse(Console.ReadLine(), out add); int totalDays = GetTotalDays(new[] {days, months, years}); totalDays += add; TransformIntoDate(totalDays); Console.ReadKey(); } private static void TransformIntoDate(int inputDays) { } private static int GetTotalDays(IReadOnlyList<int> date) { int totalDays = 0; for (int i = date[2]; i > 1; i--) { if (IsLeap(i)) { daysPerMonth = new[] {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; totalDays += 366; } else { daysPerMonth = new[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; totalDays += 365; } } for (int i = 1; i <= date[1]; i++) { if (i == date[1]) { totalDays += date[0] - 1; } else { totalDays += daysPerMonth[i]; } } return totalDays; } private static bool IsLeap(int year) { if (year%400 == 0) return true; return (year%4 == 0) && (year%100 != 0); } |
有两种方法可以"保存"日期:分别保存年、月、日或保存总天数(或小时、分钟、秒或毫秒…)。从"0点"中选择测量单位)。例如.NET的
关于如何完成从年/月/日到内部编号的简单示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | public class MyDate { public int TotalDaysFrom00010101 { get; private set; } private const int DaysIn400YearCycle = 365 * 400 + 97; private const int DaysIn100YearCycleNotDivisibleBy400 = 365 * 100 + 24; private const int DaysIn4YearCycle = 365 * 4 + 1; private static readonly int[] DaysPerMonthNonLeap = new[] { 31, 31 + 28, 31 + 28 + 31, 31 + 28 + 31 + 30, 31 + 28 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 // Useless }; private static readonly int[] DaysPerMonthLeap = new[] { 31, 31 + 29, 31 + 29 + 31, 31 + 29 + 31 + 30, 31 + 29 + 31 + 30 + 31, 31 + 29 + 31 + 30 + 31 + 30, 31 + 29 + 31 + 30 + 31 + 30 + 31, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31 // Useless }; public static bool IsLeap(int year) { if (year % 400 == 0) return true; return (year % 4 == 0) && (year % 100 != 0); } public void SetDate(int year, int month, int day) { TotalDaysFrom00010101 = 0; { int year2 = year - 1; // Full 400 year cycles TotalDaysFrom00010101 += (year2 / 400) * DaysIn400YearCycle; year2 %= 400; // Remaining 100 year cycles (0...3) if (year2 >= 100) { year2 -= 100; TotalDaysFrom00010101 += DaysIn100YearCycleNotDivisibleBy400; if (year2 >= 100) { year2 -= 100; TotalDaysFrom00010101 += DaysIn100YearCycleNotDivisibleBy400; if (year2 >= 100) { year2 -= 100; TotalDaysFrom00010101 += DaysIn100YearCycleNotDivisibleBy400; } } } // Full 4 year cycles TotalDaysFrom00010101 += (year2 / 4) * DaysIn4YearCycle; year2 %= 4; // Remaining non-leap years TotalDaysFrom00010101 += year2 * 365; } // Days from the previous month if (month > 1) { // -2 is because -1 is for the 1 January == 0 index, plus -1 // because we must add only the previous full months here. // So if the date is 1 March 2016, we must add the days of // January + February, so month 3 becomes index 1. TotalDaysFrom00010101 += DaysPerMonthNonLeap[month - 2]; if (month > 2 && IsLeap(year)) { TotalDaysFrom00010101 += 1; } } // Days (note that the"instant 0" in this class is day 1, so // we must add day - 1) TotalDaysFrom00010101 += day - 1; } public void GetDate(out int year, out int month, out int day) { int days = TotalDaysFrom00010101; // year { year = days / DaysIn400YearCycle * 400; days %= DaysIn400YearCycle; if (days >= DaysIn100YearCycleNotDivisibleBy400) { year += 100; days -= DaysIn100YearCycleNotDivisibleBy400; if (days >= DaysIn100YearCycleNotDivisibleBy400) { year += 100; days -= DaysIn100YearCycleNotDivisibleBy400; if (days >= DaysIn100YearCycleNotDivisibleBy400) { year += 100; days -= DaysIn100YearCycleNotDivisibleBy400; } } } year += days / DaysIn4YearCycle * 4; days %= DaysIn4YearCycle; // Special case: 31 dec of a leap year if (days != 1460) { year += days / 365; days %= 365; } else { year += 3; days = 365; } year++; } // month { bool isLeap = IsLeap(year); int[] daysPerMonth = isLeap ? DaysPerMonthLeap : DaysPerMonthNonLeap; for (month = 0; month < daysPerMonth.Length; month++) { if (daysPerMonth[month] > days) { if (month > 0) { days -= daysPerMonth[month - 1]; } break; } } month++; } // day { day = days; day++; } } public void AddDays(int days) { TotalDaysFrom00010101 += days; } } |
这里的重点是,我们知道有400年的"周期",每一个"周期"都有1(2)天。减去这些"周期"后,有更小的100年的"周期",每个周期有
在添加了所有"完整前几年"的天数之后,我们可以添加"完整前几个月"的天数。在这里,我们必须考虑今年可能是闰年。
最后,我们添加选定的日期。
如何编写
现在。。。如何检查结果是否正确?我们可以编写一些基于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | var date = default(DateTime); var endDate = new DateTime(2017, 1, 1); while (date < endDate) { int year = date.Year; int month = date.Month; int day = date.Day; int totalDays = (int)(date - default(DateTime)).TotalDays; var md = new MyDate(); md.SetDate(year, month, day); if (totalDays != md.TotalDaysFrom00010101) { Console.WriteLine("{0:d}: {1} vs {2}", date, totalDays, md.TotalDaysFrom00010101); } int year2, month2, day2; md.GetDate(out year2, out month2, out day2); if (year != year2 || month != month2 || day != day2) { Console.WriteLine("{0:d}: {1:D4}-{2:D2}-{3:D2} vs {4:D4}-{5:D2}-{6:D2}", date, year, month, day, year2, month2, day2); } date = date.AddDays(1); } |
号
(我知道这不是单元测试…但演示了如何使用
请注意,这是一个关于如何实现它的示例。我不会用这种方式实现它。我要做一个不可变的