#!/usr/bin/python3 import datetime import time from calendar import monthrange from dateutil.rrule import rrule, MONTHLY from dateutil.relativedelta import relativedelta def convert_date_str_to_datetime(date_str): res = datetime.date(int(date_str[0:4]), int(date_str[4:6]), int(date_str[6:8])) return res def get_full_month_str(date_from, date_to): # add one day (if last day of the month) date_to = date_to + relativedelta(days=+1) full_month = [dt for dt in rrule(MONTHLY, bymonthday=1,dtstart=date_from, until=date_to)] # remove last_month (incomplete) if len(full_month): full_month = full_month[:-1] return full_month def get_date_range_full_month_and_days(date_from, date_to): date_from = convert_date_str_to_datetime(date_from) date_to = convert_date_str_to_datetime(date_to) full_month = get_full_month_str(date_from, date_to) # request at least one month if full_month: day_list = substract_date(date_from.strftime('%Y%m%d'), full_month[0].strftime('%Y%m%d')) # remove last day (day in full moth) if day_list: day_list = day_list[:-1] day_list.extend(substract_date( (full_month[-1] + relativedelta(months=+1) ).strftime('%Y%m%d'), date_to.strftime('%Y%m%d'))) else: day_list = substract_date(date_from.strftime('%Y%m%d'), date_to.strftime('%Y%m%d')) full_month = [dt_month.strftime('%Y%m') for dt_month in full_month] return day_list, full_month # # TODO: refractor me class Date(object): """docstring for Date""" def __init__(self, *args): if len(args) == 3: self.year = str(args[0]) self.month = str(args[1]) self.day = str(args[2]).zfill(2) if len(args) == 1: self.year = str(args[0])[:4] self.month = str(args[0])[4:6] self.day = str(args[0])[6:] def __str__(self): return "{0}{1}{2}".format(self.year, self.month, self.day) def _get_year(self): return self.year def _get_month(self): return self.month def _get_day(self): return self.day def _set_year(self, year): self.year = year def _set_month(self, month): self.month = month def _set_day(self, day): self.day = day def substract_day(self, numDay): computed_date = datetime.date(int(self.year), int(self.month), int(self.day)) - datetime.timedelta(numDay) comp_year = str(computed_date.year) comp_month = str(computed_date.month).zfill(2) comp_day = str(computed_date.day).zfill(2) return comp_year + comp_month + comp_day def get_today_date_str(separator=False): if separator: return datetime.date.today().strftime("%Y/%m/%d") else: return datetime.date.today().strftime("%Y%m%d") def get_current_week_day(): dt = datetime.date.today() start = dt - datetime.timedelta(days=dt.weekday()) return start.strftime("%Y%m%d") def get_current_utc_full_time(): timestamp = datetime.datetime.fromtimestamp(time.time()) return timestamp.strftime('%Y-%m-%d %H:%M:%S') def get_month_dates(date=None): if date: date = convert_date_str_to_datetime(date) else: date = datetime.date.today() num_days = monthrange(date.year, date.month)[1] return [datetime.date(date.year, date.month, day).strftime("%Y%m%d") for day in range(1, num_days+1)] def get_date_week_by_date(date): dt = datetime.date(int(date[0:4]), int(date[4:6]), int(date[6:8])) start = dt - datetime.timedelta(days=dt.weekday()) return start.strftime("%Y%m%d") def date_add_day(date, num_day=1): new_date = datetime.date(int(date[0:4]), int(date[4:6]), int(date[6:8])) + datetime.timedelta(num_day) new_date = str(new_date).replace('-', '') return new_date def daterange_add_days(date, nb_days): end_date = date_add_day(date, num_day=nb_days) return get_daterange(date, end_date) def date_substract_day(date, num_day=1): new_date = datetime.date(int(date[0:4]), int(date[4:6]), int(date[6:8])) - datetime.timedelta(num_day) new_date = str(new_date).replace('-', '') return new_date # # TODO: remove me ## FIXME: def get_date_range(num_day): curr_date = datetime.date.today() date = Date(str(curr_date.year)+str(curr_date.month).zfill(2)+str(curr_date.day).zfill(2)) date_list = [] for i in range(0, num_day+1): date_list.append(date.substract_day(i)) return list(reversed(date_list)) def get_previous_date_list(num_day): curr_date = datetime.date.today() date = Date(str(curr_date.year)+str(curr_date.month).zfill(2)+str(curr_date.day).zfill(2)) date_list = [] for i in range(0, num_day+1): date_list.append(date.substract_day(i)) return list(reversed(date_list)) def get_nb_days_by_daterange(date_from, date_to): date_from = datetime.date(int(date_from[0:4]), int(date_from[4:6]), int(date_from[6:8])) date_to = datetime.date(int(date_to[0:4]), int(date_to[4:6]), int(date_to[6:8])) delta = date_to - date_from # timedelta return len(range(delta.days + 1)) def get_date_range_today(date_from): return substract_date(date_from, get_today_date_str()) def substract_date(date_from, date_to): date_from = datetime.date(int(date_from[0:4]), int(date_from[4:6]), int(date_from[6:8])) date_to = datetime.date(int(date_to[0:4]), int(date_to[4:6]), int(date_to[6:8])) delta = date_to - date_from # timedelta l_date = [] for i in range(delta.days + 1): date = date_from + datetime.timedelta(i) l_date.append( date.strftime('%Y%m%d') ) return l_date def get_daterange(date_from, date_to): date_from = datetime.date(int(date_from[0:4]), int(date_from[4:6]), int(date_from[6:8])) date_to = datetime.date(int(date_to[0:4]), int(date_to[4:6]), int(date_to[6:8])) delta = date_to - date_from # timedelta l_date = [] for i in range(delta.days + 1): date = date_from + datetime.timedelta(i) l_date.append(date.strftime('%Y%m%d')) return l_date def validate_str_date(str_date, separator=''): try: datetime.datetime.strptime(str_date, '%Y{}%m{}%d'.format(separator, separator)) return True except ValueError: return False except TypeError: return False def api_validate_str_date_range(date_from, date_to, separator=''): is_date = validate_str_date(date_from, separator=separator) and validate_str_date(date_from, separator=separator) if not is_date: return ({"status": "error", "reason": "Invalid Date"}, 400) if int(date_from) > int(date_to): return ({"status": "error", "reason": "Invalid Date range, Date from > Date to"}, 400) def sanitise_date_range(date_from, date_to, separator='', date_type='str'): ''' Check/Return a correct date_form and date_to ''' if not date_from and date_to: date_from = date_to elif not date_to and date_from: date_to = date_from elif not date_to and not date_from: date = datetime.date.today().strftime("%Y%m%d") return {"date_from": date, "date_to": date} if date_type=='str': # remove separators if len(date_from) == 10: date_from = date_from[0:4] + date_from[5:7] + date_from[8:10] if len(date_to) == 10: date_to = date_to[0:4] + date_to[5:7] + date_to[8:10] if not validate_str_date(date_from, separator=separator): date_from = datetime.date.today().strftime("%Y%m%d") if not validate_str_date(date_to, separator=separator): date_to = datetime.date.today().strftime("%Y%m%d") else: # datetime if isinstance(date_from, datetime.datetime): date_from = date_from.strftime("%Y%m%d") else: date_from = datetime.date.today().strftime("%Y%m%d") if isinstance(date_to, datetime.datetime): date_to = date_to.strftime("%Y%m%d") else: date_to = datetime.date.today().strftime("%Y%m%d") if int(date_from) > int(date_to): res = date_from date_from = date_to date_to = res return {"date_from": date_from, "date_to": date_to} def sanitise_daterange(date_from, date_to, separator='', date_type='str'): ''' Check/Return a correct date_form and date_to ''' if not date_from and date_to: date_from = date_to elif not date_to and date_from: date_to = date_from elif not date_to and not date_from: date = datetime.date.today().strftime("%Y%m%d") return date, date if date_type == 'str': # remove separators if len(date_from) == 10: date_from = date_from[0:4] + date_from[5:7] + date_from[8:10] if len(date_to) == 10: date_to = date_to[0:4] + date_to[5:7] + date_to[8:10] if not validate_str_date(date_from, separator=separator): date_from = datetime.date.today().strftime("%Y%m%d") if not validate_str_date(date_to, separator=separator): date_to = datetime.date.today().strftime("%Y%m%d") else: # datetime if isinstance(date_from, datetime.datetime): date_from = date_from.strftime("%Y%m%d") else: date_from = datetime.date.today().strftime("%Y%m%d") if isinstance(date_to, datetime.datetime): date_to = date_to.strftime("%Y%m%d") else: date_to = datetime.date.today().strftime("%Y%m%d") if int(date_from) > int(date_to): res = date_from date_from = date_to date_to = res return date_from, date_to