# functions related to Date-fields # ----------------------------------------------------- """ additionally functions for calculating date with formulas like [DATE+2M] and for comparison of date related on two reference-dates """ import datetime #from dateutil.relativedelta import relativedelta import re import utils.data_const as D F_DIR = "%Y-%m-%d_%H-%M-%S" F_DB_DATE = "%Y-%m-%d" F_DE = "%d.%m.%Y" F_N8 = "%Y%m%d" F_LOG = "%Y%m%d_%H%M%S" MONTH_EN = ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"] MONTH_DE = ["jan", "feb", "mar", "apr", "mai", "jun", "jul", "aug", "sep", "okt", "nov", "dez"] def getActdate(format): return getFormatdate(datetime.datetime.now(), format) def getFormatdate(date, format): """ it return the date as string in the format """ return date.strftime(format) def getFormatDatetupel(dtupel, format): """ it return the date as string in the format """ if format == F_N8: return f'{dtupel[0]:04}'+f'{dtupel[1]:02}'+f'{dtupel[2]:02}' return getFormatdate(datetime.datetime(dtupel[0], dtupel[1], dtupel[2], dtupel[3], dtupel[4], dtupel[5]) ,format) def formatParsedDate(instring, format): dtupel = parseDate(instring) print ("---------------"+str(dtupel)) return getFormatDatetupel(dtupel, format) def parseFormula(instring): """ the function parses the string as a formula. In the formula the input-date - actdate or explicite date - will be added resp. subtracted with years, months or dates which are specified in the formula. The structure of the formula: DATE +/- mY +/-nM +/-qD :param instring: :return: """ instring = instring.upper() if instring[2:6] == "DATE": refdate = datetime.datetime.today() formula = instring[7:-2].upper() else: dstring = instring[2:instring.find(" ")] res = parseDate(dstring) refdate = datetime.datetime(res[0], res[1], res[2], res[3], res[4], res[5]) formula = instring[2+len(dstring):-2] formula = re.sub(r' ', '', formula) year = refdate.year mon = refdate.month day = refdate.day hour = refdate.hour min = refdate.minute sec = refdate.second if re.match(r"[-+]\d+[JYMDT]", formula): ress = re.compile(r"([-+])(\d+)([JYMDT])") for res in ress.finditer(formula): summand = int(res.group(2)) if res.group(1) == "-": summand = summand * (-1) if res.group(3) in "JY": year = year + summand if res.group(3) in "M": mon = mon + summand while mon <= 0: mon = mon + 12 year = year - 1 while mon > 12: mon = mon - 12 year = year + 1 if res.group(3) in "DT": refdate = datetime.datetime(year, mon, day, hour, min, sec) refdate = refdate + datetime.timedelta(days=summand) year = refdate.year mon = refdate.month day = refdate.day hour = refdate.hour min = refdate.minute sec = refdate.second return (year, mon, day, hour, min, sec) else: print("re matcht nicht") return (year, mon, day, hour, min, sec) def getMonthInt(instring): i = 0 j = 0 for l in [MONTH_EN, MONTH_DE]: i = 0 for m in l: i += 1 if instring.lower() == m: j = i break if j > 0: break return j def parseDate(instring): """ the function parses the string as a date or timestamp which is formed in one of the typical formates :param the string to be parse: :return timestamp as tupel (y, m, d, H, M ,S): """ year = 0 mon = 0 day = 0 hour = 0 min = 0 sec = 0 print(instring) if instring[0:2] == "{(" and instring[-2:] == ")}": return parseFormula(instring) if re.match(r"\d{8}_\d{6}", instring): year = int(instring[0:4]) mon = int(instring[4:6]) day = int(instring[6:8]) hour = int(instring[9:11]) min = int(instring[11:13]) sec = int(instring[13:]) return (year, mon, day, hour, min, sec) if len(instring) > 8: for d in ["_", " "]: if d in instring and instring.find(d) > 8: dstring = instring[0:instring.find(d)] tstring = instring[instring.find(d)+1:] dres = parseDate(dstring) tres = parseDate(tstring) return (dres[0], dres[1], dres[2], tres[3], tres[4], tres[5]) if re.match(r"\d{4}[-./]\d{2}[-./]\d{2}", instring): res = re.match(r"(\d{4})[-./](\d{2})[-./](\d{2})", instring) year = int(res.group(1)) mon = int(res.group(2)) day = int(res.group(3)) return (year, mon, day, hour, min, sec) if re.match(r"\d{1,2}[-./]\d{1,2}[-./]\d{4}", instring): res = re.match(r"(\d{1,2})[-./](\d{1,2})[-./](\d{4})", instring) year = int(res.group(3)) mon = int(res.group(2)) day = int(res.group(1)) return (year, mon, day, hour, min, sec) if re.match(r"\w{3} \w{3} \d{1,2} \d{1,2}[:]\d{1,2}[:]\d{2} \d{4}", instring.strip()): res = re.search(r"\w{3} (\w{3}) (\d{1,2}) (\d{1,2})[:](\d{1,2})[:](\d{2}) (\d{4})", instring.strip()) month = res.group(1) mon = getMonthInt(month) day = int(res.group(2)) hour = int(res.group(3)) min = int(res.group(4)) sec = int(res.group(5)) year = int(res.group(6)) return (year, mon, day, hour, min, sec) if re.match(r"\d{8}", instring): year = instring[0:4] mon = instring[4:6] day = instring[6:8] return (year, mon, day, hour, min, sec) if re.match(r"\d{2}[-:]\d{2}[-:/]\d{2}", instring): res = re.match(r"(\d{2})[-:/](\d{2})[-:/](\d{2})", instring) hour = int(res.group(1)) min = int(res.group(2)) sec = int(res.group(3)) return (year, mon, day, hour, min, sec) return (year, mon, day, hour, min, sec)