Skip to content

Instantly share code, notes, and snippets.

@petermcd
Last active December 27, 2018 00:41
Show Gist options
  • Save petermcd/60132535abb474fe2c99294a04b7dcf6 to your computer and use it in GitHub Desktop.
Save petermcd/60132535abb474fe2c99294a04b7dcf6 to your computer and use it in GitHub Desktop.
Adding days, weeks, months or years to a datetime
"""
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