def parse_date(text, tzinfo=None, hint='date'): tzinfo = tzinfo or localtz dt = None text = text.strip() # normalize ISO time match = _ISO_8601_RE.match(text) if match: try: g = match.groups() years = g[0] months = g[1] or '01' days = g[2] or '01' hours, minutes, seconds = [x or '00' for x in g[3:6]] z, tzsign, tzhours, tzminutes = g[6:10] if z: tz = timedelta(hours=int(tzhours or '0'), minutes=int(tzminutes or '0')).seconds / 60 if tz == 0: tzinfo = utc else: tzinfo = FixedOffset(tzsign == '-' and -tz or tz, '%s%s:%s' % (tzsign, tzhours, tzminutes)) tm = time.strptime('%s ' * 6 % (years, months, days, hours, minutes, seconds), '%Y %m %d %H %M %S ') dt = tzinfo.localize(datetime(*tm[0:6])) except ValueError: pass if dt is None: for format in ['%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', '%b %d, %Y']: try: tm = time.strptime(text, format) dt = tzinfo.localize(datetime(*tm[0:6])) break except ValueError: continue if dt is None: dt = _parse_relative_time(text, tzinfo) if dt is None: hint = {'datetime': get_datetime_format_hint, 'date': get_date_format_hint}.get(hint, lambda: hint)() raise TracError(_('"%(date)s" is an invalid date, or the date format ' 'is not known. Try "%(hint)s" instead.', date=text, hint=hint), _('Invalid Date')) # Make sure we can convert it to a timestamp and back - fromtimestamp() # may raise ValueError if larger than platform C localtime() or gmtime() try: to_datetime(to_timestamp(dt), tzinfo) except ValueError: raise TracError(_('The date "%(date)s" is outside valid range. ' 'Try a date closer to present time.', date=text), _('Invalid Date')) return dt
def _parse_date_iso8601(text, tzinfo): match = _ISO_8601_RE.match(text) if match: try: g = match.groups() years = g[0] months = g[1] or '01' days = g[2] or '01' hours, minutes, seconds = [x or '00' for x in g[3:6]] z, tzsign, tzhours, tzminutes = g[6:10] if z: tz = timedelta(hours=int(tzhours or '0'), minutes=int(tzminutes or '0')).seconds / 60 if tz == 0: tzinfo = utc else: tzinfo = FixedOffset( -tz if tzsign == '-' else tz, '%s%s:%s' % (tzsign, tzhours, tzminutes)) tm = time.strptime( '%s ' * 6 % (years, months, days, hours, minutes, seconds), '%Y %m %d %H %M %S ') t = tzinfo.localize(datetime(*tm[0:6])) return tzinfo.normalize(t) except ValueError: pass return None
def _parse_relative_time(text, tzinfo): now = tzinfo.localize(datetime.now()) if text == 'now': return now if text == 'today': return now.replace(microsecond=0, second=0, minute=0, hour=0) if text == 'yesterday': return now.replace(microsecond=0, second=0, minute=0, hour=0) \ - timedelta(days=1) match = _REL_TIME_RE.match(text) if match: (value, interval) = match.groups() return now - _time_intervals[interval](float(value)) match = _TIME_START_RE.match(text) if match: (which, start) = match.groups() dt = _time_starts[start](now) if which == 'last': if start == 'month': if dt.month > 1: dt = dt.replace(month=dt.month - 1) else: dt = dt.replace(year=dt.year - 1, month=12) else: dt -= _time_intervals[start](1) return dt return None
def from_ical(ical, timezone=None): """ Parses the data format from ical text format. """ tzinfo = None if timezone: try: tzinfo = pytz.timezone(timezone) except pytz.UnknownTimeZoneError: pass try: timetuple = map( int, (( ical[:4], # year ical[4:6], # month ical[6:8], # day ical[9:11], # hour ical[11:13], # minute ical[13:15], # second ))) if tzinfo: return tzinfo.localize(datetime(*timetuple)) elif not ical[15:]: return datetime(*timetuple) elif ical[15:16] == 'Z': return datetime(tzinfo=pytz.utc, *timetuple) else: raise ValueError, ical except: raise ValueError, 'Wrong datetime format: %s' % ical
def from_ical(ical, timezone=None): tzinfo = None if timezone: try: tzinfo = pytz.timezone(timezone) except pytz.UnknownTimeZoneError: pass try: timetuple = ( int(ical[:4]), # year int(ical[4:6]), # month int(ical[6:8]), # day int(ical[9:11]), # hour int(ical[11:13]), # minute int(ical[13:15]), # second ) if tzinfo: return tzinfo.localize(datetime(*timetuple)) elif not ical[15:]: return datetime(*timetuple) elif ical[15:16] == 'Z': return datetime(tzinfo=pytz.utc, *timetuple) else: raise ValueError(ical) except: raise ValueError('Wrong datetime format: %s' % ical)
def from_ical(ical, timezone=None): """ Parses the data format from ical text format. """ tzinfo = None if timezone: try: tzinfo = pytz.timezone(timezone) except pytz.UnknownTimeZoneError: pass try: timetuple = map(int, (( ical[:4], # year ical[4:6], # month ical[6:8], # day ical[9:11], # hour ical[11:13], # minute ical[13:15], # second ))) if tzinfo: return tzinfo.localize(datetime(*timetuple)) elif not ical[15:]: return datetime(*timetuple) elif ical[15:16] == 'Z': return datetime(tzinfo=pytz.utc, *timetuple) else: raise ValueError, ical except: raise ValueError, 'Wrong datetime format: %s' % ical
def _parse_date_iso8601(text, tzinfo): match = _ISO_8601_RE.match(text) if match: try: g = match.groups() years = g[0] months = g[1] or '01' days = g[2] or '01' hours, minutes, seconds, useconds = [x or '00' for x in g[3:7]] useconds = (useconds + '000000')[:6] z = g[7] if z: tzsign = g[8] tzhours = int(g[9] or 0) tzminutes = int(g[10] or 0) if not (0 <= tzhours < 24 and 0 <= tzminutes < 60): return None tz = tzhours * 60 + tzminutes if tz == 0: tzinfo = utc else: tzinfo = FixedOffset( -tz if tzsign == '-' else tz, '%s%02d:%02d' % (tzsign, tzhours, tzminutes)) tm = [ int(x) for x in (years, months, days, hours, minutes, seconds, useconds) ] t = tzinfo.localize(datetime(*tm)) return tzinfo.normalize(t) except (ValueError, OverflowError): pass return None
def parse(time_str, tz='America/New_York', now=None): """ Convert a string that could be either number of seconds since epoch (unixtime) or a formatted string to a datetime. @param time_str: str|datetime|None @param now: datetime|None, uses current time by default @return datetime """ if not time_str or isinstance(time_str, datetime): return time_str dt = _as_datetime(time_str) or _as_timedelta(time_str, now) if dt is None: raise ValueError("unable to convert '%s' to datetime" % time_str) if tz: try: tzinfo = convert_tzinfo(tz) if dt.tzinfo: localize(dt, tz=tz, normalize=True) else: dt = tzinfo.localize(dt) except pytz.exceptions.UnknownTimeZoneError: raise ValueError("unknown timezone '%s'" % tz) dt = pytz.timezone('America/New_York').normalize(dt) return dt
def from_ical(ical, timezone=None): tzinfo = None if timezone: try: tzinfo = pytz.timezone(timezone) except pytz.UnknownTimeZoneError: tzinfo = _timezone_cache.get(timezone, None) try: timetuple = ( int(ical[:4]), # year int(ical[4:6]), # month int(ical[6:8]), # day int(ical[9:11]), # hour int(ical[11:13]), # minute int(ical[13:15]), # second ) if tzinfo: return tzinfo.localize(datetime(*timetuple)) elif not ical[15:]: return datetime(*timetuple) elif ical[15:16] == 'Z': return pytz.utc.localize(datetime(*timetuple)) else: raise ValueError(ical) except: raise ValueError('Wrong datetime format: %s' % ical)
def _parse_date_iso8601(text, tzinfo): match = _ISO_8601_RE.match(text) if match: try: g = match.groups() years = g[0] months = g[1] or '01' days = g[2] or '01' hours, minutes, seconds = [x or '00' for x in g[3:6]] z, tzsign, tzhours, tzminutes = g[6:10] if z: tz = timedelta(hours=int(tzhours or '0'), minutes=int(tzminutes or '0')).seconds / 60 if tz == 0: tzinfo = utc else: tzinfo = FixedOffset(-tz if tzsign == '-' else tz, '%s%s:%s' % (tzsign, tzhours, tzminutes)) tm = time.strptime('%s ' * 6 % (years, months, days, hours, minutes, seconds), '%Y %m %d %H %M %S ') t = tzinfo.localize(datetime(*tm[0:6])) return tzinfo.normalize(t) except ValueError: pass return None
def _parse_date_iso8601(text, tzinfo): match = _ISO_8601_RE.match(text) if match: try: g = match.groups() years = g[0] months = g[1] or '01' days = g[2] or '01' hours, minutes, seconds, useconds = [x or '00' for x in g[3:7]] useconds = (useconds + '000000')[:6] z, tzsign, tzhours, tzminutes = g[7:11] if z: tz = timedelta(hours=int(tzhours or '0'), minutes=int(tzminutes or '0')).seconds / 60 if tz == 0: tzinfo = utc else: tzinfo = FixedOffset(-tz if tzsign == '-' else tz, '%s%s:%s' % (tzsign, tzhours, tzminutes)) tm = [int(x) for x in (years, months, days, hours, minutes, seconds, useconds)] t = tzinfo.localize(datetime(*tm)) return tzinfo.normalize(t) except ValueError: pass return None
def _parse_relative_time(text, tzinfo, now=None): if now is None: # now argument for unit tests now = datetime_now(tzinfo) if text == 'now': return now dt = None if text == 'today': dt = _time_starts['day'](now) elif text == 'yesterday': dt = _time_starts['day'](now) - timedelta(days=1) elif text == 'tomorrow': dt = _time_starts['day'](now) + timedelta(days=1) if dt is None: match = _REL_FUTURE_RE.match(text) if match: (value, interval) = match.groups() dt = now + _time_intervals[interval](float(value)) if dt is None: match = _REL_PAST_RE.match(text) if match: (value, interval) = match.groups() dt = now - _time_intervals[interval](float(value)) if dt is None: match = _TIME_START_RE.match(text) if match: (which, start) = match.groups() dt = _time_starts[start](now) if which == 'last': if start == 'month': if dt.month > 1: dt = dt.replace(month=dt.month - 1) else: dt = dt.replace(year=dt.year - 1, month=12) elif start == 'year': dt = dt.replace(year=dt.year - 1) else: dt -= _time_intervals[start](1) elif which == 'next': if start == 'month': if dt.month < 12: dt = dt.replace(month=dt.month + 1) else: dt = dt.replace(year=dt.year + 1, month=1) elif start == 'year': dt = dt.replace(year=dt.year + 1) else: dt += _time_intervals[start](1) if dt is None: return None if not dt.tzinfo: dt = tzinfo.localize(dt) return tzinfo.normalize(dt)
def _parse_relative_time(text, tzinfo, now=None): if now is None: # now argument for unit tests now = datetime.now(tzinfo) if text == 'now': return now dt = None if text == 'today': dt = _time_starts['day'](now) elif text == 'yesterday': dt = _time_starts['day'](now) - timedelta(days=1) elif text == 'tomorrow': dt = _time_starts['day'](now) + timedelta(days=1) if dt is None: match = _REL_FUTURE_RE.match(text) if match: (value, interval) = match.groups() dt = now + _time_intervals[interval](float(value)) if dt is None: match = _REL_PAST_RE.match(text) if match: (value, interval) = match.groups() dt = now - _time_intervals[interval](float(value)) if dt is None: match = _TIME_START_RE.match(text) if match: (which, start) = match.groups() dt = _time_starts[start](now) if which == 'last': if start == 'month': if dt.month > 1: dt = dt.replace(month=dt.month - 1) else: dt = dt.replace(year=dt.year - 1, month=12) elif start == 'year': dt = dt.replace(year=dt.year - 1) else: dt -= _time_intervals[start](1) elif which == 'next': if start == 'month': if dt.month < 12: dt = dt.replace(month=dt.month + 1) else: dt = dt.replace(year=dt.year + 1, month=1) elif start == 'year': dt = dt.replace(year=dt.year + 1) else: dt += _time_intervals[start](1) if dt is None: return None if not dt.tzinfo: dt = tzinfo.localize(dt) return tzinfo.normalize(dt)
def _i18n_parse_date_0(text, order, regexp, period_names, month_names, tzinfo): matches = regexp.findall(text) if not matches: return None # remove am/pm markers on ahead period = None for idx, match in enumerate(matches): period = period_names.get(match) if period is not None: del matches[idx] break # for date+time, use 0 seconds if seconds are missing if 's' in order and len(matches) == 5: matches.insert(order['s'], 0) values = {} for key, idx in order.iteritems(): if idx < len(matches): value = matches[idx] if key == 'y': if len(value) == 2 and value.isdigit(): value = '20' + value values[key] = value if 'y' not in values or 'M' not in values or 'd' not in values: raise ValueError for key in ('y', 'M', 'd'): value = values[key] value = month_names.get(value) if value is not None: if key == 'M': values[key] = value else: values[key], values['M'] = values['M'], value break values = {key: int(value) for key, value in values.iteritems()} values.setdefault('h', 0) values.setdefault('m', 0) values.setdefault('s', 0) if period and values['h'] <= 12: if period == 'am': values['h'] %= 12 elif period == 'pm': values['h'] = values['h'] % 12 + 12 t = tzinfo.localize(datetime(*(values[k] for k in 'yMdhms'))) return tzinfo.normalize(t)
def _i18n_parse_date_0(text, order, regexp, period_names, month_names, tzinfo): matches = regexp.findall(text) if not matches: return None period = None for idx, match in enumerate(matches): period = period_names.get(match) if period is not None: del matches[idx] break if len(matches) == 5: matches.insert(order['s'], 0) values = {} for key, idx in order.iteritems(): if idx < len(matches): value = matches[idx] if key == 'y': if len(value) == 2 and value.isdigit(): value = '20' + value values[key] = value if 'y' not in values or 'M' not in values or 'd' not in values: raise ValueError for key in ('y', 'M', 'd'): value = values[key] value = month_names.get(value) if value is not None: if key == 'M': values[key] = value else: values[key], values['M'] = values['M'], value break values = dict((key, int(value)) for key, value in values.iteritems()) values.setdefault('h', 0) values.setdefault('m', 0) values.setdefault('s', 0) if period and values['h'] <= 12: if period == 'am': values['h'] %= 12 elif period == 'pm': values['h'] = values['h'] % 12 + 12 t = tzinfo.localize(datetime(*(values[k] for k in 'yMdhms'))) if hasattr(tzinfo, 'normalize'): # pytz t = tzinfo.normalize(t) return t
def _i18n_parse_date_0(text, order, regexp, period_names, month_names, tzinfo): matches = regexp.findall(text) if not matches: return None # remove am/pm markers on ahead period = None for idx, match in enumerate(matches): period = period_names.get(match) if period is not None: del matches[idx] break # for date+time, use 0 seconds if seconds are missing if 's' in order and len(matches) == 5: matches.insert(order['s'], 0) values = {} for key, idx in order.iteritems(): if idx < len(matches): value = matches[idx] if key == 'y': if len(value) == 2 and value.isdigit(): value = '20' + value values[key] = value if 'y' not in values or 'M' not in values or 'd' not in values: raise ValueError for key in ('y', 'M', 'd'): value = values[key] value = month_names.get(value) if value is not None: if key == 'M': values[key] = value else: values[key], values['M'] = values['M'], value break values = dict((key, int(value)) for key, value in values.iteritems()) values.setdefault('h', 0) values.setdefault('m', 0) values.setdefault('s', 0) if period and values['h'] <= 12: if period == 'am': values['h'] %= 12 elif period == 'pm': values['h'] = values['h'] % 12 + 12 t = tzinfo.localize(datetime(*(values[k] for k in 'yMdhms'))) return tzinfo.normalize(t)
def _libc_parse_date(text, tzinfo): for format in ('%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', '%b %d, %Y'): try: tm = time.strptime(text, format) dt = tzinfo.localize(datetime(*tm[0:6])) return tzinfo.normalize(dt) except (ValueError, OverflowError): continue try: return _i18n_parse_date(text, tzinfo, None) except (ValueError, OverflowError): pass return
def _libc_parse_date(text, tzinfo): for format in ('%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', '%b %d, %Y'): try: tm = time.strptime(text, format) dt = tzinfo.localize(datetime(*tm[0:6])) return tzinfo.normalize(dt) except ValueError: continue try: return _i18n_parse_date(text, tzinfo, None) except ValueError: pass return
def parse_time(value, tzinfo): """Parse Twitter API time format. >>> parse_time("Sun Dec 14 11:29:30 +0000 2008", StaticTzInfo(0)) datetime(2008, 12, 14, 11, 29, 30) >>> parse_time("Sun Dec 14 11:29:30 +0000 2008", StaticTzInfo(8)) datetime(2008, 12, 22, 11, 29, 30) """ if not value: return None day, month, date, time, timezone, year = value.lower().split() hour, min, sec = time.split(u":") utc_dt = datetime(int(year), int(MONTHS[month]), int(date), int(hour), int(min), int(sec)) return tzinfo.localize(utc_dt)
def replace_tzinfo(cls, dt: datetime, tzinfo: tzinfo, is_dst=True): """ This method does not convert timezone, it simply set the timezone to specified timezone. :param date_time: if this datetime has tzinfo, it will be overridden :param tzinfo: timezone :rtype: datetime """ # datetime.replace(tzinfo=user_tz) => sometime this change the datetime value # http://stackoverflow.com/questions/27531718/datetime-timezone-conversion-using-pytz # use localize instead if dt.tzinfo is not None: dt = dt.replace(tzinfo=None) local = tzinfo.localize(dt, is_dst=is_dst) return tzinfo.normalize(local)
def parse_date(text, tzinfo=None, locale=None, hint='date'): tzinfo = tzinfo or localtz text = text.strip() dt = _parse_date_iso8601(text, tzinfo) if dt is None and locale != 'iso8601': if babel and locale: dt = _i18n_parse_date(text, tzinfo, locale) else: for format in [ '%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', '%b %d, %Y' ]: try: tm = time.strptime(text, format) dt = tzinfo.localize(datetime(*tm[0:6])) if hasattr(tzinfo, 'normalize'): # pytz dt = tzinfo.normalize(dt) break except ValueError: continue if dt is None: dt = _parse_relative_time(text, tzinfo) if dt is None: hint = { 'datetime': get_datetime_format_hint, 'date': get_date_format_hint }.get(hint, lambda (l): hint)(locale) raise TracError( _( '"%(date)s" is an invalid date, or the date format ' 'is not known. Try "%(hint)s" instead.', date=text, hint=hint), _('Invalid Date')) # Make sure we can convert it to a timestamp and back - fromtimestamp() # may raise ValueError if larger than platform C localtime() or gmtime() try: to_datetime(to_timestamp(dt), tzinfo) except ValueError: raise TracError( _( 'The date "%(date)s" is outside valid range. ' 'Try a date closer to present time.', date=text), _('Invalid Date')) return dt
def parse_date(text, tzinfo=None, locale=None, hint='date'): tzinfo = tzinfo or localtz text = text.strip() dt = _parse_date_iso8601(text, tzinfo) if dt is None and locale != 'iso8601': if babel and locale: dt = _i18n_parse_date(text, tzinfo, locale) else: for format in ['%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', '%b %d, %Y']: try: tm = time.strptime(text, format) dt = tzinfo.localize(datetime(*tm[0:6])) dt = tzinfo.normalize(dt) break except ValueError: continue if dt is None: dt = _parse_relative_time(text, tzinfo) if dt is None: hint = {'datetime': get_datetime_format_hint, 'date': get_date_format_hint, 'relative': get_datetime_format_hint }.get(hint, lambda(l): hint)(locale) raise TracError(_('"%(date)s" is an invalid date, or the date format ' 'is not known. Try "%(hint)s" instead.', date=text, hint=hint), _('Invalid Date')) # Make sure we can convert it to a timestamp and back - fromtimestamp() # may raise ValueError if larger than platform C localtime() or gmtime() try: datetime.utcfromtimestamp(to_timestamp(dt)) except ValueError: raise TracError(_('The date "%(date)s" is outside valid range. ' 'Try a date closer to present time.', date=text), _('Invalid Date')) return dt
def parse_date(text, tzinfo=None, hint='date'): tzinfo = tzinfo or localtz dt = None text = text.strip() # normalize ISO time match = _ISO_8601_RE.match(text) if match: try: g = match.groups() years = g[0] months = g[1] or '01' days = g[2] or '01' hours, minutes, seconds = [x or '00' for x in g[3:6]] z, tzsign, tzhours, tzminutes = g[6:10] if z: tz = timedelta(hours=int(tzhours or '0'), minutes=int(tzminutes or '0')).seconds / 60 if tz == 0: tzinfo = utc else: tzinfo = FixedOffset( tzsign == '-' and -tz or tz, '%s%s:%s' % (tzsign, tzhours, tzminutes)) tm = time.strptime( '%s ' * 6 % (years, months, days, hours, minutes, seconds), '%Y %m %d %H %M %S ') dt = tzinfo.localize(datetime(*tm[0:6])) except ValueError: pass if dt is None: for format in [ '%x %X', '%x, %X', '%X %x', '%X, %x', '%x', '%c', '%b %d, %Y' ]: try: tm = time.strptime(text, format) dt = tzinfo.localize(datetime(*tm[0:6])) break except ValueError: continue if dt is None: dt = _parse_relative_time(text, tzinfo) if dt is None: hint = { 'datetime': get_datetime_format_hint, 'date': get_date_format_hint }.get(hint, lambda: hint)() raise TracError( _( '"%(date)s" is an invalid date, or the date format ' 'is not known. Try "%(hint)s" instead.', date=text, hint=hint), _('Invalid Date')) # Make sure we can convert it to a timestamp and back - fromtimestamp() # may raise ValueError if larger than platform C localtime() or gmtime() try: to_datetime(to_timestamp(dt), tzinfo) except ValueError: raise TracError( _( 'The date "%(date)s" is outside valid range. ' 'Try a date closer to present time.', date=text), _('Invalid Date')) return dt
def localize(dt, tzinfo): if hasattr(tzinfo, 'localize'): return tzinfo.localize(dt) return normalize(dt.replace(tzinfo=tzinfo))