import datetime import arrow def diff_month(d1, d2): return (d1.year - d2.year) * 12 + d1.month - d2.month def calc_current_period(start_date, period, now=None, unit='months'): now = now or datetime.datetime.now() now = arrow.get(now) if unit == 'months': if now.day < start_date.day: now = now.shift(months=-1) start_date = arrow.get(start_date) remainder = diff_month(now, start_date) % period current_start_date = now.shift(months=-remainder).replace(day=start_date.day) current_end_date = now.shift(months=period - remainder).replace(day=start_date.day) return current_start_date.date(), current_end_date.date() elif unit == 'days': start_date = arrow.get(start_date) remainder = (now - start_date).days % period current_start_date = now.shift(days=-remainder) current_end_date = now.shift(days=period - remainder) return current_start_date.date(), current_end_date.date() else: raise ValueError # now 2.6 class NewDateTime(datetime.datetime): @classmethod def now(cls, tz=None): return cls(2018, 2, 6) datetime.datetime = NewDateTime assert calc_current_period(datetime.datetime(2018, 2, 7), 1) == (datetime.date(2018, 1, 7), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 2, 6), 1) == (datetime.date(2018, 2, 6), datetime.date(2018, 3, 6)) assert calc_current_period(datetime.datetime(2018, 2, 5), 1) == (datetime.date(2018, 2, 5), datetime.date(2018, 3, 5)) assert calc_current_period(datetime.datetime(2018, 2, 7), 2) == (datetime.date(2017, 12, 7), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 2, 6), 2) == (datetime.date(2018, 2, 6), datetime.date(2018, 4, 6)) assert calc_current_period(datetime.datetime(2018, 2, 5), 2) == (datetime.date(2018, 2, 5), datetime.date(2018, 4, 5)) assert calc_current_period(datetime.datetime(2018, 1, 7), 1) == (datetime.date(2018, 1, 7), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 1, 6), 1) == (datetime.date(2018, 2, 6), datetime.date(2018, 3, 6)) assert calc_current_period(datetime.datetime(2018, 1, 5), 1) == (datetime.date(2018, 2, 5), datetime.date(2018, 3, 5)) assert calc_current_period(datetime.datetime(2018, 1, 7), 2) == (datetime.date(2018, 1, 7), datetime.date(2018, 3, 7)) assert calc_current_period(datetime.datetime(2018, 1, 6), 2) == (datetime.date(2018, 1, 6), datetime.date(2018, 3, 6)) assert calc_current_period(datetime.datetime(2018, 1, 5), 2) == (datetime.date(2018, 1, 5), datetime.date(2018, 3, 5)) assert calc_current_period(datetime.datetime(2018, 3, 7), 2) == (datetime.date(2018, 1, 7), datetime.date(2018, 3, 7)) assert calc_current_period(datetime.datetime(2018, 3, 6), 2) == (datetime.date(2018, 1, 6), datetime.date(2018, 3, 6)) assert calc_current_period(datetime.datetime(2018, 3, 5), 2) == (datetime.date(2018, 1, 5), datetime.date(2018, 3, 5)) assert calc_current_period(datetime.datetime(2018, 2, 6), 1, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 2, 5), 1, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 2, 7), 1, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 1, 6), 1, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 1, 5), 1, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 1, 7), 1, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 3, 6), 1, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 3, 5), 1, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 3, 7), 1, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 2, 6), 2, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 8)) assert calc_current_period(datetime.datetime(2018, 2, 5), 2, unit='days') == ( datetime.date(2018, 2, 5), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 2, 7), 2, unit='days') == ( datetime.date(2018, 2, 5), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 1, 6), 2, unit='days') == ( datetime.date(2018, 2, 5), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 1, 5), 2, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 8)) assert calc_current_period(datetime.datetime(2018, 1, 7), 2, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 8)) assert calc_current_period(datetime.datetime(2018, 3, 6), 2, unit='days') == ( datetime.date(2018, 2, 6), datetime.date(2018, 2, 8)) assert calc_current_period(datetime.datetime(2018, 3, 5), 2, unit='days') == ( datetime.date(2018, 2, 5), datetime.date(2018, 2, 7)) assert calc_current_period(datetime.datetime(2018, 3, 7), 2, unit='days') == ( datetime.date(2018, 2, 5), datetime.date(2018, 2, 7))