Source code for timelinelib.calendar.coptic.dateformatter
# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Rickard Lindberg, Roger Lindberg
#
# This file is part of Timeline.
#
# Timeline is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Timeline is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Timeline. If not, see <http://www.gnu.org/licenses/>.
from timelinelib.calendar.coptic.coptic import days_in_month
from timelinelib.calendar.coptic.monthnames import abbreviated_name_of_month
from timelinelib.calendar.coptic.monthnames import month_of_abbreviated_name
[docs]class CopticDateFormatter:
YEAR = "YEAR"
MONTH = "MONTH"
DAY = "DAY"
[docs] def __init__(self):
self.set_separators("-", "-")
self.set_region_order(year=0, month=1, day=2)
self.use_abbreviated_name_for_month(False)
self.use_date_default_values = False
self.default_year = '1700'
self.default_month = '01'
self.default_day = '01'
[docs] def use_abbreviated_name_for_month(self, value):
self._use_abbreviated_name_for_month = value
[docs] def set_separators(self, first, second):
if not first or not second:
raise ValueError("Can not set empty separator.")
self._first_separator = first
self._second_separator = second
[docs] def set_region_order(self, year, month, day):
if set([year, month, day]) != set([0, 1, 2]):
raise ValueError("Invalid region order. Must be a combination of 0, 1, and 2.")
self._year_position = year
self._month_position = month
self._day_position = day
[docs] def set_defaults(self, use_date_default_values, default_year=None, default_month=None, default_day=None):
self.use_date_default_values = use_date_default_values
self.default_year = default_year
self.default_month = default_month
self.default_day = default_day
[docs] def format(self, ymd_tuple):
(year, month, day) = ymd_tuple
return self._format_date(year, month, day), self._is_bc(year)
[docs] def format_sample_date(self):
date_tuple = int(self.default_year), int(self.default_month), int(self.default_day)
return self.format(date_tuple)[0]
[docs] def parse(self, date_bc_tuple):
(date, is_bc) = date_bc_tuple
regions = self._split(date)
if self.use_date_default_values:
self.set_default_regions(regions, date)
year = self._parse_year(regions[self._year_position], is_bc)
month = self._parse_month(regions[self._month_position])
day = self._parse_day(regions[self._day_position], year, month)
return (year, month, day)
[docs] def set_default_regions(self, regions, date):
if regions == ['', '', '']:
regions[0] = date
for n in range(3):
if regions[n] == '':
self.set_default_for_region(regions, n)
[docs] def set_default_for_region(self, regions, n):
if self._year_position == n:
regions[n] = self.default_year
elif self._month_position == n:
regions[n] = self.default_month
elif self._day_position == n:
regions[n] = self.default_day
[docs] def get_region_type(self, date_string, cursor_position):
return {
self._year_position: self.YEAR,
self._month_position: self.MONTH,
self._day_position: self.DAY,
}[self._get_region(date_string, cursor_position)]
def _get_region(self, date_string, cursor_position):
if cursor_position < self._get_region_start(date_string, 1):
return 0
elif cursor_position < self._get_region_start(date_string, 2):
return 1
else:
return 2
def _split(self, date_string):
region_1 = region_2 = region_3 = ''
try:
(region_1, region_2) = date_string.split(self._first_separator, 1)
(region_2, region_3) = region_2.split(self._second_separator, 1)
except ValueError:
pass
return [
region_1,
region_2,
region_3,
]
[docs] def get_next_region(self, date_string, cursor_position):
if self._cursor_at_end_of_string(date_string, cursor_position):
return None
for region in [1, 2]:
if cursor_position < self._get_region_start(date_string, region):
return self._get_region_selection(date_string, region)
return None
def _cursor_at_end_of_string(self, date_string, cursor_position):
return cursor_position == len(date_string)
[docs] def get_previous_region(self, date_string, cursor_position):
for region in [1, 0]:
if cursor_position > self._get_region_end(date_string, region):
return self._get_region_selection(date_string, region)
return None
def _get_region_selection(self, date_string, which_region):
return (self._get_region_start(date_string, which_region),
self._get_region_len(date_string, which_region))
def _get_region_len(self, date_string, which_region):
return len(self._split(date_string)[which_region])
def _get_region_start(self, date_string, which_region):
part_delimiter = {
0: 0,
1: 2,
2: 4,
}[which_region]
return len("".join(self._get_all_parts(date_string)[:part_delimiter]))
def _get_region_end(self, date_string, which_region):
part_delimiter = {
0: 1,
1: 3,
2: 5,
}[which_region]
return len("".join(self._get_all_parts(date_string)[:part_delimiter]))
def _get_all_parts(self, date_string):
regions = self._split(date_string)
return [
regions[0],
self._first_separator,
regions[1],
self._second_separator,
regions[2],
]
def _format_date(self, year, month, day):
regions = {
self._year_position: self._format_year(year),
self._month_position: self._format_month(month),
self._day_position: self._format_day(day),
}
return "".join([
regions[0],
self._first_separator,
regions[1],
self._second_separator,
regions[2],
])
def _format_year(self, year):
if self._is_bc(year):
new_year = 1 - year
else:
new_year = year
return "%04d" % new_year
def _is_bc(self, year):
return year <= 0
def _parse_year(self, year_string, is_bc):
if is_bc:
return 1 - int(year_string)
else:
return int(year_string)
def _format_month(self, month):
if self._use_abbreviated_name_for_month:
return abbreviated_name_of_month(month)
else:
return "%02d" % month
def _parse_month(self, month_string):
if self._use_abbreviated_name_for_month:
return month_of_abbreviated_name(month_string)
else:
month = int(month_string)
if month - 1 in range(13):
return month
else:
raise ValueError("Invalid month")
def _format_day(self, day):
return "%02d" % day
def _parse_day(self, day_string, year, month):
day = int(day_string)
if day - 1 in range(days_in_month(year, month)):
return day
else:
raise ValueError("Invalid day")