Computus.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System.IO;
  2. using JetBrains.Annotations;
  3. namespace Content.Server.Holiday.ShouldCelebrate
  4. {
  5. /// <summary>
  6. /// Computus for easter calculation.
  7. /// </summary>
  8. [UsedImplicitly]
  9. [DataDefinition]
  10. public sealed partial class Computus : DefaultHolidayShouldCelebrate
  11. {
  12. [DataField("daysEarly")]
  13. private byte _daysEarly = 1;
  14. [DataField("daysExtra")]
  15. private byte _daysExtra = 1;
  16. public (int day, int month) DoComputus(DateTime date)
  17. {
  18. var currentYear = date.Year;
  19. var m = 0;
  20. var n = 0;
  21. switch (currentYear)
  22. {
  23. case var i when i >= 1900 && i <= 2099:
  24. m = 24;
  25. n = 5;
  26. break;
  27. case var i when i >= 2100 && i <= 2199:
  28. m = 24;
  29. n = 6;
  30. break;
  31. case var i when i >= 2200 && i <= 2299:
  32. m = 25;
  33. n = 0;
  34. break;
  35. // Hello, future person! If you're living in the year >=2300, you might want to fix this method.
  36. // t. earth coder living in 2021
  37. default:
  38. throw new InvalidDataException("Easter machine broke.");
  39. }
  40. var a = currentYear % 19;
  41. var b = currentYear % 4;
  42. var c = currentYear % 7;
  43. var d = (19 * a + m) % 30;
  44. var e = (2 * b + 4 * c + 6 * d + n) % 7;
  45. (int day, int month) easterDate = (0, 0);
  46. if (d + e < 10)
  47. {
  48. easterDate.month = 3;
  49. easterDate.day = (d + e + 22);
  50. } else if (d + e > 9)
  51. {
  52. easterDate.month = 4;
  53. easterDate.day = (d + e - 9);
  54. }
  55. if (easterDate.month == 4 && easterDate.day == 26)
  56. easterDate.day = 19;
  57. if (easterDate.month == 4 && easterDate.day == 25 && d == 28 && e == 6 && a > 10)
  58. easterDate.day = 18;
  59. return easterDate;
  60. }
  61. public override bool ShouldCelebrate(DateTime date, HolidayPrototype holiday)
  62. {
  63. if (holiday.BeginMonth == Month.Invalid)
  64. {
  65. var (day, month) = DoComputus(date);
  66. holiday.BeginDay = (byte) day;
  67. holiday.BeginMonth = (Month) month;
  68. holiday.EndDay = (byte) (holiday.BeginDay + _daysExtra);
  69. holiday.EndMonth = holiday.BeginMonth;
  70. // Begins in march, ends in april
  71. if (holiday.EndDay >= 32 && holiday.EndMonth == Month.March)
  72. {
  73. holiday.EndDay -= 31;
  74. holiday.EndMonth++;
  75. }
  76. // Begins in april, ends in june.
  77. if (holiday.EndDay >= 31 && holiday.EndMonth == Month.April)
  78. {
  79. holiday.EndDay -= 30;
  80. holiday.EndMonth++;
  81. }
  82. holiday.BeginDay -= _daysEarly;
  83. // Begins in march, ends in april.
  84. if (holiday.BeginDay <= 0 && holiday.BeginMonth == Month.April)
  85. {
  86. holiday.BeginDay += 31;
  87. holiday.BeginMonth--;
  88. }
  89. }
  90. return base.ShouldCelebrate(date, holiday);
  91. }
  92. }
  93. }