Source code for stompy.parse_interval

""" Some convenience routines for parsing interval inputs
"""
from __future__ import division
from __future__ import print_function

import datetime
from matplotlib.dates import date2num,num2date
import pytz

units_to_days = {'d':1.0,
                 'h':1.0/24.0,
                 'm':1.0/(60.0*24.0),
                 's':1.0/(3600.0*24.0)}

                 
[docs]def parse_date_or_interval(s): if s[0] in "+-": # it's an interval val = float(s[:-1]) units = s[-1] print("Got interval: ",val,units) val = val * units_to_days[units] return val else: # Must be a date: year=0 month=1 day=1 hour=0 minute=0 second=0 if len(s) < 4: raise Exception("%s: bad date. wanted YYYYMMDDHHmmss or prefix thereof"%s) if len(s) >= 4: year = int(s[:4]) if len(s) >= 6: month = int(s[4:6]) if len(s) >= 8: day = int(s[6:8]) if len(s) >= 10: hour = int(s[8:10]) if len(s) >= 12: minute = int(s[10:12]) if len(s) >= 14: second = int(s[12:14]) if len(s) > 14: raise Exception("Extra characters in date: %s"%s) d = datetime.datetime(year,month,day,hour,minute,second,tzinfo=pytz.timezone('utc')) return d
[docs]def parse_interval(s,default_start=None,default_end=None,default_days=None): """ s: the string to parse. Format of s is start_spec:end_spec start_spec :end_spec Each can be either a date in YYYYMMDDHHMMSS format or a signed offset +/-XXXXunits the leading + or - *MUST* be included where units is d for days, h for hours, m for minutes, s for seconds returns a pair of python datetime instances """ inputs = 0 if default_start is not None: inputs += 1 if default_end is not None: inputs += 1 if default_days is not None: inputs += 1 if inputs!=2: raise Exception("parse_interval expects exactly two of the defaults to be set") if default_start is None: default_start = default_end - datetime.timedelta(default_days) if default_end is None: default_end = default_start + datetime.timedelta(default_days) # do it. if ':' in s: a,b = s.split(':') if a != "": default_start = parse_date_or_interval(a) if b != "": default_end = parse_date_or_interval(b) if not isinstance(default_start,datetime.datetime): default_start = default_end + default_start elif not isinstance(default_end,datetime.datetime): default_end = default_start + datetime.timedelta(default_end) elif s not in [None,'']: # This part is more slippery... # parse the one value we've got. # if it's a date, it's the start date and interval is unchanged # if it's an interval, then decide based on the sign. a = parse_date_or_interval(s) if isinstance(a,datetime.datetime): default_start = a default_end = a+datetime.timedelta(default_days) else: if a<0: default_start = default_end + datetime.timedelta(a) else: default_end = default_start + datetime.timedelta(a) else: print("No interval string specified") if date2num(default_start) > date2num(default_end): raise Exception("Bad date range: %s -> %s"%(default_start,default_end)) return default_start,default_end