1 """ 2 DateInterval.py 3 4 Convert interval strings (in the form of 1w2d, etc) to 5 seconds, and back again. Is not exactly about months or 6 years (leap years in particular). 7 8 Accepts (y)ear, (b)month, (w)eek, (d)ay, (h)our, (m)inute, (s)econd. 9 10 Exports only timeEncode and timeDecode functions. 11 """ 12 13 import re 14 15 __all__ = ['interval_decode', 'interval_encode'] 16 17 second = 1 18 minute = second*60 19 hour = minute*60 20 day = hour*24 21 week = day*7 22 month = day*30 23 year = day*365 24 timeValues = { 25 'y': year, 26 'b': month, 27 'w': week, 28 'd': day, 29 'h': hour, 30 'm': minute, 31 's': second, 32 } 33 timeOrdered = list(timeValues.items()) 34 timeOrdered.sort(key=lambda x: x[1], reverse=True) 35 36 37 def interval_encode(seconds, include_sign=False): 38 """Encodes a number of seconds (representing a time interval) 39 into a form like 1h2d3s. 40 41 >>> interval_encode(10) 42 '10s' 43 >>> interval_encode(493939) 44 '5d17h12m19s' 45 """ 46 s = '' 47 orig = seconds 48 seconds = abs(seconds) 49 for char, amount in timeOrdered: 50 if seconds >= amount: 51 i, seconds = divmod(seconds, amount) 52 s += '%i%s' % (i, char) 53 if orig < 0: 54 s = '-' + s 55 elif not orig: 56 return '0' 57 elif include_sign: 58 s = '+' + s 59 return s 60 61 _timeRE = re.compile(r'[0-9]+[a-zA-Z]') 62 def interval_decode(s): 63 """Decodes a number in the format 1h4d3m (1 hour, 3 days, 3 minutes) 64 into a number of seconds 65 66 >>> interval_decode('40s') 67 40 68 >>> interval_decode('10000s') 69 10000 70 >>> interval_decode('3d1w45s') 71 864045 72 """ 73 time = 0 74 sign = 1 75 s = s.strip() 76 if s.startswith('-'): 77 s = s[1:] 78 sign = -1 79 elif s.startswith('+'): 80 s = s[1:] 81 for match in allMatches(s, _timeRE): 82 char = match.group(0)[-1].lower() 83 if char not in timeValues: 84 # @@: should signal error 85 continue 86 time += int(match.group(0)[:-1]) * timeValues[char] 87 return time 88 89 # @@-sgd 2002-12-23 - this function does not belong in this module, find a better place. 90 def allMatches(source, regex): 91 """Return a list of matches for regex in source 92 """ 93 pos = 0 94 end = len(source) 95 rv = [] 96 match = regex.search(source, pos) 97 while match: 98 rv.append(match) 99 match = regex.search(source, match.end() ) 100 return rv 101 102 if __name__ == '__main__': 103 import doctest 104 doctest.testmod() 105