Dokumentation für das Modul Exchange rate[Ansicht] [Bearbeiten] [Versionsgeschichte] [Aktualisieren]

Hinweis: Seit dem 24. Februar 2023 werden die Wechselkurse auf Wikimedia Commons nicht mehr aktualisiert.

Versionsbezeichnung auf Wikidata: 2024-02-24 Ok!

Benötigte weitere Module

Dieses Modul benötigt folgende weitere Module: CountryData/Currencies

Verwendung in anderen Modulen

Dieses Modul ist notwendig für die Ausführung folgender Module. Bei Anpassungen sollte die Funktionstüchtigkeit der folgenden Module geprüft werden. Benutze dazu auch diese Tracking-Kategorie um Fehler zu finden, die sich dann auf Artikel auswirken:

Häufig genutzte Variablen

  • amount: string Wert oder Wertebereich eines Geldbetrages,
  • source: string dreistelliger ISO-4217-Code der Ursprungswährung,
  • target: string dreistelliger ISO-4217-Code der Zielwährung,
  • frame: table Parametertabelle, die durch einen #invoke-Aufruf übergeben wird.

Extern nutzbare Funktionen

function er.getRate( source, target, toRound ) 

Die Funktion liefert drei Werte zurück: rate, asOf, digitCount.

  • Vorgabe:
    • toRound: boolean. Falls true wird rate nur mit maximal signifikanten Stellen ausgegeben.
  • Ergebnis:
    • rate: number. Wechselkurs für die Umrechnung aus Ursprungs- in die Zielwährung.
    • asOf: string. Datumsangabe für den Wechselkurs in der Form YYYY-MM-DD.
    • digitCount: number: Anzahl signifikanter Stellen für den Wechselkurs.
function er.getWrapper( amount, source, target, digits, externalFormatter ) 

Die Funktion liefert eine Formatierungszeichenkette für ein span-Tag, wobei öffnendes und schließendes Tag den %s-Platzhalter umschließen. Das title-Attribut des Tags enthält den umgerechneten Betrag in mehreren Währungen (üblicherweise EUR, CHF und USD), das class-Attribut zwei Werte, nämlich voy-currency und voy-currency-xxx, wobei xxx den ISO-4217-Code der Ursprungswährung in Kleinbuchstaben darstellen.

  • Vorgabe:
    • digits: number. Anzahl der Nachkommastellen der umgerechneten Beträge. Standard ist 2.
    • externalFormatter: function. Externe Funktion, die eine Formatierungszeichenkette für das Einfügen eines Betrages zurückliefert. Sie stellt einen Ersatz für die lokale Funktion getFormatter dar, um den Zugriff auf das externe Modul mit den Währungscodes zu vermeiden.
  • Ergebnis:
    • string: Formatierungszeichenkette.
function er.rate( frame ) 

Die Funktion liefert den Wechselkurs für die Umrechnung aus Ursprungs- in die Zielwährung in wählbaren Formaten zur Verfügung.

  • Vorgabe:
    • args.source, args.target, args.show und args.digits.
    • args.show: date: nur Datum des Wechselkurses, all: Wechselkurs mit Datum in Klammern.
    • args.digits: maximale Anzahl der Nachkommastellen.
  • Ergebnis:
    • string: Formatierungszeichenkette.
function er.convert( frame ) 
function er.currencyWithConversions( frame ) 

Lokale Funktionen

local function getFormatter( isoCode, externalFormatter ) 
local function getDigitCount( num ) 
local function round( num, digitCount ) 
local function getFields( tabularData ) 
local function getRateTable( tableName ) 
local function getCurrencyData( rateTable, source, target ) 
local function getDate( aDate, formatStr ) 
local function insertThousandsSep( amount ) 
local function formatNumber( num ) 
local function addUnit( amount, isoCode, externalFormatter ) 
local function formatRate( rate, asOf, show, digits, target ) 
local function convertSingle( source, target, amount, digits ) 
function er._convert( source, targets, amount, withUnit, digits, externalFormatter ) 
Hinweise
--[[ 	Thanks to GiftBot who is uploading/updating currency exchange rates to Wikimedia 	Commons. This service is available since March of 2022. ]]--  -- module variable and administration local er = { 	moduleInterface = { 		suite  = 'Exchange rate', 		serial = '2024-02-24', 		item   = 112066294 	} }  -- require( 'strict' )  -- Exchange-rate tables stored on Wikimedia Commons local tableNames =  { 	'ECB euro foreign exchange reference rates.tab',  	'Xe.com exchange rates.tab' }  -- language-dependent error messages local messages = { 	unknownIsoCode = '[[Category:Währung: Seiten mit unbekanntem Währungscode]] <span class="error">Unbekannter Währungscode</span>', 	wrongParams    = '[[Category:Währung: Fehlerhafte Parameter]] <span class="error">Fehlerhafte(r) Parameter</span>' }  -- language-dependent constants local language = { 	defaultUnits     = { 'EUR', 'CHF', 'USD' }, 	decimalSep       = ',', -- decimal separator 	thousandsSep     = '.', 	commaSep         = mw.message.new( 'comma-separator' ):plain(), 	dateFormat       = 'j. M Y', 	convertFormatter = '≈ %s', 	defaultFormatter = '%s&#x202F;unit', 	wrapperClass     = 'voy-currency', 	conversionVia    = 'EUR', -- EUR or USD 	all              = 'alle', -- lowercase letters 	date             = 'datum' }  -- variables for internal use local cu -- for currencies-table module local rateTables = {} -- to prevent multiple fetching  -- check if arg is set local function isSet( arg ) 	return arg and arg ~= '' end  -- returns a currency formatter string for isoCode -- the following function must be localized local function getFormatter( isoCode, externalFormatter ) 	isoCode = isSet( isoCode ) and isoCode:upper() or 'XXX'  	if externalFormatter then 		return externalFormatter( isoCode ) 	elseif not cu then 		cu = mw.loadData( 'Module:CountryData/Currencies' ) 	end  	local tab = cu.isoToQid[ isoCode ] and cu.currencies[ cu.isoToQid[ isoCode ] ] 	local default = cu.currencies.default or language.defaultFormatter 	if tab then 		if tab.f then 			return tab.f 		else 			local unit = tab.add and tab.add:gsub( ',.*', '' ) or tab.iso 			return default:gsub( 'unit', unit ) 		end 	end 	return default:gsub( 'unit', isoCode ) end  -- returns count of significant digits -- zeros after decimal separator are significant local function getDigitCount( num ) 	num = num:gsub( '%.', '' ):gsub( '^0+', '' ) 	return #num end  -- rounds mantissa/significand of number num to digit count digitCount local function round( num, digitCount ) 	return tonumber( string.format( '%.' .. digitCount .. 'g', num ) ) end  -- returns tabularData fields schema as associative table local function getFields( tabularData ) 	local fields = {} 	local tFields = tabularData.schema.fields 	for i = 1, #tFields do 		fields[ tFields[ i ].name ] = i 	end 	return fields end  -- returns currency-rates table as associative table -- this is an expensive function: the rateTables should be established only once local function getRateTable( tableName ) 	local rows = {} 	local colNo, fields, row, tData 	if not rateTables[ tableName ] then 		local tabularData = mw.ext.data.get( tableName ) 		if not tabularData then 			return nil 		end 		fields = getFields( tabularData ) 		colNo = fields[ 'currency' ] 		tData = tabularData.data 		for i = 1, #tData do 			row = tData[ i ] 			rows[ row[ colNo ] ] = row 		end 		rateTables[ tableName ] = { 			fields = fields, 			rows = rows 		} 	end 	return rateTables[ tableName ] end  -- returns exchange-rate properties for source -> target iso codes local function getCurrencyData( rateTable, source, target ) 	local rate, digitCount, asOf 	local fields = rateTable.fields 	local row = rateTable.rows[ source ] 	if row then 		rate = row[ fields[ target ] ]:gsub( ',', '' ) 			-- remove English thousands separator 		digitCount = getDigitCount( rate ) 		rate = tonumber( rate ) 		asOf = row[ fields[ 'date' ] ] 	end 	return rate, digitCount, asOf end  -- returns exchange rate for source -> target iso codes -- toRound: Boolean function er.getRate( source, target, toRound ) 	-- source, target are three-letter ISO 4217 codes 	if not source:match( '^%a%a%a$' ) or not target:match( '^%a%a%a$' ) then 		return nil 	end  	local rateTable, fields, rate, rows, digitCount, asOf 	source = source:upper() 	target = target:upper()  	for i = 1, #tableNames do 		rateTable = getRateTable( tableNames[ i ] ) 		if rateTable then 			fields = rateTable.fields 			if fields[ target ] then 				rate, digitCount, asOf = getCurrencyData( rateTable, source, target ) 				if rate then 					rate = 1/rate 				end 			elseif fields[ source ] then  				rate, digitCount, asOf = getCurrencyData( rateTable, target, source ) 			elseif fields[ language.conversionVia ] then 				local rate1, digitCount1, asOf1 = getCurrencyData( rateTable, source, language.conversionVia ) 				local rate2, digitCount2, asOf2 = getCurrencyData( rateTable, target, language.conversionVia ) 				if rate1 and rate2 then 					rate = rate2/rate1 					digitCount = digitCount1 < digitCount2 and digitCount1 or digitCount2 					asOf = asOf1 < asOf2 and asOf1 or asOf2 				end 			end 		end 		if rate then 			break 		end 	end 	if rate and toRound then 		rate = round( rate, digitCount ) 	end 	return rate, asOf, digitCount end  -- returns a converted date for aDate due to formatStr local function getDate( aDate, formatStr ) 	local function formatDate( aDate, formatStr ) 		return mw.getContentLanguage():formatDate( formatStr, aDate, true ) 	end  	if isSet( aDate ) then 		local success, t = pcall( formatDate, aDate, formatStr ) 		return success and t or '' 	else 		return '' 	end end  -- inserts thousands separators in amount string local function insertThousandsSep( amount ) 	local k 	local sep = '%1' .. language.thousandsSep .. '%2' 	while true do   		amount, k = amount:gsub( '^(-?%d+)(%d%d%d)', sep ) 		if k == 0 then 			break 		end 	end 	return amount end  -- localizes a number string local function formatNumber( num ) 	if language.decimalSep ~= '.' then 		num = num:gsub( '%.', language.decimalSep ) 	end 	return insertThousandsSep( num ) end  -- adds the currency unit of isoCode to amount string local function addUnit( amount, isoCode, externalFormatter ) 	local formatStr = getFormatter( isoCode, externalFormatter ) 	return mw.ustring.format( mw.text.decode( formatStr ), amount ) end  local function outputFormat( digits ) 	digits = math.floor( tonumber( digits ) or 2 ) 	if digits < 0 or digits > 6 then 		digits = 2 	end 	return '%.'.. digits .. 'f' end  -- selects different rate outputs due to show local function formatRate( rate, asOf, show, digits, target ) 	show = ( show or '' ):lower() 	rate = formatNumber( isSet( digits ) and outputFormat( digits ):format( rate ) 		or tostring( rate ) ) 	if isSet( digits ) or show == 'all' or show == language.all then 		rate = addUnit( rate, target ) 	end 		 	if show == 'all' or show == language.all then 		return rate .. ' (' .. getDate( asOf, language.dateFormat ) .. ')' 	elseif show == 'date' or show == language.date then 		return getDate( asOf, language.dateFormat ) 	else 		return rate 	end end  -- converts a single currency amount without adding the currency unit local function convertSingle( source, target, amount, digits ) 	local rate, asOf, digitCount = er.getRate( source, target ) 	if rate then 		return formatNumber( outputFormat( digits ):format( 			round( amount * rate, digitCount ) ):gsub( '%.0*$', '' ) ) 	else 		return nil 	end end  -- converts a single currency amount or an amount range and adding the currency unit function er._convert( source, targets, amount, withUnit, digits, externalFormatter ) 	local amount1, amount2, pos, result 	local results = {}  	if not isSet( targets ) then 		targets = language.defaultUnits 		withUnit = true 	elseif type( targets ) == 'string' then 		targets = { targets } 	end  	amount = amount:gsub( '[ %a%' .. language.thousandsSep .. ']+', '' ):gsub( '-', '–' ) 	if language.decimalSep ~= '.' then 		amount = amount:gsub( language.decimalSep, '.' ) 	end  	for i, target in ipairs( targets ) do 		if target ~= source then 			pos = mw.ustring.find( amount, '[^,%.%d]' ) 			if pos then 				amount1 = mw.ustring.sub( amount, 1, pos - 1 ) 				amount2 = tonumber( mw.ustring.sub( amount, pos + 1 ) ) 			else 				amount1 = amount 			end 			amount1 = tonumber( amount1 ) or 1 			result = convertSingle( source, target, amount1, digits ) 			if pos and result and amount2 then 				amount2 = convertSingle( source, target, amount2, digits ) 				result = amount2 and 					( result .. mw.ustring.sub( amount, pos, pos ) .. amount2 ) 			end 			if result then 				if withUnit then 					result = addUnit( result, target, externalFormatter ) 				end 				table.insert( results, result ) 			end 		end 	end 	result = table.concat( results, language.commaSep ) 	return result ~= '' and result end  -- returns a wrapper format string with tooltip title function er.getWrapper( amount, source, target, digits, externalFormatter, 	withMaintenance) 	local formatStr = getFormatter( source, externalFormatter ) 	local title = er._convert( source, target, amount, true, digits ) 	if title then 		return tostring( mw.html.create( 'abbr' ) 			:attr( 'title', mw.ustring.format( language.convertFormatter, title ) ) 			:addClass( language.wrapperClass ) 			:addClass( language.wrapperClass .. '-' .. source:lower() ) 			:wikitext( formatStr ) 		) 	else 		return formatStr .. ( withMaintenance and messages.wrongParams or '' ) 	end end  -- #invoke function returning the exchange rate function er.rate( frame ) 	local args = frame.args 	local rate, asOf, digitCount = er.getRate( args.source, args.target, true ) 	return rate and formatRate( rate, asOf, args.show, args.digits, args.target ) 		or messages.unknownIsoCode end  -- #invoke function returning the converted amount or amount range function er.convert( frame ) 	local args = frame.args 	if isSet( args.show ) then 		return er.rate( frame ) 	else 		return er._convert( args.source, args.target, 			isSet( args.amount ) and args.amount or '1', ( args.plain or '' ) ~= '1', 			args.digits ) or messages.wrongParams 	end end  -- #invoke function returning exchange-rate information -- returns the formatted amount or amount range with a tooltip containing -- converted values function er.currencyWithConversions( frame ) 	local args = frame.args 	if not isSet( args.amount ) then 		args.amount = '1' 	end 	return mw.ustring.format( 		er.getWrapper( args.amount, args.source, args.target, args.digits, nil, true ), 		args.amount:gsub( '-', '–' ) 	) end  return er