Coverage for lino/utils/quantities.py : 41%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: UTF-8 -*- # Copyright 2012-2015 Luc Saffre # License: BSD (see file COPYING for details)
A :class:`Duration` is a Decimal expressed in ``hh:mm`` format. A :class:`Percentage` is a Decimal expressed in ``x%`` format.
Usage examples:
The `parse` function ====================
>>> parse('1') Decimal('1') >>> parse('1:15') Duration('1:15') >>> parse('33%') Percentage('33%')
>>> lines = [] >>> lines.append('repr(x) str(x) x*3 x*100') >>> lines.append('------------------- ------- ------ ------') >>> for s in '2', '2.5', '33%', '2:30', '0:20': ... v = parse(s) ... lines.append("%-20s %6s %6s %6s" % (repr(v), v, v*3, v*100)) >>> print '\n'.join(lines) repr(x) str(x) x*3 x*100 ------------------- ------- ------ ------ Decimal('2') 2 6 200 Decimal('2.5') 2.5 7.5 250.0 Percentage('33%') 33% 0.99 33.00 Duration('2:30') 2:30 7:30 250:00 Duration('0:20') 0:20 1:00 33:20
Formatting ==========
>>> print Duration("0.33334") 0:20 >>> print Duration("2.50") 2:30
Decimal separator =================
Both period and comma are accepted as decimal separator:
>>> parse('1.5') Decimal('1.5') >>> parse('1,5') Decimal('1.5')
But you may not use both at the same time:
>>> parse('1,000.50') Traceback (most recent call last): ... Exception: Invalid decimal value '1,000.50'
"""
return "%s('%s')" % (self.__class__.__name__, str(self))
return self.__class__(Decimal.__add__(self, *args, **kw))
return self.__class__(Decimal.__truediv__(self, *args, **kw))
return self.__class__(Decimal.__mul__(self, *args, **kw))
if isinstance(value, basestring) and value.endswith('%'): self = Decimal.__new__( Percentage, old_div(Decimal(value[:-1]), 100), context) self._value = value return self #~ raise Exception("Invalid Percentage %r" % value) return cls.__new__(Quantity, value, context)
return self._value
"""A duration, expressed in `hours:minutes`.
>>> print Duration('1') 1:00 >>> print Duration('2.5') 2:30 >>> print Duration('2.50') 2:30
>>> print Duration('1:00') 1:00 >>> print Duration('1:30') 1:30 >>> print Duration('1:55') 1:55
>>> print Duration('1:45') * 2 3:30 >>> print Duration('1:55') * 2 3:50
>>> print Duration('0:45') / 3 0:15
>>> print Duration('0:49') / 10 0:05
>>> print Duration('1:30') * 2 3:00 >>> print Duration('0:03') * 10 0:30 >>> print Duration('0:01') * 60 1:00 >>> print Duration('0:01') * 6000 100:00
>>> print Duration('1:55') + Duration('0:05') 2:00 >>> print Duration('1:55') + Duration('0:10') 2:05
>>> print Duration('1:55') - Duration('0:10') 1:45 >>> print Duration('1:05') - Duration('0:10') 0:55
>>> print Duration(datetime.timedelta(0)) 0:00 >>> print Duration(datetime.timedelta(0, hours=10)) 10:00 >>> print Duration(datetime.timedelta(0, minutes=10)) 0:10
A duration can be more than 24 hours, and in that case (unlike :class:`datetime.datetime`) it is still represented using `hhhh.mm`:
>>> print Duration(datetime.timedelta(hours=25)) 25:00
>>> print Duration(datetime.timedelta(days=128)) 3072:00
"""
if isinstance(value, basestring): if ':' in value: h, m = value.split(':') value = Decimal(h) + Decimal(m) * DEC2HOUR elif isinstance(value, datetime.timedelta): hours = 0 if value.days != 0: hours += value.days * 24 value = datetime.timedelta(seconds=value.seconds) a = str(value).split(':')[:2] hours += int(a[0]) minutes = int(a[1]) return cls('{0}:{1}'.format(hours, minutes)) # return cls(':'.join(a)) self = Decimal.__new__(Duration, value, context) return self
minutes = old_div((self - int(self)), DEC2HOUR) return '%d:%02d' % ( int(self), minutes.to_integral())
""" """ if not isinstance(s, basestring): raise Exception("Expected a string, got %r" % s) if ':' in s: return Duration(s) # if '/' in s: # return Fraction(s) if s.endswith('%'): return Percentage(s) return parse_decimal(s)
if '.' in s and ',' in s: raise Exception("Invalid decimal value %r" % s) s = s.replace(',', '.') return Decimal(s)
import doctest doctest.testmod()
_test() |