2008-04-27 16:54:37 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2008-06-19 09:21:21 +00:00
|
|
|
# vi:si:et:sw=4:sts=4:ts=4
|
2008-04-28 07:48:13 +00:00
|
|
|
import math
|
2008-04-27 16:54:37 +00:00
|
|
|
import re
|
|
|
|
|
|
|
|
def to36(q):
|
2008-06-19 09:21:21 +00:00
|
|
|
"""
|
|
|
|
Converts an integer to base 36 (a useful scheme for human-sayable IDs).
|
|
|
|
|
|
|
|
>>> to36(35)
|
|
|
|
'z'
|
|
|
|
>>> to36(119292)
|
|
|
|
'2k1o'
|
|
|
|
>>> int(to36(939387374), 36)
|
|
|
|
939387374
|
|
|
|
>>> to36(0)
|
|
|
|
'0'
|
|
|
|
>>> to36(-393)
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
ValueError: must supply a positive integer
|
|
|
|
"""
|
|
|
|
if q < 0: raise ValueError, "must supply a positive integer"
|
|
|
|
letters = "0123456789abcdefghijklmnopqrstuvwxyz"
|
|
|
|
converted = []
|
|
|
|
while q != 0:
|
|
|
|
q, r = divmod(q, 36)
|
|
|
|
converted.insert(0, letters[r])
|
|
|
|
return "".join(converted) or '0'
|
2008-04-27 16:54:37 +00:00
|
|
|
|
|
|
|
def from36(q):
|
2008-06-19 09:21:21 +00:00
|
|
|
return int(q, 36)
|
2008-04-27 16:54:37 +00:00
|
|
|
|
|
|
|
def intValue(strValue, default=''):
|
2008-06-19 09:21:21 +00:00
|
|
|
try:
|
|
|
|
val = re.compile('(\d+)').findall(unicode(strValue).strip())[0]
|
|
|
|
except:
|
|
|
|
val = default
|
|
|
|
return val
|
2008-04-27 16:54:37 +00:00
|
|
|
|
2008-05-05 18:12:27 +00:00
|
|
|
def test_intValue():
|
2008-06-19 09:21:21 +00:00
|
|
|
assert intValue('abc23') == '23'
|
|
|
|
assert intValue(' abc23') == '23'
|
|
|
|
assert intValue(' abc') == ''
|
2008-05-05 18:12:27 +00:00
|
|
|
|
2008-04-27 16:54:37 +00:00
|
|
|
def floatValue(strValue, default=''):
|
2008-06-19 09:21:21 +00:00
|
|
|
try:
|
|
|
|
val = re.compile('([\d.]+)').findall(unicode(strValue).strip())[0]
|
|
|
|
except:
|
|
|
|
val = default
|
|
|
|
return val
|
2008-04-27 16:54:37 +00:00
|
|
|
|
2008-05-05 18:12:27 +00:00
|
|
|
def test_floatValue():
|
2008-06-19 09:21:21 +00:00
|
|
|
assert floatValue('abc23.4') == '23.4'
|
|
|
|
assert floatValue(' abc23.4') == '23.4'
|
|
|
|
assert floatValue(' abc') == ''
|
2008-05-05 18:12:27 +00:00
|
|
|
|
2008-04-28 07:48:13 +00:00
|
|
|
def formatNumber(number, longName, shortName):
|
2008-06-19 09:21:21 +00:00
|
|
|
"""
|
|
|
|
Return the number in a human-readable format (23 KB, 23.4 MB, 23.42 GB)
|
|
|
|
|
|
|
|
>>> formatNumber(123, 'Byte', 'B')
|
|
|
|
'123 Bytes'
|
2008-05-05 18:12:27 +00:00
|
|
|
|
2008-06-19 09:21:21 +00:00
|
|
|
>>> formatNumber(1234, 'Byte', 'B')
|
|
|
|
'1 KB'
|
2008-05-05 18:12:27 +00:00
|
|
|
|
2008-06-19 09:21:21 +00:00
|
|
|
>>> formatNumber(1234567, 'Byte', 'B')
|
|
|
|
'1.2 MB'
|
2008-05-05 18:12:27 +00:00
|
|
|
|
2008-06-19 09:21:21 +00:00
|
|
|
>>> formatNumber(1234567890, 'Byte', 'B')
|
|
|
|
'1.15 GB'
|
2008-05-05 18:12:27 +00:00
|
|
|
|
2008-06-19 09:21:21 +00:00
|
|
|
>>> formatNumber(1234567890123456789, 'Byte', 'B')
|
|
|
|
'1,096.5166 PB'
|
2008-05-05 18:12:27 +00:00
|
|
|
|
2008-06-19 09:21:21 +00:00
|
|
|
"""
|
|
|
|
if number < 1024:
|
|
|
|
return '%s %s%s' % (formatThousands(number), longName, number != 1 and 's' or '')
|
|
|
|
prefix = ['K', 'M', 'G', 'T', 'P']
|
|
|
|
for i in range(5):
|
|
|
|
if number < math.pow(1024, i + 2) or i == 4:
|
|
|
|
n = number / math.pow(1024, i + 1)
|
|
|
|
return '%s %s%s' % (formatThousands('%.*f' % (i, n)), prefix[i], shortName)
|
2008-04-28 09:25:52 +00:00
|
|
|
|
|
|
|
def formatThousands(number, separator = ','):
|
2008-06-19 09:21:21 +00:00
|
|
|
"""
|
|
|
|
Return the number with separators (1,000,000)
|
|
|
|
|
|
|
|
>>> formatThousands(1)
|
|
|
|
'1'
|
|
|
|
>>> formatThousands(1000)
|
|
|
|
'1,000'
|
|
|
|
>>> formatThousands(1000000)
|
|
|
|
'1,000,000'
|
|
|
|
"""
|
|
|
|
string = str(number).split('.')
|
|
|
|
l = []
|
|
|
|
for i, character in enumerate(reversed(string[0])):
|
|
|
|
if i and (not (i % 3)):
|
|
|
|
l.insert(0, separator)
|
|
|
|
l.insert(0, character)
|
|
|
|
string[0] = ''.join(l)
|
|
|
|
return '.'.join(string)
|
2008-04-28 07:48:13 +00:00
|
|
|
|
|
|
|
def formatBits(number):
|
2008-06-19 09:21:21 +00:00
|
|
|
return formatNumber(number, 'bit', 'b')
|
2008-04-27 16:54:37 +00:00
|
|
|
|
|
|
|
def formatBytes(number):
|
2008-06-19 09:21:21 +00:00
|
|
|
return formatNumber(number, 'byte', 'B')
|
2008-04-27 16:54:37 +00:00
|
|
|
|
2008-04-28 07:48:13 +00:00
|
|
|
def formatPixels(number):
|
2008-06-19 09:21:21 +00:00
|
|
|
return formatNumber(number, 'pixel', 'px')
|
2008-04-28 07:48:13 +00:00
|
|
|
|
2008-06-19 14:23:08 +00:00
|
|
|
def formatCurrency(amount, currency="$"):
|
|
|
|
if amount:
|
|
|
|
temp = "%.2f" % amount
|
|
|
|
profile=re.compile(r"(\d)(\d\d\d[.,])")
|
|
|
|
while 1:
|
|
|
|
temp, count = re.subn(profile,r"\1,\2",temp)
|
|
|
|
if not count:
|
|
|
|
break
|
|
|
|
if temp.startswith('-'):
|
|
|
|
return "-"+ currency + temp[1:-3]
|
|
|
|
return currency + temp[:-3]
|
|
|
|
else:
|
|
|
|
return ""
|
|
|
|
|
2008-04-27 16:54:37 +00:00
|
|
|
def plural(amount, unit, plural='s'):
|
2008-06-19 09:21:21 +00:00
|
|
|
'''
|
|
|
|
>>> plural(1, 'unit')
|
|
|
|
'1 unit'
|
|
|
|
>>> plural(2, 'unit')
|
|
|
|
'2 units'
|
|
|
|
'''
|
|
|
|
if abs(amount) != 1:
|
|
|
|
if plural == 's':
|
|
|
|
unit = unit + plural
|
|
|
|
else: unit = plural
|
|
|
|
return "%s %s" % (formatThousands(amount), unit)
|
2008-04-27 16:54:37 +00:00
|
|
|
|
2008-04-27 17:17:29 +00:00
|
|
|
def ms2runtime(ms):
|
2008-06-19 09:21:21 +00:00
|
|
|
'''
|
|
|
|
>>> ms2runtime(5000)
|
|
|
|
'5 seconds'
|
|
|
|
>>> ms2runtime(500000)
|
|
|
|
'8 minutes 20 seconds'
|
|
|
|
>>> ms2runtime(50000000)
|
|
|
|
'13 hours 53 minutes 20 seconds'
|
|
|
|
>>> ms2runtime(50000000-20000)
|
|
|
|
'13 hours 53 minutes'
|
|
|
|
'''
|
|
|
|
seconds = int(ms / 1000)
|
|
|
|
years = 0
|
|
|
|
days = 0
|
|
|
|
hours = 0
|
|
|
|
minutes = 0
|
|
|
|
if seconds >= 60:
|
|
|
|
minutes = int(seconds / 60)
|
|
|
|
seconds = seconds % 60
|
|
|
|
if minutes >= 60:
|
|
|
|
hours = int(minutes / 60)
|
|
|
|
minutes = minutes % 60
|
|
|
|
if hours >= 24:
|
|
|
|
days = int(hours / 24)
|
|
|
|
hours = hours % 24
|
|
|
|
if days >= 365:
|
|
|
|
years = int(days / 365)
|
|
|
|
days = days % 365
|
|
|
|
runtimeString = (plural(years, 'year'), plural(days, 'day'),
|
|
|
|
plural(hours,'hour'), plural(minutes, 'minute'), plural(seconds, 'second'))
|
|
|
|
runtimeString = filter(lambda x: not x.startswith('0'), runtimeString)
|
|
|
|
return " ".join(runtimeString).strip()
|
2008-04-27 17:17:29 +00:00
|
|
|
|
|
|
|
def ms2playtime(ms):
|
2008-06-19 09:21:21 +00:00
|
|
|
'''
|
|
|
|
>>> ms2playtime(5000)
|
|
|
|
'00:05'
|
|
|
|
>>> ms2playtime(500000)
|
|
|
|
'08:20'
|
|
|
|
>>> ms2playtime(50000000)
|
|
|
|
'13:53:20'
|
|
|
|
'''
|
|
|
|
it = int(ms / 1000)
|
|
|
|
ms = ms - it*1000
|
|
|
|
ss = it % 60
|
|
|
|
mm = ((it-ss)/60) % 60
|
|
|
|
hh = ((it-(mm*60)-ss)/3600) % 60
|
2008-06-19 14:18:49 +00:00
|
|
|
if hh >= 24:
|
|
|
|
dd = int(hh / 24)
|
|
|
|
hh = hh % 24
|
|
|
|
playtime= "%d:%02d:%02d:%02d" % (dd, hh, mm, ss)
|
2008-06-19 09:21:21 +00:00
|
|
|
if hh:
|
|
|
|
playtime= "%02d:%02d:%02d" % (hh, mm, ss)
|
|
|
|
else:
|
|
|
|
playtime= "%02d:%02d" % (mm, ss)
|
|
|
|
return playtime
|
2008-04-27 17:17:29 +00:00
|
|
|
|
|
|
|
def ms2time(ms):
|
2008-06-19 09:21:21 +00:00
|
|
|
'''
|
|
|
|
>>> ms2time(44592123)
|
|
|
|
'12:23:12.123'
|
|
|
|
'''
|
|
|
|
it = int(ms / 1000)
|
|
|
|
ms = ms - it*1000
|
|
|
|
ss = it % 60
|
|
|
|
mm = ((it-ss)/60) % 60
|
|
|
|
hh = ((it-(mm*60)-ss)/3600) % 60
|
|
|
|
return "%d:%02d:%02d.%03d" % (hh, mm, ss, ms)
|
2008-04-27 17:17:29 +00:00
|
|
|
|
|
|
|
def time2ms(timeString):
|
2008-06-19 09:21:21 +00:00
|
|
|
'''
|
|
|
|
>>> time2ms('12:23:12.123')
|
|
|
|
44592123
|
|
|
|
'''
|
|
|
|
ms = 0.0
|
|
|
|
p = timeString.split(':')
|
|
|
|
for i in range(len(p)):
|
|
|
|
ms = ms * 60 + float(p[i])
|
|
|
|
return int(ms * 1000)
|
2008-04-27 17:17:29 +00:00
|
|
|
|
|
|
|
def shiftTime(offset, timeString):
|
2008-06-19 09:21:21 +00:00
|
|
|
newTime = time2ms(timeString) + offset
|
|
|
|
return ms2time(newTime)
|
2008-04-27 17:17:29 +00:00
|
|
|
|