import locale
import decimal
import datetime
zero = decimal.Decimal( 0 )
def chkzero( val ):
if val == None: return zero
return val
if getattr( locale, 'currency', None ) == None: #python 2.4 non ha
def _group(s):
conv=locale.localeconv()
grouping=conv['mon_grouping']
if not grouping:return (s, 0)
result=""
seps = 0
spaces = ""
if s[-1] == ' ':
sp = s.find(' ')
spaces = s[sp:]
s = s[:sp]
while s and grouping:
# if grouping is -1, we are done
if grouping[0]==locale.CHAR_MAX:
break
# 0: re-use last group ad infinitum
elif grouping[0]!=0:
#process last group
group=grouping[0]
grouping=grouping[1:]
if result:
result=s[-group:]+conv['mon_thousands_sep']+result
seps += 1
else:
result=s[-group:]
s=s[:-group]
if s and s[-1] not in "0123456789":
# the leading string is only spaces and signs
return s+result+spaces,seps
if not result:
return s+spaces,seps
if s:
result=s+conv['mon_thousands_sep']+result
seps += 1
return result+spaces,seps
def formatmon( f, val, grouping=0 ):
"""Formats a value in the same way that the % formatting would use,
but takes the current locale into account.
Grouping is applied if the third parameter is true."""
result = f % val
fields = result.split(".")
seps = 0
if grouping:
fields[0],seps=_group(fields[0])
if len(fields)==2:
result = fields[0]+locale.localeconv()['mon_decimal_point']+fields[1]
elif len(fields)==1:
result = fields[0]
else:
raise Error, "Too many decimal points in result string"
while seps:
# If the number was formatted for a specific width, then it
# might have been filled with spaces to the left or right. If
# so, kill as much spaces as there where separators.
# Leading zeroes as fillers are not yet dealt with, as it is
# not clear how they should interact with grouping.
sp = result.find(" ")
if sp==-1:break
result = result[:sp]+result[sp+1:]
seps -= 1
return result
def currency( val, symbol=False, grouping=False, international=False):
# funzione presente solo in python 2.5
if val is None: val = decimal.Decimal( 0 )
conv = locale.localeconv()
if international:
fmt = '%%.%df' % conv['int_frac_digits']
else:
fmt = '%%.%df' % conv['frac_digits']
result = formatmon( fmt, val, grouping )
if not symbol: return result
if val < 0:
symprec = conv['n_cs_precedes']
symspace = conv['n_sep_by_space']
else:
symprec = conv['p_cs_precedes']
symspace = conv['p_sep_by_space']
if international:
sym = conv['int_curr_symbol']
else:
sym = conv['currency_symbol']
if symprec:
if symspace: result = sym + ' ' + result
else: result = sym + result
else:
if symspace: result = result + ' ' + sym
else: result = result + sym
return result
else:
currency = locale.currency
def ocurrency( value, imon='EUR', omon='EUR', chg=None ):
'mostra un valore espresso in una moneta in un\'altra'
if imon == 'CVE': imon = 'EUR'
if imon != omon:
if chg == None: chg = cambiavalori()
value = chg.convert( value, imon, omon )
return currency( chkzero( value ), False, True, True )
def vcont2decimal( value, segno='A' ):
vdec = decimal.Decimal( str( value ) )
if segno == 'D': vdec = vdec * -1
return vdec
def decimal2vcont( value ):
if value < 0: return 'D', value * -1
return 'A', value
class cambiavalori:
'''
gestisce la conversione di un valore da una moneta ad un'altra
'''
def __init__( self, dtrif=None ):
self.dtrif = dtrif or datetime.date.today()
self.loadcache()
#def read( self, mon ):
# return self.monin[mon]
#except:
# pass # lancia query sql per definizione moneta
def loadcache( self ):
self._dbmon = {}
# cerca nel db le monete presenti e scrive nella cache
self._dbmon['EUR'] = [ decimal.Decimal( '1' ), 2 ]
self._dbmon['ITL'] = [ decimal.Decimal( '1936.27' ), 0 ]
self._dbmon['DEM'] = [ decimal.Decimal( '1.955830' ), 2 ]
self._dbmon['FRL'] = [ decimal.Decimal( '40.339900' ), 2 ]
self._dbmon['YEP'] = [ decimal.Decimal( '0.787564' ), 2 ]
self._dbmon['ATS'] = [ decimal.Decimal( '13.7603' ), 2 ]
self._dbmon['FIM'] = [ decimal.Decimal( '5.945730' ), 2 ]
self._dbmon['FRF'] = [ decimal.Decimal( '6.559570' ), 2 ]
self._dbmon['ESP'] = [ decimal.Decimal( '166.386' ), 2 ]
self._dbmon['NLG'] = [ decimal.Decimal( '2.203710' ), 2 ]
self._dbmon['PTE'] = [ decimal.Decimal( '200.482' ), 2 ]
self._dbmon['GRD'] = [ decimal.Decimal( '340.75' ), 0 ]
def retrieve( self, mon ):
# cerca il cambio nel db e scrive nella cache
return self._dbmon[mon]
def cambio( self, mon ):
try: vc = self._dbmon[mon]
except IndexError: vc = self.retrieve( mon, self.dtrif )
return vc[0]
def convert( self, value, monfrom, monto='EUR' ):
'converti un valore (decimal) da una moneta ad un\'altra (default EUR)'
if value is not None:
value = value / self.cambio( monfrom )
if monto != 'EUR': value = value * self.cambio( monto )
return value
if __name__ == '__main__':
locale.setlocale( locale.LC_ALL, '' )
nr = decimal.Decimal('3456.78')
print currency( nr, False, True, True )