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