Ejemplo n.º 1
0
def decodeOneDate(datestr, workdate=None, months=None, days=None, quarters=None, locale=None, isEndPeriod=False):
    """Parse a string representing a date or a period. Return ``datetime.date``
    or ``tuple(year,month)`` or ``None``
    
    :param datestr: the string to be interpreted
    :param workdate: the :ref:`workdate`
    :param months: names of months according to locale (just for caching)
    :param days: names of weekdays according to locale (just for caching)
    :param quarters: names of quarters according to locale (just for caching)
    :param locale: the current locale (e.g: en, en_us, it)
    :param isEndPeriod: if the string represents a period, return the end date
                        (default return the start date)
    
    Special keywords like ``today`` or the name of a month can be translated in all languages
    and support synonimous. (e.g: this month; e.g: month)
    
    The input string can be:
    
    * a year: e.g. 2007 or 07
    * today, yesterday, tomorrow (can be translated in all languages)
        * you can specify a number of days to add to today: e.g. 'today + 3' or 'today - 15'
    * this week, next week, last week (can be translated in all languages)
    * this month, next month, last month (can be translated in all languages )
        * can be specified a number of months to add to current month: e.g. 'this month + 3' or 'this month - 24'
    * the name of a quarter: e.g. Q1 or 1st quarter
    * the name of a month: e.g. april or apr
        * can be specified a year after the month: e.g. apr 07 or april 2007
        * returns a tuple (year, month): if year is not specified in datestr, year is returned None
    * the name of a weekday: e.g. monday or mon
        * the date returned is the date of the given weekday in this week (relative to workdate)
    * an iso date: e.g. 2008-04-28
    * a date formatted according to locale (see babel doc): e.g. 4 28, 2008 (en_us) or 28-4-08 (it)
                           various separators are admitted: 28-4-08, 28/4/08, 28 4 08"""
    
    def addToDay(datestr, date):
        if '+' in datestr:
            days = int(datestr.split('+')[1].strip())
            return date + datetime.timedelta(days)
        if '-' in datestr:
            days = int(datestr.split('-')[1].strip())
            return date - datetime.timedelta(days)
        return date

    def addToMonth(datestr, date, addmonth=0):#l'errore è nel chiamate che passa addmonth sbagliato
        delta=0
        if '+' in datestr:
            delta =  int(datestr.split('+')[1].strip())
        if '-' in datestr:
            delta = -int(datestr.split('-')[1].strip())
        month = date.month + addmonth+ delta
        year = date.year
        while month <= 0:
            month = month + 12
            year = year - 1
        while month > 12:
            month = month - 12
            year = year + 1
        return datetime.date(year, month, 1)
        
    datestr = datestr or ''
    datestr = datestr.strip()
    if datestr:
        months = months or gnrlocale.getMonthNames(locale)
        def_months = gnrlocale.getMonthNames(DEFAULT_LOCALE)
        days = days or gnrlocale.getDayNames(locale)
        def_days = gnrlocale.getDayNames(DEFAULT_LOCALE)
        quarters = quarters or gnrlocale.getQuarterNames(locale)
        def_quarters = gnrlocale.getQuarterNames(DEFAULT_LOCALE)
        dateStart = None
        dateEnd = None
        workdate = workdate or datetime.date.today()
        
        if datestr.isdigit() and len(datestr) in (2, 4):                          # a full year
            year = yearDecode(datestr)
            dateStart = datetime.date(year, 1, 1)
            if isEndPeriod:
                dateEnd = datetime.date(year, 12, 31)
                
        elif checkDateKeywords('today', datestr, locale):     # today
            dateStart = addToDay(datestr, workdate)
        elif checkDateKeywords('yesterday', datestr, locale): # yesterday
            dateStart = addToDay(datestr, workdate - datetime.timedelta(1))
        elif checkDateKeywords('tomorrow', datestr, locale):  # tomorrow
            dateStart = addToDay(datestr, workdate + datetime.timedelta(1))

        elif checkDateKeywords(('this week', 'next week', 'last week'), datestr, locale): # relative week
            j = workdate.weekday()
            dateStart = workdate - datetime.timedelta(j)
            if checkDateKeywords('last week', datestr, locale):
                dateStart = dateStart - datetime.timedelta(7)
            elif checkDateKeywords('next week', datestr, locale):
                dateStart = dateStart + datetime.timedelta(7)
            if '+' in datestr:
                 dateStart = dateStart + datetime.timedelta(7*int(datestr.split('+')[1]))
            if '-' in datestr:
                 dateStart = dateStart - datetime.timedelta(7*int(datestr.split('-')[1]))
            if isEndPeriod:
                dateEnd = dateStart + datetime.timedelta(6)
        elif checkDateKeywords(('this month', 'next month', 'last month'), datestr, locale): # relative month
            if checkDateKeywords('last month', datestr, locale):  
                dateStart = addToMonth(datestr, workdate, -1)
            elif checkDateKeywords('next month', datestr, locale):
                dateStart = addToMonth(datestr, workdate, 1)
            else:
                dateStart = addToMonth(datestr, workdate)
            if isEndPeriod:
                dateEnd = monthEnd(date=dateStart)
        elif anyWordIn(quarters.keys(), datestr): # quarter
            qt, year = splitAndStrip(datestr, sep=' ', n=1, fixed=2)
            year = yearDecode(year)
            qt = quarters[datestr]
            dateStart = (year, qt * 3 - 2)
            if isEndPeriod:
                dateEnd = (year, qt * 3)
        elif anyWordIn(def_quarters.keys(), datestr): # quarter
            qt, year = splitAndStrip(datestr, sep=' ', n=1, fixed=2)
            year = yearDecode(year)
            qt = def_quarters[datestr]
            dateStart = (year, qt * 3 - 2)
            if isEndPeriod:
                dateEnd = (year, qt * 3)
        elif anyWordIn(months.keys(), datestr):                                 # month name
            month, year = splitAndStrip(datestr, sep=' ', n=1, fixed=2)
            year = yearDecode(year)
            month = months[month]
            dateStart = (year, month)
        elif anyWordIn(def_months.keys(), datestr):                                 # month name
            month, year = splitAndStrip(datestr, sep=' ', n=1, fixed=2)
            year = yearDecode(year)
            month = def_months[month]
            dateStart = (year, month)
        elif datestr in days:                                                   # weekday name
            dateStart = workdate + datetime.timedelta(days[datestr] - workdate.weekday())
        elif datestr in def_days:                                                   # weekday name
            dateStart = workdate + datetime.timedelta(def_days[datestr] - workdate.weekday())
        elif re.match('\d{4}-\d{2}-\d{2}', datestr):                            # ISO date
            date_items = [int(el) for el in wordSplit(datestr)[0:3]]
            dateStart = datetime.date(*[int(el) for el in wordSplit(datestr)[0:3]])
        else:                                                                   # a date in local format
            dateStart = gnrlocale.parselocal(datestr, datetime.date, locale)
        if isEndPeriod and dateEnd:
            return dateEnd
        else:
            return dateStart
Ejemplo n.º 2
0
def decodeOneDate(datestr, workdate=None, months=None, days=None, quarters=None, locale=None, isEndPeriod=False):
    """Parse a string representing a date or a period. Return ``datetime.date``
    or ``tuple(year,month)`` or ``None``
    
    :param datestr: the string to be interpreted
    :param workdate: the :ref:`workdate`
    :param months: names of months according to locale (just for caching)
    :param days: names of weekdays according to locale (just for caching)
    :param quarters: names of quarters according to locale (just for caching)
    :param locale: the current locale (e.g: en, en_us, it)
    :param isEndPeriod: if the string represents a period, return the end date
                        (default return the start date)
    
    Special keywords like ``today`` or the name of a month can be translated in all languages
    and support synonimous. (e.g: this month; e.g: month)
    
    The input string can be:
    
    * a year: e.g. 2007 or 07
    * today, yesterday, tomorrow (can be translated in all languages)
        * you can specify a number of days to add to today: e.g. 'today + 3' or 'today - 15'
    * this week, next week, last week (can be translated in all languages)
    * this month, next month, last month (can be translated in all languages )
        * can be specified a number of months to add to current month: e.g. 'this month + 3' or 'this month - 24'
    * the name of a quarter: e.g. Q1 or 1st quarter
    * the name of a month: e.g. april or apr
        * can be specified a year after the month: e.g. apr 07 or april 2007
        * returns a tuple (year, month): if year is not specified in datestr, year is returned None
    * the name of a weekday: e.g. monday or mon
        * the date returned is the date of the given weekday in this week (relative to workdate)
    * an iso date: e.g. 2008-04-28
    * a date formatted according to locale (see babel doc): e.g. 4 28, 2008 (en_us) or 28-4-08 (it)
                           various separators are admitted: 28-4-08, 28/4/08, 28 4 08"""
    
    def addToDay(datestr, date):
        if '+' in datestr:
            days = int(datestr.split('+')[1].strip())
            return date + datetime.timedelta(days)
        if '-' in datestr:
            days = int(datestr.split('-')[1].strip())
            return date - datetime.timedelta(days)
        return date

    def addToMonth(datestr, date, addmonth=0):#l'errore è nel chiamate che passa addmonth sbagliato
        delta=0
        if '+' in datestr:
            delta =  int(datestr.split('+')[1].strip())
        if '-' in datestr:
            delta = -int(datestr.split('-')[1].strip())
        month = date.month + addmonth+ delta
        year = date.year
        while month <= 0:
            month = month + 12
            year = year - 1
        while month > 12:
            month = month - 12
            year = year + 1
        return datetime.date(year, month, 1)
        
    datestr = datestr or ''
    datestr = datestr.strip()
    if datestr:
        months = months or gnrlocale.getMonthNames(locale)
        def_months = gnrlocale.getMonthNames(DEFAULT_LOCALE)
        days = days or gnrlocale.getDayNames(locale)
        def_days = gnrlocale.getDayNames(DEFAULT_LOCALE)
        quarters = quarters or gnrlocale.getQuarterNames(locale)
        def_quarters = gnrlocale.getQuarterNames(DEFAULT_LOCALE)
        dateStart = None
        dateEnd = None
        workdate = workdate or datetime.date.today()
        
        if datestr.isdigit() and len(datestr) in (2, 4):                          # a full year
            year = yearDecode(datestr)
            dateStart = datetime.date(year, 1, 1)
            if isEndPeriod:
                dateEnd = datetime.date(year, 12, 31)
                
        elif checkDateKeywords('today', datestr, locale):     # today
            dateStart = addToDay(datestr, workdate)
        elif checkDateKeywords('yesterday', datestr, locale): # yesterday
            dateStart = addToDay(datestr, workdate - datetime.timedelta(1))
        elif checkDateKeywords('tomorrow', datestr, locale):  # tomorrow
            dateStart = addToDay(datestr, workdate + datetime.timedelta(1))

        elif checkDateKeywords(('this week', 'next week', 'last week'), datestr, locale): # relative week
            j = workdate.weekday()
            dateStart = workdate - datetime.timedelta(j)
            if checkDateKeywords('last week', datestr, locale):
                dateStart = dateStart - datetime.timedelta(7)
            elif checkDateKeywords('next week', datestr, locale):
                dateStart = dateStart + datetime.timedelta(7)
            if '+' in datestr:
                 dateStart = dateStart + datetime.timedelta(7*int(datestr.split('+')[1]))
            if '-' in datestr:
                 dateStart = dateStart - datetime.timedelta(7*int(datestr.split('-')[1]))
            if isEndPeriod:
                dateEnd = dateStart + datetime.timedelta(6)
        elif checkDateKeywords(('this month', 'next month', 'last month'), datestr, locale): # relative month
            if checkDateKeywords('last month', datestr, locale):  
                dateStart = addToMonth(datestr, workdate, -1)
            elif checkDateKeywords('next month', datestr, locale):
                dateStart = addToMonth(datestr, workdate, 1)
            else:
                dateStart = addToMonth(datestr, workdate)
            if isEndPeriod:
                dateEnd = monthEnd(date=dateStart)
        elif anyWordIn(quarters.keys(), datestr): # quarter
            qt, year = splitAndStrip(datestr, sep=' ', n=1, fixed=2)
            year = yearDecode(year)
            qt = quarters[qt]
            dateStart = (year, qt * 3 - 2)
            if isEndPeriod:
                dateEnd = (year, qt * 3)
        elif anyWordIn(def_quarters.keys(), datestr): # quarter
            qt, year = splitAndStrip(datestr, sep=' ', n=1, fixed=2)
            year = yearDecode(year)
            qt = def_quarters[datestr]
            dateStart = (year, qt * 3 - 2)
            if isEndPeriod:
                dateEnd = (year, qt * 3)
        elif anyWordIn(months.keys(), datestr):                                 # month name
            month, year = splitAndStrip(datestr, sep=' ', n=1, fixed=2)
            year = yearDecode(year)
            month = months[month]
            dateStart = (year, month)
        elif anyWordIn(def_months.keys(), datestr):                                 # month name
            month, year = splitAndStrip(datestr, sep=' ', n=1, fixed=2)
            year = yearDecode(year)
            month = def_months[month]
            dateStart = (year, month)
        elif datestr in days:                                                   # weekday name
            dateStart = workdate + datetime.timedelta(days[datestr] - workdate.weekday())
        elif datestr in def_days:                                                   # weekday name
            dateStart = workdate + datetime.timedelta(def_days[datestr] - workdate.weekday())
        elif re.match('\d{4}-\d{2}-\d{2}', datestr):                            # ISO date
            date_items = [int(el) for el in wordSplit(datestr)[0:3]]
            dateStart = datetime.date(*[int(el) for el in wordSplit(datestr)[0:3]])
        else:                                                                   # a date in local format
            dateStart = gnrlocale.parselocal(datestr, datetime.date, locale)
        if isEndPeriod and dateEnd:
            return dateEnd
        else:
            return dateStart