summaryrefslogtreecommitdiff
path: root/paste/util/dateinterval.py
diff options
context:
space:
mode:
Diffstat (limited to 'paste/util/dateinterval.py')
-rw-r--r--paste/util/dateinterval.py104
1 files changed, 104 insertions, 0 deletions
diff --git a/paste/util/dateinterval.py b/paste/util/dateinterval.py
new file mode 100644
index 0000000..023bce4
--- /dev/null
+++ b/paste/util/dateinterval.py
@@ -0,0 +1,104 @@
+"""
+DateInterval.py
+
+Convert interval strings (in the form of 1w2d, etc) to
+seconds, and back again. Is not exactly about months or
+years (leap years in particular).
+
+Accepts (y)ear, (b)month, (w)eek, (d)ay, (h)our, (m)inute, (s)econd.
+
+Exports only timeEncode and timeDecode functions.
+"""
+
+import re
+
+__all__ = ['interval_decode', 'interval_encode']
+
+second = 1
+minute = second*60
+hour = minute*60
+day = hour*24
+week = day*7
+month = day*30
+year = day*365
+timeValues = {
+ 'y': year,
+ 'b': month,
+ 'w': week,
+ 'd': day,
+ 'h': hour,
+ 'm': minute,
+ 's': second,
+ }
+timeOrdered = list(timeValues.items())
+timeOrdered.sort(key=lambda x: x[1], reverse=True)
+
+
+def interval_encode(seconds, include_sign=False):
+ """Encodes a number of seconds (representing a time interval)
+ into a form like 1h2d3s.
+
+ >>> interval_encode(10)
+ '10s'
+ >>> interval_encode(493939)
+ '5d17h12m19s'
+ """
+ s = ''
+ orig = seconds
+ seconds = abs(seconds)
+ for char, amount in timeOrdered:
+ if seconds >= amount:
+ i, seconds = divmod(seconds, amount)
+ s += '%i%s' % (i, char)
+ if orig < 0:
+ s = '-' + s
+ elif not orig:
+ return '0'
+ elif include_sign:
+ s = '+' + s
+ return s
+
+_timeRE = re.compile(r'[0-9]+[a-zA-Z]')
+def interval_decode(s):
+ """Decodes a number in the format 1h4d3m (1 hour, 3 days, 3 minutes)
+ into a number of seconds
+
+ >>> interval_decode('40s')
+ 40
+ >>> interval_decode('10000s')
+ 10000
+ >>> interval_decode('3d1w45s')
+ 864045
+ """
+ time = 0
+ sign = 1
+ s = s.strip()
+ if s.startswith('-'):
+ s = s[1:]
+ sign = -1
+ elif s.startswith('+'):
+ s = s[1:]
+ for match in allMatches(s, _timeRE):
+ char = match.group(0)[-1].lower()
+ if char not in timeValues:
+ # @@: should signal error
+ continue
+ time += int(match.group(0)[:-1]) * timeValues[char]
+ return time
+
+# @@-sgd 2002-12-23 - this function does not belong in this module, find a better place.
+def allMatches(source, regex):
+ """Return a list of matches for regex in source
+ """
+ pos = 0
+ end = len(source)
+ rv = []
+ match = regex.search(source, pos)
+ while match:
+ rv.append(match)
+ match = regex.search(source, match.end() )
+ return rv
+
+if __name__ == '__main__':
+ import doctest
+ doctest.testmod()