#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Last update January 2011 by Chris Tozzi
# For more information or to report problems, see http://christozzi.com/repyblican.php
import sys
import datetime
usage = "Usage: repyblican.py day [republican or Gregorian month] year\n\nExamples:\nrepyblican.py 13 Brumaire 3\nrepyblican.py 27 July 1794\nrepyblican.py Vertu 3"
# Arrays of month and sansculottides names. Make first value 'null' so that the first name is array[1], not array[0], as this mitigates confusion below
rep_months = 'null','Vendémiaire','Brumaire','Frimaire','Nivôse','Pluviôse','Ventôse','Germinal','Floréal','Prairial','Messidor','Thermidor','Fructidor'
greg_months = 'null','January','February','March','April','May','June','July','August','September','October','November','December'
sansculottides = 'null','Vertu','Génie','Travail','Opinion','Récompenses','Révolution'
# Generate lists of simplified month and sansculottide names (convert all characters to lowercase and remove accents)
# This way it doesn't matter whether the input names are capitalized or properly accented
rep_months_simp = []
greg_months_simp = []
sansculottides_simp = []
for key in rep_months:
key = key.lower().translate(None,"ôéeo")
rep_months_simp.append(key)
for key in greg_months:
key = key.lower() # Don't remove accents for Gregorian month names because they have no accents
greg_months_simp.append(key)
for key in sansculottides:
key = key.lower().translate(None,"ôéeo")
sansculottides_simp.append(key)
# Check input data for validity
def analyze_input():
if len(sys.argv) <= 1: # No arguments given
print usage
quit()
elif len(sys.argv) > 4: # Too many arguments given
print "Invalid input :", sys.argv[1:]
quit()
elif len(sys.argv) == 3 and sys.argv[1].lower().translate(None,"ôéeo") in sansculottides_simp: # Input is sansculottide date
if not sys.argv[2].isdigit():
print "Invalid year: ", sys.argv[2] # Input year for sansculottide is not a digit
quit()
elif not sys.argv[3].isdigit(): # Input year for non-sansculottide date is not a digit
print "Invalid year: ", sys.argv[3]
quit()
elif int(sys.argv[3]) <= 1791: # Input is a republican date
if not sys.argv[1].isdigit():
print "Invalid day: ", sys.argv[1]
quit()
if not 0 < int(sys.argv[1]) < 31:
print "Invalid day: ", sys.argv[1]
quit()
if sys.argv[2].isdigit() and not 0 < int(sys.argv[2]) < 13:
print "Invalid month: ", sys.argv[2]
quit()
if not sys.argv[2].isdigit() and not sys.argv[2].lower().translate(None,"ôéeo") in rep_months_simp:
print "Invalid month: ", sys.argv[2]
quit()
if int(sys.argv[3]) > 14:
print "WARNING: republican year", sys.argv[3], "is later than the republican period. I'll still calculate the date, but I can't guarantee accuracy!"
elif 1791 < int(sys.argv[3]) < 10000: # Input is a Gregorian date
republican_date = "no"
if not sys.argv[1].isdigit():
print "Invalid day: ", sys.argv[1]
quit()
if not 0 < int(sys.argv[1]) < 32:
print "Invalid day: ", sys.argv[1]
quit()
if sys.argv[2].isdigit() and not 0 < int(sys.argv[2]) < 13:
print "Invalid month: ", sys.argv[2]
quit()
if not sys.argv[2].isdigit() and not sys.argv[2].lower() in greg_months_simp:
print "Invalid month: ", sys.argv[2]
quit()
if int(sys.argv[3]) > 1806:
print "WARNING: Gregorian year", sys.argv[3], "is later than the republican period. I'll still calculate the date, but I can't guarantee accuracy!"
elif int(sys.argv[3]) > 9999: # Year can't exceed 9999 or datetime functions will fail
print "Invalid year :", sys.argv[3], ". Year must be between 1 and 9999"
quit()
else:
print "Invalid input :", sys.argv[1:]
quit()
def get_dates(): # Calculate numerical date
global month
global day
global year
for i in range (1,7):
if sys.argv[1].lower().translate(None,"ôéeo") == sansculottides_simp[i]:
month = int(13)
day = int(i)
year = int(sys.argv[2])
for i in range(1,13):
if rep_months_simp[i] == sys.argv[2].lower().translate(None,"ôéeo") or greg_months_simp[i] == sys.argv[2].lower():
month = int(i)
day = int(sys.argv[1])
year = int(sys.argv[3])
if len(sys.argv) > 3 and sys.argv[2].isdigit():
month = int(sys.argv[2])
day = int(sys.argv[1])
year = int(sys.argv[3])
def get_days_since_Republic(): # Calculate days since the Republic was founded (22 September 1792)
global days_since_Republic
global leaps # Number of republican leap years
global greg_leap_years # Gregorian years in which a _republican_ leap year occurs
greg_leap_years = '1795','1799','1803','1807' # Could write something to populate this automatically with all possible dates
if year <= 1791:
# First calculate basic days_since_Republic, ignoring leap years
days_since_Republic = int((day)+((month-1)*30)+((year-1)*365))
# Calculate number of republican leap years. Republican leap years
# occur on the last day of years 3, 7, 11, etc. A sixth sansculottide
# day is added to these years
leaps = int(year/4)
# If (and only if) we are on the sixth sansculottide of a republican leap year, we add a leap,
# since we consider a new leap year to have occurred when the calendar reaches the beginning of
# a sixth sansculottide day
if month == 13 and day == 6:
leaps = leaps + 1
# Add an extra day to days_since_Republic for each leap year
days_since_Republic = days_since_Republic + leaps
elif year > 1791:
days_since_Republic = datetime.date(year, month, day) - datetime.date(1792, 9, 21)
days_since_Republic = int(days_since_Republic.days)
# Calculate how many _republican_ leap years have occurred since input date
# (i.e., how many times a Jour de la Révolution has happened)
# The first Jour de la Révolution occurs on 22 September 1795; it recurs
# every four republican years thereafter
# Note that Gregorian leap years are NOT a reliable means of calculating republican leap years,
# because they do NOT always occur every four years (1800 was not a leap year), which republican years do
# (The republican calendar was supposed to be adjusted beginning in year 20 to account for this,
# but the calendar was abolished before that date)
# See http://www.webexhibits.org/calendars/calendar-french.html#anchor-leap-years for more on
# republican leap years
leaps = 0 # Initially (for dates before 22 September 1795) we have no leaps
# Beginning in 1796, there is at least one leap year for every four years that have passed
if int(year) >= 1796:
leaps = int((year - 1792)/4)
# For dates on or after 22 September of each year, we add one more leap year
if str(year) in greg_leap_years and month == 9 and day >= 22:
leaps = int((year - 1792)/4) + 1
elif str(year) in greg_leap_years and month >= 10:
leaps = int((year - 1792)/4) + 1
# Calculate republican date based on days_since_Republic
def get_rep_date():
global rep_day
global rep_month
global rep_year
rep_year = int((days_since_Republic)/365) + 1
rep_month = int((days_since_Republic - (365*(rep_year - 1)))/(30.4666666)) + 1
rep_day = int(days_since_Republic - (365*(rep_year - 1)) - (30*(rep_month-1))) - leaps
# Below, we run some checks to correct particular situations where rounding and sansculottide
# bizarreness cause problems with the numbers produced by the math above
# Probably some of this messiness could be avoided if the calculations above were made more precise
if rep_day == 0 and rep_month == 1: # This happens on the last sansculottide of each republican year
rep_year = rep_year - 1
# Determine if this is a sixth sansculottide, or a fifth
if str(year) in greg_leap_years and month == 9 and day == 22:
rep_day = 36
elif str(year) in greg_leap_years and month == 9 and day == 23 and year >= 1803:
rep_day = 36
else:
rep_day = 35
rep_date = "Day of " + str(sansculottides[int(rep_day)-30]) + " (sansculottide) Year " + str(rep_year)
elif rep_day > 30 and rep_month == 12: # If rep_day > 30 and the month == 12, we are in the sansculottides
rep_date = "Day of " + str(sansculottides[int(rep_day)-30]) + " (sansculottide) Year " + str(rep_year)
elif rep_month == 13: # If rep_month == 13, we are also in the sansculottides
rep_date = "Day of " + str(sansculottides[int(rep_day)]) + " (sansculottide) Year " + str(rep_year)
elif rep_day < 0 and rep_month == 1: # This happens for some third and fourth sansculottides dates
rep_year = rep_year - 1
rep_day = rep_day + 35
if year >= 1803:
rep_day = rep_day + 1
rep_date = "Day of " + str(sansculottides[int(rep_day)-30]) + " (sansculottide) Year " + str(rep_year)
elif rep_month != 12 and rep_day > 30: # This happens on the last day (or days) of each republican month
rep_month = rep_month + 1
rep_day = rep_day - 30
rep_date = str(rep_day) + " " + str(rep_months[rep_month]) + " Year " + str(rep_year)
elif rep_day < 0: # Sometimes happens towards the end of a republican month
rep_day = rep_day + 30
if year >= 1799:
rep_month = rep_month - 1
else:
rep_month = 1
rep_date = str(rep_day) + " " + str(rep_months[rep_month]) + " Year " + str(rep_year)
elif rep_day == 0 and rep_month == 2 and year < 1799: # This happens in certain years for some reason
rep_day = 30
rep_month = 1
rep_date = str(rep_day) + " " + str(rep_months[rep_month]) + " Year " + str(rep_year)
elif rep_day == 0 and rep_month == 3 and year < 1799: # This happens in certain years for some reason
rep_day = 30
rep_month = 2
rep_date = str(rep_day) + " " + str(rep_months[rep_month]) + " Year " + str(rep_year)
elif rep_day == 0 and year >= 1799: # This happens in certain years for some reason
rep_day = 30
rep_month = rep_month - 1
rep_date = str(rep_day) + " " + str(rep_months[rep_month]) + " Year " + str(rep_year)
else: # If none of the above conditions apply, we don't have to adjust the numbers and can simply get the final date
rep_date = str(rep_day) + " " + str(rep_months[rep_month]) + " Year " + str(rep_year)
print "Republican date: ", rep_date
# Calculate Gregorian date based on days_since_Republic
def get_greg_date():
greg_date = datetime.date(1792, 9, 21) + datetime.timedelta(days=days_since_Republic)
print "Gregorian date: ", greg_date
def debug(): # Print out some extra information for debugging purposes
print "day =", day
print "month =", month
print "year =", year
print "rep_day =", rep_day
print "rep_month =", rep_month
print "rep_year =", rep_year
print "days since Republic =", days_since_Republic
print "leaps =", leaps
def main():
analyze_input()
get_dates()
get_days_since_Republic()
get_rep_date()
get_greg_date()
main()