--- /dev/null
+/* This file is taken from http://www.genealogy.org/~scottlee/
+ Only this initial comment has been added. The next comment
+ gives the original copyright notice.
+*/
+
+
+/* $selId: french.c,v 2.0 1995/10/24 01:13:06 lees Exp $
+ * Copyright 1993-1995, Scott E. Lee, all rights reserved.
+ * Permission granted to use, copy, modify, distribute and sell so long as
+ * the above copyright and this permission statement are retained in all
+ * copies. THERE IS NO WARRANTY - USE AT YOUR OWN RISK.
+ */
+
+/**************************************************************************
+ *
+ * These are the externally visible components of this file:
+ *
+ * void
+ * SdnToFrench(
+ * long int sdn,
+ * int *pYear,
+ * int *pMonth,
+ * int *pDay);
+ *
+ * Convert a SDN to a French republican calendar date. If the input SDN is
+ * before the first day of year 1 or after the last day of year 14, the
+ * three output values will all be set to zero, otherwise *pYear will be in
+ * the range 1 to 14 inclusive; *pMonth will be in the range 1 to 13
+ * inclusive; *pDay will be in the range 1 to 30 inclusive. If *pMonth is
+ * 13, the SDN represents one of the holidays at the end of the year and
+ * *pDay will be in the range 1 to 6 inclusive.
+ *
+ * long int
+ * FrenchToSdn(
+ * int year,
+ * int month,
+ * int day);
+ *
+ * Convert a French republican calendar date to a SDN. Zero is returned
+ * when the input date is detected as invalid or out of the supported
+ * range. The return value will be > 0 for all valid, supported dates, but
+ * there are some invalid dates that will return a positive value. To
+ * verify that a date is valid, convert it to SDN and then back and compare
+ * with the original.
+ *
+ * char *FrenchMonthName[14];
+ *
+ * Convert a French republican month number (1 to 13) to the name of the
+ * French republican month (null terminated). An index of 13 (for the
+ * "extra" days at the end of the year) will return the string "Extra". An
+ * index of zero will return a zero length string.
+ *
+ * VALID RANGE
+ *
+ * These routines only convert dates in years 1 through 14 (Gregorian
+ * dates 22 September 1792 through 22 September 1806). This more than
+ * covers the period when the calendar was in use.
+ *
+ * I would support a wider range of dates, but I have not been able to
+ * find an authoritative definition of when leap years were to have
+ * occurred. There are suggestions that it was to skip a leap year ever
+ * 100 years like the Gregorian calendar.
+ *
+ * CALENDAR OVERVIEW
+ *
+ * The French republican calendar was adopted in October 1793 during
+ * the French Revolution and was abandoned in January 1806. The intent
+ * was to create a new calendar system that was based on scientific
+ * principals, not religious traditions.
+ *
+ * The year is divided into 12 months of 30 days each. The remaining 5
+ * to 6 days in the year are grouped at the end and are holidays. Each
+ * month is divided into three decades (instead of weeks) of 10 days
+ * each.
+ *
+ * The epoch (first day of the first year) is 22 September 1792 in the
+ * Gregorian calendar. Leap years are every fourth year (year 3, 7,
+ * 11, etc.)
+ *
+ * TESTING
+ *
+ * This algorithm has been tested from the year 1 to 14. The source
+ * code of the verification program is included in this package.
+ *
+ * REFERENCES
+ *
+ * I have found no detailed, authoritative reference on this calendar.
+ * The algorithms are based on a preponderance of less authoritative
+ * sources.
+ *
+ **************************************************************************/
+
+#include "sdncal.h"
+
+#define SDN_OFFSET 2375474
+#define DAYS_PER_4_YEARS 1461
+#define DAYS_PER_MONTH 30
+#define FIRST_VALID 2375840
+#define LAST_VALID 2380952
+
+void
+SdnToFrench(
+ long int sdn,
+ int *pYear,
+ int *pMonth,
+ int *pDay)
+{
+ long int temp;
+ int dayOfYear;
+
+ if (sdn < FIRST_VALID || sdn > LAST_VALID) {
+ *pYear = 0;
+ *pMonth = 0;
+ *pDay = 0;
+ return;
+ }
+
+ temp = (sdn - SDN_OFFSET) * 4 - 1;
+ *pYear = temp / DAYS_PER_4_YEARS;
+ dayOfYear = (temp % DAYS_PER_4_YEARS) / 4;
+ *pMonth = dayOfYear / DAYS_PER_MONTH + 1;
+ *pDay = dayOfYear % DAYS_PER_MONTH + 1;
+}
+
+long int
+FrenchToSdn(
+ int year,
+ int month,
+ int day)
+{
+ /* check for invalid dates */
+ if (year < 1 || year > 14 ||
+ month < 1 || month > 13 ||
+ day < 1 || day > 30)
+ {
+ return(0);
+ }
+
+ return( (year * DAYS_PER_4_YEARS) / 4
+ + (month - 1) * DAYS_PER_MONTH
+ + day
+ + SDN_OFFSET );
+}
+
+char *FrenchMonthName[14] = {
+ "",
+ "Vendemiaire",
+ "Brumaire",
+ "Frimaire",
+ "Nivose",
+ "Pluviose",
+ "Ventose",
+ "Germinal",
+ "Floreal",
+ "Prairial",
+ "Messidor",
+ "Thermidor",
+ "Fructidor",
+ "Extra"
+};