python-minari-date/minari_date/__init__.py

229 lines
5.4 KiB
Python
Raw Normal View History

2021-03-19 14:42:41 +00:00
from datetime import datetime, timedelta
from math import ceil
from typing import Optional
class MinariDateTime:
DAY_NAMES = (
'Mirdu',
'Hëmi',
'Drak',
'Þodon',
'Charm',
'Rounn',
)
MONTH_NAMES = (
'Mëbel',
'Dirann',
'Ma',
'Gerub',
'Þrei',
'Dimoc',
'Xentor',
2021-11-19 07:44:20 +00:00
'Mëðir',
2021-03-19 14:42:41 +00:00
'Draþ',
'Quaden',
'Ridïmel',
'Rodom',
)
SPECIAL_NAMES = (
'Hëður',
'Rideyy',
'Morkh',
'Khmerd',
'Chamog',
)
ENTITIES = {
'Hëður': {
'entity': 'Garquon',
'element': 'Meren'
},
'Mëbel': {
'entity': 'Þoraðrin',
'element': 'Aðun'
},
'Dirann': {
'entity': 'Detërien',
'element': 'Merðen'
},
'Ma': {
'entity': 'Elin',
'element': 'Fronn'
},
'Rideyy': {
'entity': 'Hëriel',
'element': 'Enðir'
},
'Gerub': {
'entity': 'Iliþon',
'element': 'Miþon'
},
'Þrei': {
'entity': 'Amenar',
'element': None
},
'Dimoc': {
'entity': 'Iminiru',
'element': 'Sëdur'
},
'Morkh': {
'entity': 'Luminar',
'element': 'Holar'
},
'Xentor': {
'entity': 'Motimor',
'element': 'Rort'
},
'Mëðïr': {
'entity': 'Mirian',
'element': 'Ilšir'
},
'Draþ': {
'entity': 'Heloor',
'element': None
},
'Khmerd': {
'entity': 'Zuþeron',
'element': 'Gord'
},
'Quaden': {
'entity': 'Umonar',
'element': 'Ulquon'
},
'Ridïmel': {
'entity': 'Feiriamen',
'element': 'Reina'
},
'Rodom': {
'entity': 'Nozoru',
'element': 'Zima'
},
'Chamog': {
'entity': 'Ketirai',
'element': 'Loar'
}
}
def __init__(self, timestamp: datetime):
self.set_timestamp(timestamp.replace(hour=0, minute=0, second=0, microsecond=0))
self._minari_year = None
self._minari_month = None
self._minari_day = None
self._special_day = None
self._minari_weekday = None
def set_timestamp(self, timestamp: datetime):
self._timestamp = timestamp + timedelta(days=11)
self._calculated = False
@staticmethod
def _get_doy(timestamp: datetime) -> int:
onejan = datetime(timestamp.year, 1, 1)
time_diff = timestamp - onejan
return ceil(time_diff.total_seconds() / 86400)
@staticmethod
def _is_leap(timestamp: datetime) -> bool:
year = timestamp.year
if year % 400 == 0:
return True
if year % 100 == 0:
return False
if year % 4 == 0:
return True
return False
def _calculate_minari_parts(self):
if self._calculated:
return
minari_leap = self._is_leap(self._timestamp)
doy = self._get_doy(self._timestamp)
self._minari_year = self._timestamp.year - 1873
self._minari_month = None
self._minari_day = None
special_days = (
(0, None, 0),
(91, None, 1),
(182, None, 2),
(183, True, 2),
(273, False, 3),
(274, True, 3),
(364, False, 4),
(365, True, 4),
)
for special_doy, leap_only, special_num in special_days:
if doy == special_doy and (leap_only is None or leap_only == minari_leap):
self._special_day = special_num
break
if self._special_day is None:
decr = 0
minari_doy = doy
for special_doy, leap_only, _ in special_days:
if minari_doy > special_doy and (leap_only is None or leap_only == minari_leap):
decr += 1
minari_doy -= decr - 1
self._minari_month = ceil(minari_doy / 30)
self._minari_day = minari_doy % 30
if self._minari_day == 0:
self._minari_day = 30
self._minari_weekday = self._minari_day % 6
self._calculated = True
@property
def minari_year(self):
if not self._calculated:
self._calculate_minari_parts()
return self._minari_year
@property
def minari_month(self):
if not self._calculated:
self._calculate_minari_parts()
return self._minari_month
@property
def minari_day(self):
if not self._calculated:
self._calculate_minari_parts()
return self._minari_day
@property
def minari_special(self):
if not self._calculated:
self._calculate_minari_parts()
return self._special_day
def __str__(self):
output = f'{self.minari_year} '
if self._special_day is not None:
output += self.SPECIAL_NAMES[self._special_day]
else:
month_name = self.MONTH_NAMES[self._minari_month]
weekday_name = self.DAY_NAMES[self._minari_weekday]
output += f'{month_name} {self._minari_day} ({weekday_name})'
return output