Last active
December 27, 2018 00:41
-
-
Save petermcd/60132535abb474fe2c99294a04b7dcf6 to your computer and use it in GitHub Desktop.
Adding days, weeks, months or years to a datetime
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Author: Peter McDonald | |
Description: Probably not the best way to do this but gives the ability to add or remove days, weeks, | |
months or years to a DateTime date | |
""" | |
from datetime import datetime | |
MonthDays = [None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] | |
class DateTimeDelta: | |
_epoch: float = 0 # Stores the Unix Epoch of the given date | |
_original: datetime = None # The original date passed in init | |
""" | |
Description: Initializer | |
date_time: date_time The date additions/subtractions will be made on. | |
""" | |
def __init__(self, date_time: datetime = datetime.now()): | |
self.date = date_time | |
""" | |
Description: Adds a given number of days to the stored date | |
days: int Number of days to be added. | |
""" | |
def add_days(self, days: int = 1): | |
"""Convert days into seconds and add to stored epoch""" | |
self._epoch += days * 24 * 60 * 60 | |
""" | |
Description: Subtracts a given number of days to the stored date | |
days: int Number of days to be subtracted. | |
""" | |
def remove_days(self, days: int = 1): | |
"""Convert days into seconds and subtract to stored epoch""" | |
self._epoch -= days * 24 * 60 * 60 | |
""" | |
Description: Adds a given weeks of weeks to the stored date | |
weeks: int Number of weeks to be added. | |
""" | |
def add_weeks(self, weeks: int = 1): | |
"""Calculate weeks in days and use add_days""" | |
self.add_days(7 * weeks) | |
""" | |
Description: Subtracts a given weeks of days to the stored date | |
weeks: int Number of weeks to be added. | |
""" | |
def remove_weeks(self, weeks: int = 1): | |
"""Calculate weeks in days and use remove_days""" | |
self.remove_days(7 * weeks) | |
""" | |
Description: Adds a given number of months to the stored date | |
months: int Number of months to be added. | |
""" | |
def add_months(self, months: int = 1): | |
current_month = self._original.month | |
current_year = self._original.year | |
additional_days = 0 | |
i = 0 | |
while i < months: | |
if current_month == 2 and DateTimeDelta.is_leap_year(current_year): | |
additional_days += MonthDays[current_month] + 1 | |
else: | |
additional_days += MonthDays[current_month] | |
if current_month == 12: | |
current_month = 1 | |
current_year += 1 | |
else: | |
current_month += 1 | |
i += 1 | |
self.add_days(additional_days) | |
""" | |
Description: Subtracts a given number of months to the stored date | |
months: int Number of months to be added. | |
""" | |
def remove_months(self, months: int = 1): | |
current_month = self._original.month | |
current_year = self._original.year | |
less_days = 0 | |
i = 0 | |
while i < months: | |
if current_month == 3 and DateTimeDelta.is_leap_year(current_year): | |
less_days += MonthDays[current_month - 1] + 1 | |
elif current_month == 1: | |
less_days += MonthDays[12] | |
else: | |
less_days += MonthDays[current_month - 1] | |
if current_month == 1: | |
current_month = 12 | |
current_year -= 1 | |
else: | |
current_month -= 1 | |
i += 1 | |
self.remove_days(less_days) | |
""" | |
Description: Adds a given number of years to the stored date | |
years: int Number of years to be added. | |
""" | |
def add_years(self, years: int = 1): | |
leap_year_count = 0 | |
i = 0 | |
while i < years: | |
""" | |
If the current month is greater than 2 the current year should be checked for a leap year | |
otherwise next year will be | |
""" | |
equivaliser = 0 | |
if self._original.month > 2: | |
equivaliser = 1 | |
if DateTimeDelta.is_leap_year(self._original.year + (i + equivaliser)): | |
leap_year_count += 1 | |
i += 1 | |
self.add_days((365 * years) + leap_year_count) | |
""" | |
Description: Subtracts a given number of years to the stored date | |
years: int Number of years to be added. | |
""" | |
def remove_years(self, years: int = 1): | |
leap_year_count = 0 | |
i = 0 | |
while i < years: | |
""" | |
If the current month is greater than 2 the current year should be checked for a leap year | |
otherwise previous year will be | |
""" | |
equivaliser = 1 | |
if self._original.month > 2: | |
equivaliser = 0 | |
if DateTimeDelta.is_leap_year(self._original.year - (i + equivaliser)): | |
leap_year_count += 1 | |
i += 1 | |
self.add_days((365 * years) + leap_year_count) | |
""" | |
Description: Calculates if a given year is a leap year taking into consideration | |
if the given year is a millennium. | |
year: int The year being checked. | |
Returns: bool True if a leap year otherwise false. | |
""" | |
@staticmethod | |
def is_leap_year(year: int) -> bool: | |
if (year % 4 == 0) and (year % 100 == 0): | |
return False | |
elif year % 4 == 0: | |
return True | |
return False | |
""" | |
Description: Getter for date. | |
Returns: datetime The date with additions and subtractions made | |
""" | |
@property | |
def date(self) -> datetime: | |
return datetime.fromtimestamp(self._epoch) | |
""" | |
Description: Setter for date. | |
date_time: datetime The year being checked. | |
""" | |
@date.setter | |
def date(self, date_time: datetime = datetime.now()): | |
self._epoch = date_time.timestamp() | |
self._original = date_time | |
""" | |
Description: Resets the calculated date to the original date passed t the object. | |
""" | |
def reset(self): | |
self._epoch = self._original.timestamp() | |
"""Usage""" | |
a_date = datetime(year=2020, month=3, day=27) | |
delta = DateTimeDelta(a_date) | |
delta.remove_years(4) | |
print(delta.date.isoformat()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment