X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Futil%2Fsfatime.py;h=743566739aaf530dcad2f6c477a5d693e1574040;hb=30d9951e075d93127c3909dcb41be09b420b3525;hp=d14f44b0a52646077e81bfd6b191f9ca3bee8f90;hpb=d748c93a11a23b22d9e310db3c58c2bfb18b38fb;p=sfa.git diff --git a/sfa/util/sfatime.py b/sfa/util/sfatime.py index d14f44b0..74356673 100644 --- a/sfa/util/sfatime.py +++ b/sfa/util/sfatime.py @@ -20,12 +20,16 @@ # OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS # IN THE WORK. #---------------------------------------------------------------------- -from types import StringTypes -import dateutil.parser -import datetime +from __future__ import print_function + import time +import datetime +import dateutil.parser +import calendar +import re from sfa.util.sfalogging import logger +from sfa.util.py23 import StringType SFATIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" @@ -35,18 +39,38 @@ the timezone, so that it's compatible with normal datetime.datetime objects. For safety this can also handle inputs that are either timestamps, or datetimes """ + + def handle_shorthands (input): + """recognize string like +5d or +3w or +2m as + 2 days, 3 weeks or 2 months from now""" + if input.startswith('+'): + match=re.match (r"([0-9]+)([dwm])",input[1:]) + if match: + how_many=int(match.group(1)) + what=match.group(2) + if what == 'd': d=datetime.timedelta(days=how_many) + elif what == 'w': d=datetime.timedelta(weeks=how_many) + elif what == 'm': d=datetime.timedelta(weeks=4*how_many) + return datetime.datetime.utcnow()+d + # prepare the input for the checks below by # casting strings ('1327098335') to ints - if isinstance(input, StringTypes): + if isinstance(input, StringType): try: input = int(input) except ValueError: - pass + try: + new_input=handle_shorthands(input) + if new_input is not None: input=new_input + except: + import traceback + traceback.print_exc() + #################### here we go if isinstance (input, datetime.datetime): - logger.warn ("argument to utcparse already a datetime - doing nothing") + #logger.info ("argument to utcparse already a datetime - doing nothing") return input - elif isinstance (input, StringTypes): + elif isinstance (input, StringType): t = dateutil.parser.parse(input) if t.utcoffset() is not None: t = t.utcoffset() + t.replace(tzinfo=None) @@ -56,18 +80,38 @@ For safety this can also handle inputs that are either timestamps, or datetimes else: logger.error("Unexpected type in utcparse [%s]"%type(input)) -def datetime_to_string(input): - return datetime.datetime.strftime(input, SFATIME_FORMAT) +def datetime_to_string(dt): + return datetime.datetime.strftime(dt, SFATIME_FORMAT) -def datetime_to_utc(input): - return time.gmtime(datetime_to_epoch(input)) +def datetime_to_utc(dt): + return time.gmtime(datetime_to_epoch(dt)) -def datetime_to_epoch(input): - return int(time.mktime(input.timetuple())) +# see https://docs.python.org/2/library/time.html +# all timestamps are in UTC so time.mktime() would be *wrong* +def datetime_to_epoch(dt): + return int(calendar.timegm(dt.timetuple())) -def adjust_datetime(input, days=0, hours=0, minutes=0, seconds=0): +def add_datetime(input, days=0, hours=0, minutes=0, seconds=0): """ Adjust the input date by the specified delta (in seconds). """ dt = utcparse(input) return dt + datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds) + +if __name__ == '__main__': + # checking consistency + print(20*'X') + print(("Should be close to zero: %s"%(datetime_to_epoch(datetime.datetime.utcnow())-time.time()))) + print(20*'X') + for input in [ + '+2d', + '+3w', + '+2m', + 1401282977.575632, + 1401282977, + '1401282977', + '2014-05-28', + '2014-05-28T15:18', + '2014-05-28T15:18:30', + ]: + print("input=%20s -> parsed %s"%(input,datetime_to_string(utcparse(input))))