XZise added a comment.
Okay here is one flexible solution which does work with any month length and any number of months (> 1) in a year:
``` def month_delta(date, month_delta=1): if int(month_delta) != month_delta: raise ValueError('Month delta must be an integer') delta = -1 if month_delta < 0 else +1 month = date.month target_day = date.day while date.day != target_day or month_delta != 0: date += datetime.timedelta(days=delta) if date.month != month: # month number has changed month_delta -= delta month = date.month return date ```
It's basically adding or removing one day and checks if the month number changes. If that is the case it reduces the number of months by one until no delta is left. Then it checks if the day number is equal to the original day number and stops if that is the case.
You could speed that up if you rely on the fact a month has at least N days and a year has always M months:
``` min_day_per_month = 28 months_per_year = 12 def month_delta2(date, month_delta=1): if int(month_delta) != month_delta: raise ValueError('Month delta must be an integer') delta = -1 if month_delta < 0 else +1 new_date = date + datetime.timedelta(days=min_day_per_month * month_delta) # figure out how many months have been skipped month_delta -= (new_date.year - date.year) * months_per_year - date.month + new_date.month month = new_date.month while new_date.day != date.day or month_delta != 0: new_date += datetime.timedelta(days=delta) if new_date.month != month: # month number has changed month_delta -= delta month = new_date.month import time; time.sleep(2) return new_date ```
This already skips "month_delta * N" days, so you only need to add a few (`<= |4*month_delta|`).
TASK DETAIL https://phabricator.wikimedia.org/T73124
REPLY HANDLER ACTIONS Reply to comment or attach files, or !close, !claim, !unsubscribe or !assign <username>.
To: XZise Cc: pywikipedia-bugs, Legoktm, jayvdb, XZise, Multichill, Xqt