Search code examples
pythondatecalendar

Calender types in Python


I have to map a certain number of days, lets say 10590 to a few different calender types, preferrably in python.

The calenders I would like to use are standard, proleptic gregorian, 360 day, 365 day, and 366 day.

I tried looking for such functionality in the python calender module but didn't find anything, at least not a straight forward solution. Does this exist or do i have to implement it myself?

To be clear, I don't need to display anything fancy, just simply map a given day to a date of a given calender type.

Thank you!


Solution

  • Hope this alternative code snippet can help you out. It is using datetime instead. Tested locally:

    import datetime
    
    class Calendar:
        def __init__(self, start_year, start_month, start_day):
            self.start_date = datetime.date(start_year, start_month, start_day)
    
        def days_to_date(self, days):
            raise NotImplementedError
    
    
    class GregorianCalendar(Calendar):
        def __init__(self):
            super().__init__(1900, 1, 1)
    
        def days_to_date(self, days):
            return self.start_date + datetime.timedelta(days=days)
    
    
    class ProlepticGregorianCalendar(Calendar):
        def __init__(self):
            super().__init__(1, 1, 1)
    
        def days_to_date(self, days):
            return self.start_date + datetime.timedelta(days=days)
    
    
    class ThreeSixtyDayCalendar(Calendar):
        def __init__(self):
            super().__init__(1900, 1, 1)
    
        def days_to_date(self, days):
            years, days_in_year = divmod(days, 360)
            target_year = self.start_date.year + years
            target_month, target_day = divmod(days_in_year, 30)
            return datetime.date(target_year, target_month + 1, target_day + 1)
    
    
    class ThreeSixtyFiveDayCalendar(Calendar):
        def __init__(self):
            super().__init__(1, 1, 1)
    
        def days_to_date(self, days):
            return self.start_date + datetime.timedelta(days=days - 1)
    
    
    class ThreeSixtySixDayCalendar(Calendar):
        def __init__(self):
            super().__init__(1, 1, 1)
    
        def days_to_date(self, days):
            return self.start_date + datetime.timedelta(days=days - 1)
    
    
    class CalendarFactory:
        @staticmethod
        def create_calendar(calendar_type):
            if calendar_type == 'gregorian':
                return GregorianCalendar()
            elif calendar_type == 'proleptic_gregorian':
                return ProlepticGregorianCalendar()
            elif calendar_type == '360_day':
                return ThreeSixtyDayCalendar()
            elif calendar_type == '365_day':
                return ThreeSixtyFiveDayCalendar()
            elif calendar_type == '366_day':
                return ThreeSixtySixDayCalendar()
            else:
                raise ValueError('Invalid calendar type')
    
    
    days = 10590
    
    # create Gregorian calendar and map days to date
    calendar = CalendarFactory.create_calendar('gregorian')
    print(calendar.days_to_date(days))  # prints: 1931-06-26
    
    # create 360-day calendar and map days to date
    calendar = CalendarFactory.create_calendar('360_day')
    print(calendar.days_to_date(days))  # prints: 1930-10-29