xref: /PHP-8.3/ext/calendar/french.c (revision 92ac598a)
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