1. Guido Draheim
  2. trac-userscriptservernotes-plugin

Source

trac-userscriptservernotes-plugin / src / usernotes / parsedate.py

# -*- encoding: utf-8 -*-

def _RelativeDays(weekday):
    if weekday == "heute": return 0
    if weekday == "Heute": return 0
    if weekday == "gestern": return 1
    if weekday == "Gestern": return 1
    if weekday == "vorgestern": return 2
    if weekday == "Vorgestern": return 2
    return None

def _WeekdayToNumber(weekday):
    # python datetime.weekday() "Monday is 0 and Sunday is 6."
    if weekday == "Montag": return 0;
    if weekday == "Dienstag": return 1;
    if weekday == "Mittwoch": return 2;
    if weekday == "Donnerstag": return 3;
    if weekday == "Freitag": return 4;
    if weekday == "Samstag": return 5;
    if weekday == "Sonntag": return 6;
    return -1

def _DaysInMonth(month):
    if month == 1: return 31;
    if month == 2: return 29;
    if month == 3: return 31;
    if month == 4: return 30;
    if month == 5: return 31;
    if month == 6: return 30;
    if month == 7: return 31;
    if month == 8: return 31;
    if month == 9: return 30;
    if month == 10: return 31;
    if month == 11: return 30;
    if month == 12: return 31;
    return 0;

def _MonthnameToMonth(month):
    if month == "Januar": return 1;
    if month == "Februar": return 2;
    if month == "März": return 3;
    if month == "April": return 4;
    if month == "Mai": return 5;
    if month == "Juni": return 6;
    if month == "Juli": return 7;
    if month == "August": return 8;
    if month == "September": return 9;
    if month == "Oktober": return 10;
    if month == "November": return 11;
    if month == "Dezember": return 12;
    return 0;

import re

class _P:
    def __init__(self, pattern):
        self.re = re.compile(pattern)
    def match(self, value):
        return self.re.match(value)
    

_A = _P(r"\s*([0-9]+)[.]([0-9]+)[.]([0-9]+),*(?:\s+um)?\s+([0-9]+):([0-9]+)\s+Uhr")
_A.names = ["%d","%m","%Y","%H","%M"]
_B = _P(r"\s*vor\s+(\d+)\s+(Std|Min).*")
_B.names = ["tt","xx"]
_B1 = _P(r"\s*vor\s+(\d+)\s+(Min|Minuten?).*")
_B1.names = ["-M","L"]
_B1.clear = [ "%S" ]
_B2 = _P(r"\s*vor\s+(\d+)\s+(Std|Stunden?).*")
_B2.names = ["-H","L"]
_B2.clear = [ "%M" ]
_B3 = _P(r"\s*vor\s+(\d+)\s+(Tag|Tagen).*")
_B3.names = ["-d","L"]
_B3.clear = [ "%H" ]
_C = _P(r"\s*([0-9]+)[.]\s*(Januar|Februar|März|April|Mai|Juni|Juli|August|September|Oktober|November|Dezember)\s([0-9]+),*(?:\s+um)?\s+([0-9]+):([0-9]+)(?: Uhr)?")
_C.names = ["%d","mm","%Y","%H","%M"]
_C2 = _P(r"\s*([0-9]+)[.]\s*(Januar|Februar|März|April|Mai|Juni|Juli|August|September|Oktober|November|Dezember),*(?:\s+um)?\s+([0-9]+):([0-9]+)(?: Uhr)?")
_C2.names = ["%d","mm","%H","%M"]
_D = _P(r"\s*(heute|Heute|gestern|Gestern|vorgestern|Vorgestern),*(?:\s+um)?\s+([0-9]+):([0-9]+)(?:\sUhr)?")
_D.names = ["ww","%H","%M"]
_E = _P(r"\s*(Montag|Dienstag|Mittwoch|Donnerstag|Freitag|Samstag|Sonntag),(?:\s+um)?\s+([0-9]+):([0-9]+)(?:\s*Uhr)?")
_E.names = ["%w","%H","%M"]
_F = _P(r"(\d+)-(\d+)-(\d+)[.T ](\d+):(\d+)")
_F.names = ["%Y","%m","%d","%H","%M"]
_V = _P(r"(vor einigen Sekunden)")
_V.names = ["--"]
_X = _P(r"(now|jetzt)")
_X.names = ["--"]

import datetime

NOW = None
def now():
    if NOW is not None:
        return NOW
    return datetime.datetime.now()

class DatestringFromFormattedDate:
    def __init__(self, value = None):
        self.date = now()
        self.patterns = [ _A, _B1, _B2, _B3, _C, _C2, _D, _E, _F, _V, _X]
        if value is not None:
            self.parse(value)
    def __str__(self):
        return self.date.strftime("%Y%m%d%H%M")
    def parse(self, value):
        for pattern in self.patterns:
            m = pattern.match(value)
            if m:
                self.clear(getattr(pattern, "clear", ["%S"]))
                self.set(zip(pattern.names, m.groups()))
                return self.__str__()
        return None
    def clear(self, clear):
        for name in clear:
            if name in [ "%S"]:
                self.date = self.date.replace(second = 0, microsecond = 0)
            if name in [ "%M" ]:
                self.date = self.date.replace(minute = 0, second = 0, microsecond = 0)
            if name in [ "%H" ]:
                self.date = self.date.replace(hour = 0, minute = 0, second = 0, microsecond = 0)
    def set(self, values):
        for name, val in values:
            if name in [ "%Y" ]:
                self.date = self.date.replace(year = int(val))
            if name in [ "%m" ]:
                self.date = self.date.replace(month = int(val))
            if name in [ "%d" ]:
                self.date = self.date.replace(day = int(val))
            if name in [ "%H" ]:
                self.date = self.date.replace(hour = int(val))
            if name in [ "%M" ]:
                self.date = self.date.replace(minute = int(val))
            if name in [ "%S" ]:
                self.date = self.date.replace(second = int(val))
            if name in [ "mm" ]:
                self.date = self.date.replace(month = _MonthnameToMonth(val))
            if name in [ "%w" ]:
                weekday = self.date.weekday()
                w = _WeekdayToNumber(val)
                diff = weekday - w
                if diff <= 0:
                    diff += 7
                self.date = self.date - datetime.timedelta(days = diff)
            if name in [ "ww" ]:
                d = _RelativeDays(val)
                if d:
                    self.date = self.date - datetime.timedelta(days = d)
            if name in [ "-H" ]:
                d = int(val)
                if d:
                    self.date = self.date - datetime.timedelta(hours = d)
            if name in [ "-M" ]:
                d = int(val)
                if d:
                    self.date = self.date - datetime.timedelta(minutes = d)
            if name in [ "-d" ]:
                d = int(val)
                if d:
                    self.date = self.date - datetime.timedelta(days = d)
                
                
    

def _DatestringFromFormattedDate(check):
    founds = _A.match(check)
    if founds:
        found = [ founds.group(0) ] + list(founds.groups())
        return found[3]+found[2]+found[1]+found[4]+found[5];
    founds = _B.match(check)
    if founds:
        found = [ founds.group(0) ] + list(founds.groups())
        date = now()
        offset = int(found[1]);
        y, m, d = (date.year, date.month, date.day)
        H, M = (date.hour, date.minute)
        if found[2] == "Min": M -= offset
        if found[2] == "Std": H -= offset
        while M < 0: 
            M += 60; H -= 1
        if H < 0:
            H = 0; M = 0;
        return "%04i%02i%02i%02i%02i" % (y,m,d,H,M)
    founds = _C.match(check)
    if founds:
        found = [ founds.group(0) ] + list(founds.groups())
        date = now()
        w = date.weekday() # as number 0...6
        y = int(found[3])
        m = date.month;
        d = int(found[1])
        month = _MonthnameToMonth(found[2]);
        if month:
            if month > m: y -= 1
            m = month
        H = int(found[4])
        M = int(found[5])
        return "%04i%02i%02i%02i%02i" % (y,m,d,H,M)
    founds = _D.match(check)
    if founds:
        found = [ founds.group(0) ] + list(founds.groups())
        date = now()
        w = date.weekday() # as number 0...6
        y, m, d = (date.year, date.month, date.day)
        if found[1] in [ "heute", "Heute"]: 
            d -= 0
        if found[1] in [ "gestern", "Gestern"]: 
            d -= 1
        while d <= 0:  
            m -= 1; d += _DaysInMonth(m)
        while m <= 0: 
            y -= 1; m += 12
        H = int(found[2])
        M = int(found[3])
        return "%04i%02i%02i%02i%02i" % (y,m,d,H,M)
    founds = _E.match(check)
    if founds:
        found = [ founds.group(0) ] + list(founds.groups())
        date = now()
        w = date.weekday() # as number 0...6
        y, m, d = (date.year, date.month, date.day)
        weekday = _WeekdayToNumber(found[1])
        if weekday >= 0:
            diff = weekday - w
            if diff > 0: 
                diff = diff - 7
            d = d + diff;
            while d <= 0:
                m -= 1; d += _DaysInMonth(m)
            while m <= 0: 
                y -= 1; m += 12
            H = int(found[2])
            M = int(found[3])
        return "%04i%02i%02i%02i%02i" % (y,m,d,H,M)
    date = now()
    y, m, d = (date.year, date.month, date.day)
    return "%04i%02i%02i (FEHLER: %s)" %(y,m,d,check)

def parsedate1(check):
    """  returns a string representation !! 
         So, if the format is not recognized then
         it just returns what it got.
    """
    if check and " " in check:
        return _DatestringFromFormattedDate(check)
    return check

def parsedate2(check):
    """  returns a string representation !! 
         So, if the format is not recognized then
         it just returns what it got.
    """
    if check and " " in check:
        return str(DatestringFromFormattedDate(check))
    return check

def parse(check):
    """  returns a string representation !! 
         So, if the format is not recognized then
         it just returns what it got.
    """
    return DatestringFromFormattedDate().parse(check)

def parse_datetime(check):
    """  returns a string representation !! 
         So, if the format is not recognized then
         it just returns what it got.
    """
    work = DatestringFromFormattedDate()
    if not work.parse(check):
        return None
    return work.date


def parsedate(check):
    return parsedate2(check)