Opa_omroep-automatiseren/venv/lib/python3.8/site-packages/convertdate/positivist.py

151 lines
3.8 KiB
Python
Raw Normal View History

2020-12-27 20:00:11 +00:00
# -*- coding: utf-8 -*-
# This file is part of convertdate.
# http://github.com/fitnr/convertdate
# Licensed under the MIT license:
# http://opensource.org/licenses/MIT
# Copyright (c) 2016, fitnr <fitnr@fakeisthenewreal>
from calendar import isleap
from . import gregorian
from .utils import floor
from .data import positivist as data
'''
Convert between Gregorian/Julian Day and Comte's Positivist calendar.
The Positivist calendar has 13 months and one or two festival days.
Festival days are given as the fourteenth month.
The Gregorian date 1789-01-01 is Positivist 0001-01-01.
'''
# Positivist calendar has 13 28-day months and one festival day
EPOCH = 2374479.5
YEAR_EPOCH = 1789
DAYS_IN_YEAR = 365
MONTHS = (
'Moses', 'Homer', 'Aristotle', 'Archimedes',
'Caesar', 'Saint Paul', 'Charlemagne', 'Dante',
'Gutenberg', 'Shakespeare', 'Descartes', 'Frederic',
'Bichat', ''
)
def legal_date(year, month, day):
'''Checks if a given date is a legal positivist date'''
try:
assert year >= 1
assert 0 < month <= 14
assert 0 < day <= 28
if month == 14:
if isleap(year + YEAR_EPOCH - 1):
assert day <= 2
else:
assert day == 1
except AssertionError:
raise ValueError("Invalid Positivist date: ({}, {}, {})".format(year, month, day))
return True
def to_jd(year, month, day):
'''Convert a Positivist date to Julian day count.'''
legal_date(year, month, day)
gyear = year + YEAR_EPOCH - 1
return (
gregorian.EPOCH - 1 + (365 * (gyear - 1)) +
floor((gyear - 1) / 4) + (-floor((gyear - 1) / 100)) +
floor((gyear - 1) / 400) + (month - 1) * 28 + day
)
def from_jd(jd):
'''Convert a Julian day count to Positivist date.'''
try:
assert jd >= EPOCH
except AssertionError:
raise ValueError('Invalid Julian day')
depoch = floor(jd - 0.5) + 0.5 - gregorian.EPOCH
quadricent = floor(depoch / gregorian.INTERCALATION_CYCLE_DAYS)
dqc = depoch % gregorian.INTERCALATION_CYCLE_DAYS
cent = floor(dqc / gregorian.LEAP_SUPPRESSION_DAYS)
dcent = dqc % gregorian.LEAP_SUPPRESSION_DAYS
quad = floor(dcent / gregorian.LEAP_CYCLE_DAYS)
dquad = dcent % gregorian.LEAP_CYCLE_DAYS
yindex = floor(dquad / gregorian.YEAR_DAYS)
year = (
quadricent * gregorian.INTERCALATION_CYCLE_YEARS +
cent * gregorian.LEAP_SUPPRESSION_YEARS +
quad * gregorian.LEAP_CYCLE_YEARS + yindex
)
if yindex == 4:
yearday = 365
year = year - 1
else:
yearday = (
depoch -
quadricent * gregorian.INTERCALATION_CYCLE_DAYS -
cent * gregorian.LEAP_SUPPRESSION_DAYS -
quad * gregorian.LEAP_CYCLE_DAYS -
yindex * gregorian.YEAR_DAYS
)
month = floor(yearday / 28)
return (year - YEAR_EPOCH + 2, month + 1, int(yearday - (month * 28)) + 1)
def from_gregorian(year, month, day):
return from_jd(gregorian.to_jd(year, month, day))
def to_gregorian(year, month, day):
return gregorian.from_jd(to_jd(year, month, day))
def dayname(year, month, day):
'''
Give the name of the month and day for a given date.
Returns:
tuple month_name, day_name
'''
legal_date(year, month, day)
yearday = (month - 1) * 28 + day
if isleap(year + YEAR_EPOCH - 1):
dname = data.day_names_leap[yearday - 1]
else:
dname = data.day_names[yearday - 1]
return MONTHS[month - 1], dname
def weekday(day):
'''
Gives the weekday (0=Monday) of a positivist month and day.
Note that the festival month does not have a day.
'''
return (day % 7) - 1
def festival(month, day):
'''
Gives the festival day for a month and day.
Returns None if inapplicable.
'''
return data.festivals.get((month, day))