french.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /* $selId: french.c,v 2.0 1995/10/24 01:13:06 lees Exp $
  2. * Copyright 1993-1995, Scott E. Lee, all rights reserved.
  3. * Permission granted to use, copy, modify, distribute and sell so long as
  4. * the above copyright and this permission statement are retained in all
  5. * copies. THERE IS NO WARRANTY - USE AT YOUR OWN RISK.
  6. */
  7. /**************************************************************************
  8. *
  9. * These are the externally visible components of this file:
  10. *
  11. * void
  12. * SdnToFrench(
  13. * long int sdn,
  14. * int *pYear,
  15. * int *pMonth,
  16. * int *pDay);
  17. *
  18. * Convert a SDN to a French republican calendar date. If the input SDN is
  19. * before the first day of year 1 or after the last day of year 14, the
  20. * three output values will all be set to zero, otherwise *pYear will be in
  21. * the range 1 to 14 inclusive; *pMonth will be in the range 1 to 13
  22. * inclusive; *pDay will be in the range 1 to 30 inclusive. If *pMonth is
  23. * 13, the SDN represents one of the holidays at the end of the year and
  24. * *pDay will be in the range 1 to 6 inclusive.
  25. *
  26. * long int
  27. * FrenchToSdn(
  28. * int year,
  29. * int month,
  30. * int day);
  31. *
  32. * Convert a French republican calendar date to a SDN. Zero is returned
  33. * when the input date is detected as invalid or out of the supported
  34. * range. The return value will be > 0 for all valid, supported dates, but
  35. * there are some invalid dates that will return a positive value. To
  36. * verify that a date is valid, convert it to SDN and then back and compare
  37. * with the original.
  38. *
  39. * char *FrenchMonthName[14];
  40. *
  41. * Convert a French republican month number (1 to 13) to the name of the
  42. * French republican month (null terminated). An index of 13 (for the
  43. * "extra" days at the end of the year) will return the string "Extra". An
  44. * index of zero will return a zero length string.
  45. *
  46. * VALID RANGE
  47. *
  48. * These routines only convert dates in years 1 through 14 (Gregorian
  49. * dates 22 September 1792 through 22 September 1806). This more than
  50. * covers the period when the calendar was in use.
  51. *
  52. * I would support a wider range of dates, but I have not been able to
  53. * find an authoritative definition of when leap years were to have
  54. * occurred. There are suggestions that it was to skip a leap year ever
  55. * 100 years like the Gregorian calendar.
  56. *
  57. * CALENDAR OVERVIEW
  58. *
  59. * The French republican calendar was adopted in October 1793 during
  60. * the French Revolution and was abandoned in January 1806. The intent
  61. * was to create a new calendar system that was based on scientific
  62. * principals, not religious traditions.
  63. *
  64. * The year is divided into 12 months of 30 days each. The remaining 5
  65. * to 6 days in the year are grouped at the end and are holidays. Each
  66. * month is divided into three decades (instead of weeks) of 10 days
  67. * each.
  68. *
  69. * The epoch (first day of the first year) is 22 September 1792 in the
  70. * Gregorian calendar. Leap years are every fourth year (year 3, 7,
  71. * 11, etc.)
  72. *
  73. * TESTING
  74. *
  75. * This algorithm has been tested from the year 1 to 14. The source
  76. * code of the verification program is included in this package.
  77. *
  78. * REFERENCES
  79. *
  80. * I have found no detailed, authoritative reference on this calendar.
  81. * The algorithms are based on a preponderance of less authoritative
  82. * sources.
  83. *
  84. **************************************************************************/
  85. #include "sdncal.h"
  86. #define FRENCH_SDN_OFFSET 2375474
  87. #define DAYS_PER_4_YEARS 1461
  88. #define DAYS_PER_MONTH 30
  89. #define FIRST_VALID 2375840
  90. #define LAST_VALID 2380952
  91. void SdnToFrench(
  92. zend_long sdn,
  93. int *pYear,
  94. int *pMonth,
  95. int *pDay)
  96. {
  97. zend_long temp;
  98. int dayOfYear;
  99. if (sdn < FIRST_VALID || sdn > LAST_VALID) {
  100. *pYear = 0;
  101. *pMonth = 0;
  102. *pDay = 0;
  103. return;
  104. }
  105. temp = (sdn - FRENCH_SDN_OFFSET) * 4 - 1;
  106. *pYear = temp / DAYS_PER_4_YEARS;
  107. dayOfYear = (temp % DAYS_PER_4_YEARS) / 4;
  108. *pMonth = dayOfYear / DAYS_PER_MONTH + 1;
  109. *pDay = dayOfYear % DAYS_PER_MONTH + 1;
  110. }
  111. zend_long FrenchToSdn(
  112. int year,
  113. int month,
  114. int day)
  115. {
  116. /* check for invalid dates */
  117. if (year < 1 || year > 14 ||
  118. month < 1 || month > 13 ||
  119. day < 1 || day > 30) {
  120. return (0);
  121. }
  122. return ((year * DAYS_PER_4_YEARS) / 4
  123. + (month - 1) * DAYS_PER_MONTH
  124. + day
  125. + FRENCH_SDN_OFFSET);
  126. }
  127. const char * const FrenchMonthName[14] =
  128. {
  129. "",
  130. "Vendemiaire",
  131. "Brumaire",
  132. "Frimaire",
  133. "Nivose",
  134. "Pluviose",
  135. "Ventose",
  136. "Germinal",
  137. "Floreal",
  138. "Prairial",
  139. "Messidor",
  140. "Thermidor",
  141. "Fructidor",
  142. "Extra"
  143. };