#!/usr/bin/env python #coding:utf-8 # Purpose: timeparser # Created: 29.01.2011 # Copyright (C) , Manfred Moitzi # License: MIT license from __future__ import unicode_literals, print_function, division __author__ = "mozman " import re from datetime import date, timedelta, datetime from .compatibility import tostr, is_string DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S" DATE_FORMAT = "%Y-%m-%d" class TimeParser(object): duration_matcher = re.compile("^P(\d+Y)?(\d+M)?(\d+D)?(?:T(\d+H)?(\d+M)?(\d+(?:,\d+)?S)?)?$") def __init__(self, time): if is_string(time): self.timestr = time self.value = TimeParser.parse(time) else: self.value = time self.timestr = tostr(self) def __str__(self): if self.is_date: if self.has_time: string = self.value.strftime(DATETIME_FORMAT) else: string = self.value.strftime(DATE_FORMAT) else: string = TimeParser.duration_to_string(self.value) return string @staticmethod def parse(timestr): if timestr.startswith('P'): value = TimeParser.duration_parser(timestr) else: if 'T' in timestr: value = datetime.strptime(timestr, DATETIME_FORMAT) else: value = datetime.strptime(timestr, DATE_FORMAT).date() return value @property def is_date(self): return isinstance(self.value, date) @property def has_time(self): return isinstance(self.value, datetime) @property def is_duration(self): return isinstance(self.value, timedelta) @staticmethod def duration_parser(duration): def clean(timepart): result = 0 if timepart: timepart = timepart[:-1].replace(',', '.') result = float(timepart) return result matchresult = TimeParser.duration_matcher.match(duration) if matchresult: timeparts = [clean(part) for part in matchresult.groups()] years, months, days, hours, minutes, seconds = timeparts days = years * 365 + months * 30 + days else: raise ValueError('not a valid duration: %s' % duration) return timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds) @staticmethod def duration_to_string(duration): def get_time(seconds): hours = int(seconds / 3600) seconds = seconds % 3600 minutes = int(seconds / 60) seconds = seconds % 60 return (hours, minutes, seconds) timeparts = ["P%dD" % duration.days] if duration.days else ["P"] timeparts.append("T%02dH%02dM%02d" % get_time(duration.seconds)) micros = duration.microseconds if micros > 0: micros_str = ",%06d" % micros timeparts.append("%sS" % micros_str[:5]) else: timeparts.append("S") return ''.join(timeparts)