Example #1
0
    def adjust(self, to):
        """
        Adjusts the time from kwargs to timedelta
        **Will change this object**

        return new copy of self
        """
        if self.date == "infinity":
            return
        new = copy(self)
        if type(to) in (str, unicode):
            to = to.lower()
            res = TIMESTRING_RE.search(to)
            if res:
                rgroup = res.groupdict()
                if rgroup.get("delta") or rgroup.get("delta_2"):
                    i = int(text2num(rgroup.get("num", "one"))) * (-1 if to.startswith("-") else 1)
                    delta = (rgroup.get("delta") or rgroup.get("delta_2")).lower()
                    if delta.startswith("y"):
                        try:
                            new.date = new.date.replace(year=(new.date.year + i))
                        except ValueError:
                            # day is out of range for month
                            new.date = new.date + timedelta(days=(365 * i))
                    elif delta.startswith("month"):
                        if (new.date.month + i) > 12:
                            new.date = new.date.replace(month=(i - (i / 12)), year=(new.date.year + 1 + (i / 12)))
                        elif (new.date.month + i) < 1:
                            new.date = new.date.replace(month=12, year=(new.date.year - 1))
                        else:
                            new.date = new.date.replace(month=(new.date.month + i))
                    elif delta.startswith("q"):
                        # NP
                        pass
                    elif delta.startswith("w"):
                        new.date = new.date + timedelta(days=(7 * i))
                    elif delta.startswith("s"):
                        new.date = new.date + timedelta(seconds=i)
                    else:
                        new.date = new.date + timedelta(
                            **{
                                (
                                    "days"
                                    if delta.startswith("d")
                                    else "hours"
                                    if delta.startswith("h")
                                    else "minutes"
                                    if delta.startswith("m")
                                    else "seconds"
                                ): i
                            }
                        )
                    return new
        else:
            new.date = new.date + timedelta(seconds=int(to))
            return new

        raise TimestringInvalid("Invalid addition request")
Example #2
0
    def adjust(self, to):
        '''
        Adjusts the time from kwargs to timedelta
        **Will change this object**

        return new copy of self
        '''
        if self.date == 'infinity':
            return
        new = copy(self)
        if type(to) in (str, unicode):
            to = to.lower()
            res = TIMESTRING_RE.search(to)
            if res:
                rgroup = res.groupdict()
                if (rgroup.get('delta') or rgroup.get('delta_2')):
                    i = int(text2num(rgroup.get(
                        'num', 'one'))) * (-1 if to.startswith('-') else 1)
                    delta = (rgroup.get('delta')
                             or rgroup.get('delta_2')).lower()
                    if delta.startswith('y'):
                        try:
                            new.date = new.date.replace(year=(new.date.year +
                                                              i))
                        except ValueError:
                            # day is out of range for month
                            new.date = new.date + timedelta(days=(365 * i))
                    elif delta.startswith('month'):
                        if (new.date.month + i) > 12:
                            new.date = new.date.replace(month=(i - (i / 12)),
                                                        year=(new.date.year +
                                                              1 + (i / 12)))
                        elif (new.date.month + i) < 1:
                            new.date = new.date.replace(month=12,
                                                        year=(new.date.year -
                                                              1))
                        else:
                            new.date = new.date.replace(month=(new.date.month +
                                                               i))
                    elif delta.startswith('q'):
                        # NP
                        pass
                    elif delta.startswith('w'):
                        new.date = new.date + timedelta(days=(7 * i))
                    elif delta.startswith('s'):
                        new.date = new.date + timedelta(seconds=i)
                    else:
                        new.date = new.date + timedelta(
                            **{
                                ('days' if delta.startswith('d') else 'hours' if delta.startswith('h') else 'minutes' if delta.startswith('m') else 'seconds'):
                                i
                            })
                    return new
        else:
            new.date = new.date + timedelta(seconds=int(to))
            return new

        raise TimestringInvalid('Invalid addition request')
Example #3
0
 def test_word_boundaries(self):
     res = ts.search('next mon')
     self.assertNotEqual(res, None)
     res = ts.search('santa monica')
     self.assertEqual(res, None)
     res = ts.search('tuesday two weeks ago')
     self.assertNotEqual(res, None)
     res = ts.search('fri')
     self.assertNotEqual(res, None)
     res = ts.search('dec')
     self.assertNotEqual(res, None)
     res = ts.search('Current weather in East hanover new jersey')
     self.assertEqual(res, None)
     res = ts.search('august')
     self.assertNotEqual(res, None)
     res = ts.search('23rd feb 9:35pm')
     self.assertNotEqual(res, None)
Example #4
0
    def adjust(self, to):
        '''
        Adjusts the time from kwargs to timedelta
        **Will change this object**

        return new copy of self
        '''
        if self.date == 'infinity':
            return
        new = copy(self)
        if type(to) in (str, unicode):
            to = to.lower()
            res = TIMESTRING_RE.search(to)
            if res:
                rgroup = res.groupdict()
                if (rgroup.get('delta') or rgroup.get('delta_2')):
                    i = int(string_to_number(rgroup.get('num', 1))) * (-1 if to.startswith('-') else 1)
                    delta = (rgroup.get('delta') or rgroup.get('delta_2')).lower()
                    if delta.startswith('y'):
                        try:
                            new.date = new.date.replace(year=(new.date.year + i))
                        except ValueError:
                            # day is out of range for month
                            new.date = new.date + timedelta(days=(365 * i))
                    elif delta.startswith('month'):
                        if (new.date.month + i) > 12:
                            new.date = new.date.replace(month=(i - (i / 12)),
                                                        year=(new.date.year + 1 + (i / 12)))
                        elif (new.date.month + i) < 1:
                            new.date = new.date.replace(month=12, year=(new.date.year - 1))
                        else:
                            new.date = new.date.replace(month=(new.date.month + i))
                    elif delta.startswith('q'):
                        # NP
                        pass
                    elif delta.startswith('w'):
                        new.date = new.date + timedelta(days=(7 * i))
                    else:
                        new.date = new.date + timedelta(**{('days' if delta.startswith('d') else 'hours' if delta.startswith('h') else 'minutes' if delta.startswith('m') else 'seconds'): i})
                    return new
        else:
            new.date = new.date + timedelta(seconds=int(to))
            return new

        raise TimestringInvalid('Invalid addition request')
Example #5
0
    def __init__(self,
                 date,
                 offset=None,
                 start_of_week=None,
                 tz=None,
                 verbose=False):
        if isinstance(date, Date):
            self.date = copy(date.date)
            return

        # The original request
        self._original = date
        if tz:
            tz = pytz.timezone(str(tz))

        if date == 'infinity':
            self.date = 'infinity'

        elif date == 'now':
            self.date = datetime.now()

        elif type(date) in (str, unicode) and re.match(
                r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+-\d{2}", date):
            self.date = datetime.strptime(
                date[:-3],
                "%Y-%m-%d %H:%M:%S.%f") - timedelta(hours=int(date[-3:]))

        else:
            # Determinal starting date.
            if type(date) in (str, unicode):
                """The date is a string and needs to be converted into a <dict> for processesing
                """
                _date = date.lower()
                res = TIMESTRING_RE.search(_date.strip())
                if res:
                    date = res.groupdict()
                    if verbose:
                        print(
                            "Matches:\n", ''.join([
                                "\t%s: %s\n" % (k, v) for k, v in date.items()
                                if v
                            ]))
                else:
                    raise TimestringInvalid('Invalid date string >> %s' % date)

                date = dict((k, v if type(v) is str else v)
                            for k, v in date.items() if v)
                #print(_date, dict(map(lambda a: (a, date.get(a)), filter(lambda a: date.get(a), date))))

            if isinstance(date, dict):
                # Initial date.
                new_date = datetime(*time.localtime()[:3])
                if tz and tz.zone != "UTC":
                    #
                    # The purpose here is to adjust what day it is based on the timezeone
                    #
                    ts = datetime.now()
                    # Daylight savings === second Sunday in March and reverts to standard time on the first Sunday in November
                    # Monday is 0 and Sunday is 6.
                    # 14 days - dst_start.weekday()
                    dst_start = datetime(
                        ts.year, 3, 1, 2, 0,
                        0) + timedelta(13 - datetime(ts.year, 3, 1).weekday())
                    dst_end = datetime(
                        ts.year, 11, 1, 2, 0,
                        0) + timedelta(6 - datetime(ts.year, 11, 1).weekday())

                    ts = ts + tz.utcoffset(new_date,
                                           is_dst=(dst_start < ts < dst_end))
                    new_date = datetime(ts.year, ts.month, ts.day)

                if date.get('unixtime'):
                    new_date = datetime.fromtimestamp(int(
                        date.get('unixtime')))

                # !number of (days|...) (ago)?
                elif date.get('num') and (date.get('delta')
                                          or date.get('delta_2')):
                    if date.get('num', '').find('couple') > -1:
                        i = 2 * int(1 if date.get('ago', True)
                                    or date.get('ref') == 'last' else -1)
                    else:
                        i = int(text2num(date.get(
                            'num', 'one'))) * int(1 if date.get('ago') or (
                                date.get('ref', '') or '') == 'last' else -1)

                    delta = (date.get('delta') or date.get('delta_2')).lower()
                    if delta.startswith('y'):
                        try:
                            new_date = new_date.replace(year=(new_date.year -
                                                              i))
                        # day is out of range for month
                        except ValueError:
                            new_date = new_date - timedelta(days=(365 * i))
                    elif delta.startswith('month'):
                        try:
                            new_date = new_date.replace(month=(new_date.month -
                                                               i))
                        # day is out of range for month
                        except ValueError:
                            new_date = new_date - timedelta(days=(30 * i))

                    elif delta.startswith('q'):
                        '''
                        This section is not working...
                        Most likely need a generator that will take me to the right quater.
                        '''
                        q1, q2, q3, q4 = datetime(
                            new_date.year, 1,
                            1), datetime(new_date.year, 4, 1), datetime(
                                new_date.year, 7,
                                1), datetime(new_date.year, 10, 1)
                        if q1 <= new_date < q2:
                            # We are in Q1
                            if i == -1:
                                new_date = datetime(new_date.year - 1, 10, 1)
                            else:
                                new_date = q2
                        elif q2 <= new_date < q3:
                            # We are in Q2
                            pass
                        elif q3 <= new_date < q4:
                            # We are in Q3
                            pass
                        else:
                            # We are in Q4
                            pass
                        new_date = new_date - timedelta(days=(91 * i))

                    elif delta.startswith('w'):
                        new_date = new_date - timedelta(days=(i * 7))

                    else:
                        new_date = new_date - timedelta(
                            **{
                                ('days' if delta.startswith('d') else 'hours' if delta.startswith('h') else 'minutes' if delta.startswith('m') else 'seconds'):
                                i
                            })

                # !dow
                if [
                        date.get(key) for key in ('day', 'day_2', 'day_3')
                        if date.get(key)
                ]:
                    dow = max([
                        date.get(key) for key in ('day', 'day_2', 'day_3')
                        if date.get(key)
                    ])
                    iso = dict(monday=1,
                               tuesday=2,
                               wednesday=3,
                               thursday=4,
                               friday=5,
                               saturday=6,
                               sunday=7,
                               mon=1,
                               tue=2,
                               tues=2,
                               wed=3,
                               wedn=3,
                               thu=4,
                               thur=4,
                               fri=5,
                               sat=6,
                               sun=7).get(dow)
                    if iso:
                        # determin which direction
                        if date.get('ref') not in ('this', 'next'):
                            days = iso - new_date.isoweekday() - (
                                7 if iso >= new_date.isoweekday() else 0)
                        else:
                            days = iso - new_date.isoweekday() + (
                                7 if iso < new_date.isoweekday() else 0)

                        new_date = new_date + timedelta(days=days)

                    elif dow == 'yesterday':
                        new_date = new_date - timedelta(days=1)
                    elif dow == 'tomorrow':
                        new_date = new_date + timedelta(days=1)

                # !year
                year = [
                    int(CLEAN_NUMBER.sub('', date[key]))
                    for key in ('year', 'year_2', 'year_3', 'year_4', 'year_5',
                                'year_6') if date.get(key)
                ]
                if year:
                    year = max(year)
                    if len(str(year)) != 4:
                        year += 2000 if year <= 40 else 1900
                    try:
                        new_date = new_date.replace(year=year)
                    except Exception:
                        new_date = new_date.replace(year=year, day=28)

                # !month
                month = [
                    date.get(key) for key in ('month', 'month_1', 'month_2',
                                              'month_3', 'month_4')
                    if date.get(key)
                ]
                if month:
                    new_date = new_date.replace(day=1)
                    new_date = new_date.replace(
                        month=int(max(month)) if re.match('^\d+$', max(month))
                        else dict(january=1,
                                  february=2,
                                  march=3,
                                  april=4,
                                  june=6,
                                  july=7,
                                  august=8,
                                  september=9,
                                  october=10,
                                  november=11,
                                  december=12,
                                  jan=1,
                                  feb=2,
                                  mar=3,
                                  apr=4,
                                  may=5,
                                  jun=6,
                                  jul=7,
                                  aug=8,
                                  sep=9,
                                  sept=9,
                                  oct=10,
                                  nov=11,
                                  dec=12).get(max(month), new_date.month))

                # !day
                day = [
                    date.get(key) for key in ('date', 'date_2', 'date_3')
                    if date.get(key)
                ]
                if day:
                    new_date = new_date.replace(day=int(max(day)))

                # !daytime
                if date.get('daytime'):
                    if date['daytime'].find('this time') >= 1:
                        new_date = new_date.replace(
                            hour=datetime(*time.localtime()[:5]).hour,
                            minute=datetime(*time.localtime()[:5]).minute)
                    else:
                        new_date = new_date.replace(hour=dict(
                            morning=9,
                            noon=12,
                            afternoon=15,
                            evening=18,
                            night=21,
                            nighttime=21,
                            midnight=24).get(date.get('daytime'), 12))
                    # No offset because the hour was set.
                    offset = False

                # !hour
                hour = [
                    date.get(key) for key in ('hour', 'hour_2', 'hour_3')
                    if date.get(key)
                ]
                if hour:
                    new_date = new_date.replace(hour=int(max(hour)))
                    am = [
                        date.get(key) for key in ('am', 'am_1')
                        if date.get(key)
                    ]
                    if am and max(am) in ('p', 'pm'):
                        h = int(max(hour))
                        if h < 12:
                            new_date = new_date.replace(hour=h + 12)
                    # No offset because the hour was set.
                    offset = False

                    #minute
                    minute = [
                        date.get(key) for key in ('minute', 'minute_2')
                        if date.get(key)
                    ]
                    if minute:
                        new_date = new_date.replace(minute=int(max(minute)))

                    #second
                    seconds = date.get('seconds', 0)
                    if seconds:
                        new_date = new_date.replace(second=int(seconds))

                self.date = new_date

            elif type(date) in (int, long, float) and re.match(
                    '^\d{10}$', str(date)):
                self.date = datetime.fromtimestamp(int(date))

            elif isinstance(date, datetime):
                self.date = date

            elif date is None:
                self.date = datetime.now()

            else:
                # Set to the current date Y, M, D, H0, M0, S0
                self.date = datetime(*time.localtime()[:3])

            if tz:
                self.date = self.date.replace(tzinfo=tz)

            # end if type(date) is types.DictType: and self.date.hour == 0:
            if offset and isinstance(offset, dict):
                self.date = self.date.replace(**offset)
Example #6
0
    def __init__(self, date, offset=None, start_of_week=None, tz=None, verbose=False):
        if isinstance(date, Date):
            self.date = copy(date.date)
            return

        # The original request
        self._original = date
        if tz:
            tz = pytz.timezone(str(tz))

        if date == 'infinity':
            self.date = 'infinity'

        elif date == 'now':
            self.date = datetime.now()

        elif type(date) in (str, unicode) and re.match(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+-\d{2}", date):
            self.date = datetime.strptime(date[:-3], "%Y-%m-%d %H:%M:%S.%f") - timedelta(hours=int(date[-3:]))

        else:
            # Determinal starting date.
            if type(date) in (str, unicode):
                """The date is a string and needs to be converted into a <dict> for processesing
                """
                _date = date.lower()
                res = TIMESTRING_RE.search(_date.strip())
                if res:
                    date = res.groupdict()
                    if verbose:
                        print("Matches:\n", ''.join(["\t%s: %s\n" % (k, v) for k, v in date.items() if v]))
                else:
                    raise TimestringInvalid('Invlid date string >> %s' % date)

                date = dict((k, v if type(v) is str else v) for k, v in date.items() if v)
                #print(_date, dict(map(lambda a: (a, date.get(a)), filter(lambda a: date.get(a), date))))

            if isinstance(date, dict):
                # Initial date.
                new_date = datetime(*time.localtime()[:3])
                if tz and tz.zone != "UTC":
                    #
                    # The purpose here is to adjust what day it is based on the timezeone
                    #
                    ts = datetime.now()
                    # Daylight savings === second Sunday in March and reverts to standard time on the first Sunday in November
                    # Monday is 0 and Sunday is 6.
                    # 14 days - dst_start.weekday()
                    dst_start = datetime(ts.year, 3, 1, 2, 0, 0) + timedelta(13 - datetime(ts.year, 3, 1).weekday())
                    dst_end = datetime(ts.year, 11, 1, 2, 0, 0) + timedelta(6 - datetime(ts.year, 11, 1).weekday())

                    ts = ts + tz.utcoffset(new_date, is_dst=(dst_start < ts < dst_end))
                    new_date = datetime(ts.year, ts.month, ts.day)

                if date.get('unixtime'):
                    new_date = datetime.fromtimestamp(int(date.get('unixtime')))

                # !number of (days|...) (ago)?
                elif date.get('num') and (date.get('delta') or date.get('delta_2')):
                    if date.get('num', '').find('couple') > -1:
                        i = 2 * int(1 if date.get('ago', True) or date.get('ref') == 'last' else -1)
                    else:
                        i = int(string_to_number(date.get('num', 1))) * int(1 if date.get('ago') or (date.get('ref', '') or '') == 'last' else -1)

                    delta = (date.get('delta') or date.get('delta_2')).lower()
                    if delta.startswith('y'):
                        try:
                            new_date = new_date.replace(year=(new_date.year - i))
                        # day is out of range for month
                        except ValueError:
                            new_date = new_date - timedelta(days=(365*i))
                    elif delta.startswith('month'):
                        try:
                            new_date = new_date.replace(month=(new_date.month - i))
                        # day is out of range for month
                        except ValueError:
                            new_date = new_date - timedelta(days=(30*i))

                    elif delta.startswith('q'):
                        '''
                        This section is not working...
                        Most likely need a generator that will take me to the right quater.
                        '''
                        q1, q2, q3, q4 = datetime(new_date.year, 1, 1), datetime(new_date.year, 4, 1), datetime(new_date.year, 7, 1), datetime(new_date.year, 10, 1)
                        if q1 <= new_date < q2:
                            # We are in Q1
                            if i == -1:
                                new_date = datetime(new_date.year-1, 10, 1)
                            else:
                                new_date = q2
                        elif q2 <= new_date < q3:
                            # We are in Q2
                            pass
                        elif q3 <= new_date < q4:
                            # We are in Q3
                            pass
                        else:
                            # We are in Q4
                            pass
                        new_date = new_date - timedelta(days=(91*i))

                    elif delta.startswith('w'):
                        new_date = new_date - timedelta(days=(i * 7))

                    else:
                        new_date = new_date - timedelta(**{('days' if delta.startswith('d') else 'hours' if delta.startswith('h') else 'minutes' if delta.startswith('m') else 'seconds'): i})

                # !dow
                if [date.get(key) for key in ('day', 'day_2', 'day_3') if date.get(key)]:
                    dow = max([date.get(key) for key in ('day', 'day_2', 'day_3') if date.get(key)])
                    iso = dict(monday=1, tuesday=2, wednesday=3, thursday=4, friday=5, saturday=6, sunday=7, mon=1, tue=2, tues=2, wed=3, wedn=3, thu=4, thur=4, fri=5, sat=6, sun=7).get(dow)
                    if iso:
                        # determin which direction
                        if date.get('ref') not in ('this', 'next'):
                            days = iso - new_date.isoweekday() - (7 if iso >= new_date.isoweekday() else 0)
                        else:
                            days = iso - new_date.isoweekday() + (7 if iso < new_date.isoweekday() else 0)

                        new_date = new_date + timedelta(days=days)

                    elif dow == 'yesterday':
                        new_date = new_date - timedelta(days=1)
                    elif dow == 'tomorrow':
                        new_date = new_date + timedelta(days=1)

                # !year
                year = [date.get(key) for key in ('year', 'year_2', 'year_3', 'year_4', 'year_5', 'year_6') if date.get(key)]
                if year:
                    y = int(max(year))
                    if len(str(y)) != 4:
                        y += 2000 if y <= 40 else 1900
                    new_date = new_date.replace(year=y)

                # !month
                month = [date.get(key) for key in ('month', 'month_1', 'month_2', 'month_3', 'month_4') if date.get(key)]
                if month:
                    new_date = new_date.replace(day=1)
                    new_date = new_date.replace(month=int(max(month)) if re.match('^\d+$', max(month)) else dict(january=1, february=2, march=3, april=4, june=6, july=7, august=8, september=9, october=10, november=11, december=12, jan=1, feb=2, mar=3, apr=4, may=5, jun=6, jul=7, aug=8, sep=9, sept=9, oct=10, nov=11, dec=12).get(max(month),  new_date.month))

                # !day
                day = [date.get(key) for key in ('date', 'date_2', 'date_3') if date.get(key)]
                if day:
                    new_date = new_date.replace(day=int(max(day)))

                # !daytime
                if date.get('daytime'):
                    if date['daytime'].find('this time') >= 1:
                        new_date = new_date.replace(hour=datetime(*time.localtime()[:5]).hour,
                                                    minute=datetime(*time.localtime()[:5]).minute)
                    else:
                        new_date = new_date.replace(hour=dict(morning=9, noon=12, afternoon=15, evening=18, night=21, nighttime=21, midnight=24).get(date.get('daytime'), 12))
                    # No offset because the hour was set.
                    offset = False

                # !hour
                hour = [date.get(key) for key in ('hour', 'hour_2', 'hour_3') if date.get(key)]
                if hour:
                    new_date = new_date.replace(hour=int(max(hour)))
                    am = [date.get(key) for key in ('am', 'am_1') if date.get(key)]
                    if am and max(am) in ('p', 'pm'):
                        new_date = new_date.replace(hour=int(max(hour))+12)
                    # No offset because the hour was set.
                    offset = False

                    #minute
                    minute = [date.get(key) for key in ('minute', 'minute_2') if date.get(key)]
                    if minute:
                        new_date = new_date.replace(minute=int(max(minute)))

                    #second
                    seconds = date.get('seconds', 0)
                    if seconds:
                        new_date = new_date.replace(second=int(seconds))

                self.date = new_date

            elif type(date) in (int, long, float) and re.match('^\d{10}$', str(date)):
                self.date = datetime.fromtimestamp(int(date))

            elif isinstance(date, datetime):
                self.date = date

            elif date is None:
                self.date = datetime.now()

            else:
                # Set to the current date Y, M, D, H0, M0, S0
                self.date = datetime(*time.localtime()[:3])

            if tz:
                self.date = self.date.replace(tzinfo=tz)

            # end if type(date) is types.DictType: and self.date.hour == 0:
            if offset and isinstance(offset, dict):
                self.date = self.date.replace(**offset)
Example #7
0
    def __init__(self,
                 start,
                 end=None,
                 offset=None,
                 start_of_week=0,
                 tz=None,
                 verbose=False):
        """`start` can be type <class timestring.Date> or <type str>
        """
        self._dates = []
        pgoffset = None

        if start is None:
            raise TimestringInvalid("Range object requires a start valie")

        if not isinstance(start, (Date, datetime)):
            start = str(start)
        if end and not isinstance(end, (Date, datetime)):
            end = str(end)

        if start and end:
            """start and end provided
            """
            self._dates = (Date(start, tz=tz), Date(end, tz=tz))

        elif start == 'infinity':
            # end was not provided
            self._dates = (Date('infinity'), Date('infinity'))

        elif re.search(r'(\s(and|to)\s)', start):
            """Both sides where provided in the start
            """
            start = re.sub('^(between|from)\s', '', start.lower())
            # Both arguments found in start variable
            r = tuple(re.split(r'(\s(and|to)\s)', start.strip()))
            self._dates = (Date(r[0], tz=tz), Date(r[-1], tz=tz))

        elif re.match(
                r"(\[|\()((\"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?(\+|\-)\d{2}\")|infinity),((\"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?(\+|\-)\d{2}\")|infinity)(\]|\))",
                start):
            """postgresql tsrange and tstzranges support
            """
            start, end = tuple(
                re.sub('[^\w\s\-\:\.\+\,]', '', start).split(','))
            self._dates = (Date(start), Date(end))

        else:
            now = datetime.now()
            # no tz info but offset provided, we are UTC so convert

            if re.search(r"(\+|\-)\d{2}$", start):
                # postgresql tsrange and tstzranges
                pgoffset = re.search(r"(\+|\-)\d{2}$",
                                     start).group() + " hours"

            # tz info provided
            if tz:
                now = now.replace(tzinfo=pytz.timezone(str(tz)))

            # Parse
            res = TIMESTRING_RE.search(start)
            if res:
                group = res.groupdict()
                if verbose:
                    print(
                        dict(
                            map(lambda a: (a, group.get(a)),
                                filter(lambda a: group.get(a), group))))
                if (group.get('delta') or group.get('delta_2')) is not None:
                    delta = (group.get('delta')
                             or group.get('delta_2')).lower()

                    # always start w/ today
                    start = Date("today", offset=offset, tz=tz)

                    # make delta
                    di = "%s %s" % (str(int(group['num'] or 1)), delta)

                    # this           [   x  ]
                    if group['ref'] == 'this':

                        if delta.startswith('y'):
                            start = Date(datetime(now.year, 1, 1),
                                         offset=offset,
                                         tz=tz)

                        # month
                        elif delta.startswith('month'):
                            start = Date(datetime(now.year, now.month, 1),
                                         offset=offset,
                                         tz=tz)

                        # week
                        elif delta.startswith('w'):
                            start = Date("today", offset=offset, tz=tz) - (str(
                                Date("today", tz=tz).date.weekday()) + ' days')

                        # day
                        elif delta.startswith('d'):
                            start = Date("today", offset=offset, tz=tz)

                        # hour
                        elif delta.startswith('h'):
                            start = Date("today",
                                         offset=dict(hour=now.hour + 1),
                                         tz=tz)

                        # minute, second
                        elif delta.startswith('m') or delta.startswith('s'):
                            start = Date("now", tz=tz)

                        else:
                            raise TimestringInvalid(
                                "Not a valid time reference")

                        end = start + di

                    #next          x [      ]
                    elif group['ref'] == 'next':
                        if int(group['num'] or 1) > 1:
                            di = "%s %s" % (str(int(group['num'] or 1) - 1),
                                            delta)
                        end = start + di

                    # ago             [     ] x
                    elif group.get('ago') or group['ref'] == 'last' and int(
                            group['num'] or 1) == 1:
                        #if group['ref'] == 'last' and int(group['num'] or 1) == 1:
                        #    start = start - ('1 ' + delta)
                        end = start - di

                    # last & no ref   [    x]
                    else:
                        # need to include today with this reference
                        if not (delta.startswith('h') or delta.startswith('m')
                                or delta.startswith('s')):
                            start = Range('today', offset=offset, tz=tz).end
                        end = start - di

                elif group.get('month_1'):
                    # a single month of this yeear
                    start = Date(start, offset=offset, tz=tz)
                    start = start.replace(day=1)
                    end = start + '1 month'

                elif group.get('year_5'):
                    # a whole year
                    start = Date(start, offset=offset, tz=tz)
                    start = start.replace(day=1, month=1)
                    end = start + '1 year'

                else:
                    # after all else, we set the end to + 1 day
                    start = Date(start, offset=offset, tz=tz)
                    end = start + '1 day'

            else:
                raise TimestringInvalid("Invalid timestring request")

            if end is None:
                # no end provided, so assume 24 hours
                end = start + '24 hours'

            if start > end:
                # flip them if this is so
                start, end = copy(end), copy(start)

            if pgoffset:
                start = start - pgoffset
                if end != 'infinity':
                    end = end - pgoffset

            self._dates = (start, end)

        if self._dates[0] > self._dates[1]:
            self._dates = (self._dates[0], self._dates[1] + '1 day')
Example #8
0
    def __init__(self, start, end=None, offset=None, start_of_week=0, tz=None, verbose=False):
        """`start` can be type <class timestring.Date> or <type str>
        """
        self._dates = []
        pgoffset = None

        if start is None:
            raise TimestringInvalid("Range object requires a start valie")

        if not isinstance(start, (Date, datetime)):
            start = str(start)
        if end and not isinstance(end, (Date, datetime)):
            end = str(end)

        if start and end:
            """start and end provided
            """
            self._dates = (Date(start, tz=tz), Date(end, tz=tz))

        elif start == 'infinity':
            # end was not provided
            self._dates = (Date('infinity'), Date('infinity'))

        elif re.search(r'(\s(and|to)\s)', start):
            """Both sides where provided in the start
            """
            start = re.sub('^(between|from)\s', '', start.lower())
            # Both arguments found in start variable
            r = tuple(re.split(r'(\s(and|to)\s)', start.strip()))
            self._dates = (Date(r[0], tz=tz), Date(r[-1], tz=tz))

        elif re.match(r"(\[|\()((\"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?(\+|\-)\d{2}\")|infinity),((\"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?(\+|\-)\d{2}\")|infinity)(\]|\))", start):
            """postgresql tsrange and tstzranges support
            """
            start, end = tuple(re.sub('[^\w\s\-\:\.\+\,]', '', start).split(','))
            self._dates = (Date(start), Date(end))

        else:
            now = datetime.now()
            # no tz info but offset provided, we are UTC so convert

            if re.search(r"(\+|\-)\d{2}$", start):
                # postgresql tsrange and tstzranges
                pgoffset = re.search(r"(\+|\-)\d{2}$", start).group() + " hours"

            # tz info provided
            if tz:
                now = now.replace(tzinfo=pytz.timezone(str(tz)))

            # Parse
            res = TIMESTRING_RE.search(start)
            if res:
                group = res.groupdict()
                if verbose:
                    print(dict(map(lambda a: (a, group.get(a)), filter(lambda a: group.get(a), group))))
                if (group.get('delta') or group.get('delta_2')) is not None:
                    delta = (group.get('delta') or group.get('delta_2')).lower()

                    # always start w/ today
                    start = Date("today", offset=offset, tz=tz)

                    # make delta
                    di = "%s %s" % (str(int(group['num'] or 1)), delta)

                    # this           [   x  ]
                    if group['ref'] == 'this':

                        if delta.startswith('y'):
                            start = Date(datetime(now.year, 1, 1), offset=offset, tz=tz)

                        # month
                        elif delta.startswith('month'):
                            start = Date(datetime(now.year, now.month, 1), offset=offset, tz=tz)

                        # week
                        elif delta.startswith('w'):
                            start = Date("today", offset=offset, tz=tz) - (str(Date("today", tz=tz).date.weekday())+' days')

                        # day
                        elif delta.startswith('d'):
                            start = Date("today", offset=offset, tz=tz)

                        # hour
                        elif delta.startswith('h'):
                            start = Date("today", offset=dict(hour=now.hour+1), tz=tz)

                        # minute, second
                        elif delta.startswith('m') or delta.startswith('s'):
                            start = Date("now", tz=tz)

                        else:
                            raise TimestringInvalid("Not a valid time reference")

                        end = start + di

                    #next          x [      ]
                    elif group['ref'] == 'next':
                        if int(group['num'] or 1) > 1:
                            di = "%s %s" % (str(int(group['num'] or 1) - 1), delta)
                        end = start + di

                    # ago             [     ] x
                    elif group.get('ago') or group['ref'] == 'last' and int(group['num'] or 1) == 1:
                        #if group['ref'] == 'last' and int(group['num'] or 1) == 1:
                        #    start = start - ('1 ' + delta)
                        end = start - di

                    # last & no ref   [    x]
                    else:
                        # need to include today with this reference
                        if not (delta.startswith('h') or delta.startswith('m') or delta.startswith('s')):
                            start = Range('today', offset=offset, tz=tz).end
                        end = start - di                    

                elif group.get('month_1'):
                    # a single month of this yeear
                    start = Date(start, offset=offset, tz=tz)
                    start = start.replace(day=1)
                    end = start + '1 month'

                elif group.get('year_5'):
                    # a whole year
                    start = Date(start, offset=offset, tz=tz)
                    start = start.replace(day=1, month=1)
                    end = start + '1 year'

                else:
                    # after all else, we set the end to + 1 day
                    start = Date(start, offset=offset, tz=tz)
                    end = start + '1 day'

            else:
                raise TimestringInvalid("Invalid timestring request")


            if end is None:
                # no end provided, so assume 24 hours
                end = start + '24 hours'

            if start > end:
                # flip them if this is so
                start, end = copy(end), copy(start)
            
            if pgoffset:
                start = start - pgoffset
                if end != 'infinity':
                    end = end - pgoffset

            self._dates = (start, end)

        if self._dates[0] > self._dates[1]:
            self._dates = (self._dates[0], self._dates[1] + '1 day')
Example #9
0
    def __init__(self, date, offset=None, start_of_week=None, tz=None, verbose=False):
        if isinstance(date, Date):
            self.date = copy(date.date)
            return

        # The original request
        self._original = date
        if tz:
            tz = pytz.timezone(str(tz))

        if date == "infinity":
            self.date = "infinity"

        elif date == "now":
            self.date = datetime.now()

        elif type(date) in (str, unicode) and re.match(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+-\d{2}", date):
            self.date = datetime.strptime(date[:-3], "%Y-%m-%d %H:%M:%S.%f") - timedelta(hours=int(date[-3:]))

        else:
            # Determinal starting date.
            if type(date) in (str, unicode):
                """The date is a string and needs to be converted into a <dict> for processesing
                """
                _date = date.lower()
                res = TIMESTRING_RE.search(_date.strip())
                if res:
                    date = res.groupdict()
                    if verbose:
                        print("Matches:\n", "".join(["\t%s: %s\n" % (k, v) for k, v in date.items() if v]))
                else:
                    raise TimestringInvalid("Invalid date string >> %s" % date)

                date = dict((k, v if type(v) is str else v) for k, v in date.items() if v)
                # print(_date, dict(map(lambda a: (a, date.get(a)), filter(lambda a: date.get(a), date))))

            if isinstance(date, dict):
                # Initial date.
                new_date = datetime(*time.localtime()[:3])
                if tz and tz.zone != "UTC":
                    #
                    # The purpose here is to adjust what day it is based on the timezeone
                    #
                    ts = datetime.now()
                    # Daylight savings === second Sunday in March and reverts to standard time on the first Sunday in November
                    # Monday is 0 and Sunday is 6.
                    # 14 days - dst_start.weekday()
                    dst_start = datetime(ts.year, 3, 1, 2, 0, 0) + timedelta(13 - datetime(ts.year, 3, 1).weekday())
                    dst_end = datetime(ts.year, 11, 1, 2, 0, 0) + timedelta(6 - datetime(ts.year, 11, 1).weekday())

                    ts = ts + tz.utcoffset(new_date, is_dst=(dst_start < ts < dst_end))
                    new_date = datetime(ts.year, ts.month, ts.day)

                if date.get("unixtime"):
                    new_date = datetime.fromtimestamp(int(date.get("unixtime")))

                # !number of (days|...) (ago)?
                elif date.get("num") and (date.get("delta") or date.get("delta_2")):
                    if date.get("num", "").find("couple") > -1:
                        i = 2 * int(1 if date.get("ago", True) or date.get("ref") == "last" else -1)
                    else:
                        i = int(text2num(date.get("num", "one"))) * int(
                            1 if date.get("ago") or (date.get("ref", "") or "") == "last" else -1
                        )

                    delta = (date.get("delta") or date.get("delta_2")).lower()
                    if delta.startswith("y"):
                        try:
                            new_date = new_date.replace(year=(new_date.year - i))
                        # day is out of range for month
                        except ValueError:
                            new_date = new_date - timedelta(days=(365 * i))
                    elif delta.startswith("month"):
                        try:
                            new_date = new_date.replace(month=(new_date.month - i))
                        # day is out of range for month
                        except ValueError:
                            new_date = new_date - timedelta(days=(30 * i))

                    elif delta.startswith("q"):
                        """
                        This section is not working...
                        Most likely need a generator that will take me to the right quater.
                        """
                        q1, q2, q3, q4 = (
                            datetime(new_date.year, 1, 1),
                            datetime(new_date.year, 4, 1),
                            datetime(new_date.year, 7, 1),
                            datetime(new_date.year, 10, 1),
                        )
                        if q1 <= new_date < q2:
                            # We are in Q1
                            if i == -1:
                                new_date = datetime(new_date.year - 1, 10, 1)
                            else:
                                new_date = q2
                        elif q2 <= new_date < q3:
                            # We are in Q2
                            pass
                        elif q3 <= new_date < q4:
                            # We are in Q3
                            pass
                        else:
                            # We are in Q4
                            pass
                        new_date = new_date - timedelta(days=(91 * i))

                    elif delta.startswith("w"):
                        new_date = new_date - timedelta(days=(i * 7))

                    else:
                        new_date = new_date - timedelta(
                            **{
                                (
                                    "days"
                                    if delta.startswith("d")
                                    else "hours"
                                    if delta.startswith("h")
                                    else "minutes"
                                    if delta.startswith("m")
                                    else "seconds"
                                ): i
                            }
                        )

                # !dow
                if [date.get(key) for key in ("day", "day_2", "day_3") if date.get(key)]:
                    dow = max([date.get(key) for key in ("day", "day_2", "day_3") if date.get(key)])
                    iso = dict(
                        monday=1,
                        tuesday=2,
                        wednesday=3,
                        thursday=4,
                        friday=5,
                        saturday=6,
                        sunday=7,
                        mon=1,
                        tue=2,
                        tues=2,
                        wed=3,
                        wedn=3,
                        thu=4,
                        thur=4,
                        fri=5,
                        sat=6,
                        sun=7,
                    ).get(dow)
                    if iso:
                        # determin which direction
                        if date.get("ref") not in ("this", "next"):
                            days = iso - new_date.isoweekday() - (7 if iso >= new_date.isoweekday() else 0)
                        else:
                            days = iso - new_date.isoweekday() + (7 if iso < new_date.isoweekday() else 0)

                        new_date = new_date + timedelta(days=days)

                    elif dow == "yesterday":
                        new_date = new_date - timedelta(days=1)
                    elif dow == "tomorrow":
                        new_date = new_date + timedelta(days=1)

                # !year
                year = [
                    int(CLEAN_NUMBER.sub("", date[key]))
                    for key in ("year", "year_2", "year_3", "year_4", "year_5", "year_6")
                    if date.get(key)
                ]
                if year:
                    year = max(year)
                    if len(str(year)) != 4:
                        year += 2000 if year <= 40 else 1900
                    new_date = new_date.replace(year=year)

                # !month
                month = [
                    date.get(key) for key in ("month", "month_1", "month_2", "month_3", "month_4") if date.get(key)
                ]
                if month:
                    new_date = new_date.replace(day=1)
                    new_date = new_date.replace(
                        month=int(max(month))
                        if re.match("^\d+$", max(month))
                        else dict(
                            january=1,
                            february=2,
                            march=3,
                            april=4,
                            june=6,
                            july=7,
                            august=8,
                            september=9,
                            october=10,
                            november=11,
                            december=12,
                            jan=1,
                            feb=2,
                            mar=3,
                            apr=4,
                            may=5,
                            jun=6,
                            jul=7,
                            aug=8,
                            sep=9,
                            sept=9,
                            oct=10,
                            nov=11,
                            dec=12,
                        ).get(max(month), new_date.month)
                    )

                # !day
                day = [date.get(key) for key in ("date", "date_2", "date_3") if date.get(key)]
                if day:
                    new_date = new_date.replace(day=int(max(day)))

                # !daytime
                if date.get("daytime"):
                    if date["daytime"].find("this time") >= 1:
                        new_date = new_date.replace(
                            hour=datetime(*time.localtime()[:5]).hour, minute=datetime(*time.localtime()[:5]).minute
                        )
                    else:
                        new_date = new_date.replace(
                            hour=dict(
                                morning=9, noon=12, afternoon=15, evening=18, night=21, nighttime=21, midnight=24
                            ).get(date.get("daytime"), 12)
                        )
                    # No offset because the hour was set.
                    offset = False

                # !hour
                hour = [date.get(key) for key in ("hour", "hour_2", "hour_3") if date.get(key)]
                if hour:
                    new_date = new_date.replace(hour=int(max(hour)))
                    am = [date.get(key) for key in ("am", "am_1") if date.get(key)]
                    if am and max(am) in ("p", "pm"):
                        h = int(max(hour))
                        if h < 12:
                            new_date = new_date.replace(hour=h + 12)
                    # No offset because the hour was set.
                    offset = False

                    # minute
                    minute = [date.get(key) for key in ("minute", "minute_2") if date.get(key)]
                    if minute:
                        new_date = new_date.replace(minute=int(max(minute)))

                    # second
                    seconds = date.get("seconds", 0)
                    if seconds:
                        new_date = new_date.replace(second=int(seconds))

                self.date = new_date

            elif type(date) in (int, long, float) and re.match("^\d{10}$", str(date)):
                self.date = datetime.fromtimestamp(int(date))

            elif isinstance(date, datetime):
                self.date = date

            elif date is None:
                self.date = datetime.now()

            else:
                # Set to the current date Y, M, D, H0, M0, S0
                self.date = datetime(*time.localtime()[:3])

            if tz:
                self.date = self.date.replace(tzinfo=tz)

            # end if type(date) is types.DictType: and self.date.hour == 0:
            if offset and isinstance(offset, dict):
                self.date = self.date.replace(**offset)