1""" 2DateInterval.py 3 4Convert interval strings (in the form of 1w2d, etc) to 5seconds, and back again. Is not exactly about months or 6years (leap years in particular). 7 8Accepts (y)ear, (b)month, (w)eek, (d)ay, (h)our, (m)inute, (s)econd. 9 10Exports only timeEncode and timeDecode functions. 11""" 12 13import re 14 15__all__ = ['interval_decode', 'interval_encode'] 16 17second = 1 18minute = second*60 19hour = minute*60 20day = hour*24 21week = day*7 22month = day*30 23year = day*365 24timeValues = { 25 'y': year, 26 'b': month, 27 'w': week, 28 'd': day, 29 'h': hour, 30 'm': minute, 31 's': second, 32 } 33timeOrdered = list(timeValues.items()) 34timeOrdered.sort(key=lambda x: x[1], reverse=True) 35 36 37def 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]') 62def 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. 90def 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 102if __name__ == '__main__': 103 import doctest 104 doctest.testmod() 105