Presentación acerca del JSR354: Moneda y DInero. Nueva API para el uso de monedas y valores monetarios en aplicaciones Java.
Esta presentación se hizo como parte del programa Adopta un JSR para el grupo de usuarios Java de Cali (CLOJUG). Algunos meses después de la presentación, la especificación fue actualizada y algunos ejemplos de código mostrados pueden estar desactualizados.
1. JSR 354
Moneda y Dinero
CLOJUG
24-ENE-2015
http://www.clojug.org Imagen tomada de http://elpueblo.com.co/
2. JSR 354
Moneda y Dinero
Anatole Tresch
@atsticks
Regular Conference Speaker
Specification Lead JSR 354
Proyecto en Java.net
http://java.net/projects/javamoney
JSR
https://jcp.org/en/jsr/detail?id=354
Proyecto en Github
http://javamoney.github.io/
Twitter
@jsr354
3. JSR 354
Moneda y Dinero
Los valores monetarios son parte fundamental de muchas aplicaciones, sin
embargo, el JDK provee poco o ningún soporte para éstos.
La clase existente java.util.Currency es solamente una estructura para la
representación de las monedas actuales (ISO-4217), pero no para
representar sus valores asociados o monedas personalizadas. El JDK
tampoco ofrece soporte para operaciones aritméticas con monedas o
conversión entre ellas ni tampoco un tipo de valor estándar para representar
un valor monetario.
“
Texto tomado de la especificación del JSR-354
4. Agenda
Introducción
Tasas de Cambio y Conversión
Monedas y Valores Monetarios
Formato y Análisis
Extensiones
44
55
Documentación y Práctica66
11
22
33
5. Introducción
El Equipo
• Credit Suisse
• Stephen Colebourne
• JUG Chennai
• Goldman Sachs
• Werner Keil
• Y otros...
• Credit Suisse
• Stephen Colebourne
• London Java Community
• Caxton Associates
• Goldman Sachs
• JP Morgan/Chase
• Werner Keil
Grupo
Soporte
Grupo
Experto
• JUG Chennai
• London Java Community
• CEJUG
JUGs
Participantes
https://jcp.org/en/jsr/detail?id=354
https://java.net/projects/adoptajsr/pages/WhoIsAdoptingJSRs##350_-->_#359
Anatole Tresch
Credit Suisse
Líder del JSR
6. Introducción
Limitaciones actuales de java.util.Currencies
No soporta monedas históricas
Por ejemplo, en la antigua Roma existían las monedas Áureo y Denario, entre otras
No soporta monedas no-estandar (no definidas en ISO-4217)
Por ejemplo, hay países en dónde vacas y camellos pueden representar valores
monetarios
No soporta monedas virtuales
BitCoin, Facebook credits, Linden Dollar (Second life), etc.
No se puede extender
7. Introducción
Objetivos del JSR-354
• Proveer un API para el manejo de monedas y dinero en Java
• Soportar el estándar ISO-4217 y monedas personalizadas (por
ejemplo virtuales), así como la representación de valores monetarios
• Ofrecer operaciones aritméticas entre valores monetarios, incluso de
diferentes monedas, y conversión entre éstos
8. Introducción
Retos del JSR-354
• Que sea un API simple, pero aplicable a los casos más comunes
• Mantener un rendimiento óptimo que permita usarlo en aplicaciones
de alto desempeño como por ejemplo aplicaciones de comercio
electrónico.
• Que se pueda extender, dado que existen diferencias en cuanto a la
precisión, conversión y formato de los valores monetarios. Ejemplos:
Redondeo de valores monetarios en Suiza y Argentina
El formato de la Rupia India: 12,34,00,000
10. Introducción
javax.money.MonetaryContext
Describe las capacidades que tiene una moneda
Por ejemplo describe aspectos comunes como precisión, escala, etc.
Accesible dese cualquier valor monetario
+MonetaryAmount.getMonetaryContext():MonetaryContext
Inmutable, serializable y apta para concurrencia
11. Monedas y Valores Monetarios
Monedas
//Representa una moneda
public interface CurrencyUnit {
public String getCurrencyCode();
public int getNumericCode();
public int getDefaultFractionDigits();
public CurrencyContext getCurrencyContext();
}
//Fabrica de monedas
public final class MonetaryCurrencies{
public CurrencyUnit getCurrency(String currencyCode);
public CurrencyUnit getCurrency(Locale locale);
public boolean isCurrencyAvailable(...);
public Collection<CurrencyUnit> getCurrencies(CurrencyQuery query);
}
12. Monedas y Valores Monetarios
Monedas
//Moneda por código ISO-4217
CurrencyUnit usDolar = MonetaryCurrencies.getCurrency("USD");
CurrencyUnit euro = MonetaryCurrencies.getCurrency("EUR");
CurrencyUnit pesos = MonetaryCurrencies.getCurrency("COP");
//Moneda por localidad
CurrencyUnit euro = MonetaryCurrencies.getCurrency(Locale.GERMANY);
CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN);
CurrencyUnit canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);
13. Monedas y Valores Monetarios
Valores Monetarios
public interface MonetaryAmount extends CurrencySupplier, NumberSupplier,
Comparable<MonetaryAmount> {
public MonetaryContext getMonetaryContext();
...
public MonetaryAmount with(MonetaryOperator operator);
public <R> R query(MonetaryQuery<R> query);
public MonetaryAmountFactory<? extends MonetaryAmount> getFactory();
...
public boolean isLessThanOrEqualTo(MonetaryAmount amt);
public boolean isLessThan(MonetaryAmount amt);
public boolean isEqualTo(MonetaryAmount amt);
public int signum();
...
public MonetaryAmount add(MonetaryAmount amount);
public MonetaryAmount subtract(MonetaryAmount amount);
public MonetaryAmount divide(long number);
public MonetaryAmount multiply(Number number);
public MonetaryAmount remainder(double number);
}
Valor Monetario
• Moneda
• Valor Numérico
• Funciones
aritméticas
• Diseño funcional
• API fluido
14. Monedas y Valores Monetarios
Valores Monetarios
// Valores monetarios en diferentes monedas
MonetaryAmount dolar = MonetaryAmounts.getDefaultAmountFactory()
.setCurrency("USD")
.setNumber(1266.15)
.create();
MonetaryAmount peso = MonetaryAmounts.getDefaultAmountFactory()
.setCurrency("COP")
.setNumber(100_000)
.create();
MonetaryAmount euro = MonetaryAmounts.getDefaultAmountFactory()
.setCurrency("EUR")
.setNumber(3250.25)
.create();
15. Monedas y Valores Monetarios
Valores Monetarios
// Obtiene un valor monetario por defecto (MonetaryAmount)
MonetaryAmount valor = MonetaryAmounts.getDefaultAmountFactory()
.setCurrency("USD")
.setNumber(150.5)
.create();
CurrencyUnit moneda = valor.getCurrency(); // USD
NumberValue numberValue = monetaryAmount.getNumber(); //150.5
int intValue = numberValue.intValue(); // 150
double doubleValue = numberValue.doubleValue(); // 150.5
long fractionDenominator = numberValue.getAmountFractionDenominator(); // 100
long fractionNumerator = numberValue.getAmountFractionNumerator(); // 5
int precision = numberValue.getPrecision(); // 5
17. Formato y Análisis
Formato: javax.money.format.MonetaryAmountFormat
• Similar a java.text.DecimalFormat accesible por localidad (Locale)
• Soporta formatos personalizados
• Seguro para ser usado en concurrencia
• Se construye usando API fluido
18. Formato y Análisis
javax.money.format.MonetaryAmountFormat
// Define un valor monetario en Rupias
MonetaryAmount rupias = MonetaryAmounts.getDefaultAmountFactory()
.setCurrency("INR")
.setNumber(39101112.123456)
.create();
// Realizar formato con uno de los formatos proveidos
MonetaryAmountFormat formato = MonetaryFormats.getAmountFormat(new Locale("", "in"));
System.out.println(formato.format(rupias)); // INR 3,91,01,112.10
19. Formato y Análisis
javax.money.format.MonetaryAmountFormat
// Define un valor monetario en pesos
MonetaryAmount pesos = MonetaryAmounts.getDefaultAmountFactory()
.setCurrency("COP")
.setNumber(1_250_328)
.create();
// Realizar formato con uno de los formatos proveidos
MonetaryAmountFormat formato = MonetaryFormats.getAmountFormat(new Locale("", "co"));
System.out.println(formato.format(pesos)); // COP1.250.328,00
//El mismo formato se puede usar para obtener un valor monetario a partir de una cadena (parse)
MonetaryAmount parsed = formato.parse("COP 500");
// También podemos tener un formato peronalizado
MonetaryAmountFormat personalizado = MonetaryFormats.getAmountFormat(
AmountFormatQueryBuilder.of(new Locale("", "co"))
.set("pattern", "#,##0.00;(#,##0.00)")
.build());
20. Tasas de cambio y Conversión
Tasas de cambio: javax.money.ExchangeRate
• Tasas de cambio modelan la conversión entre monedas.
• Se obtienen a partir de unos provedores de este servicio entre los
que se encuentran: El Banco Central Europeo (ECB) y el Fondo
Monetario Internacional (IFM)
• Importante: El JSR define que deben existir proveedores de
servicio de tasas de cambio, pero es la implementación quién
define cuáles y cómo se accede a su información.
21. Tasas de cambio y Conversión
Tasas de cambio: javax.money.ExchangeRate
// Obtiene el proveedor de servicio de tasas de cambio por defecto
ExchangeRateProvider prov = MonetaryConversions.getExchangeRateProvider();
// Obtiene un proveedor de servicio de tasas de cambio específico
prov = MonetaryConversions.getExchangeRateProvider("IMF");
// Obtiene una cadena de proveedores de servicio de tasas de cambio
prov = MonetaryConversions.getExchangeRateProvider("ECB", "IMF");
// Obtiene la tasa de cambio entre dos monedas
ExchangeRate cambio = prov.getExchangeRate("COP", "USD");
//Métodos útiles
NumberValue factor = cambio.getFactor(); // valor del cambio
CurrencyUnit monedaBase = cambio.getBaseCurrency(); // COP
CurrencyUnit monedaDestino = cambio.getCurrency(); // USD
22. Tasas de cambio y Conversión
Conversión
// Define un valor monetario en pesos
MonetaryAmount pesos = MonetaryAmounts.getDefaultAmountFactory()
.setCurrency("COP")
.setNumber(1_000)
.create();
// Obtiene el proveedor Fondo Monetario Internacional
ExchangeRateProvider prov = MonetaryConversions.getExchangeRateProvider("IMF");
//Este objeto realizará el cambio a dólar
CurrencyConversion conv = prov.getCurrencyConversion("USD");
//Realiza la conversión
MonetaryAmount dolar = pesos.with(conv);
23. Extensiones
javax.money.MonetaryOperator
• Toma un valor monetario y produce otro con valor diferente o con
moneda diferente o ambos.
• Estos operadores pueden ser aplicados a cualquier valor
monetario:
public interface MonetaryAmount... {
...
public MonetaryAmount with (MonetaryOperator operator);
}
@FunctionalInterface
public interface MonetaryOperator extends UnaryOperator<MonetaryAmount> {
}
24. Extensiones
Casos de Uso: javax.money.MonetaryOperator
// Define un valor monetario en pesos
MonetaryAmount pesos =
MonetaryAmounts.getDefaultAmountFactory()
.setCurrency("COP")
.setNumber(100.321)
.create();
// Redondea
MonetaryRounding rounding =
MonetaryRoundings.getRounding(
MonetaryCurrencies.getCurrency("COP"));
MonetaryAmount redondeo = pesos.with(rounding);
// Calcula el 10% del valor monetario
MonetaryAmount porcentaje = redondeo.with(
MonetaryUtil.percent(10));
Permite extender las
operaciones algorítmitcas
provistas:
• Porcentajes
• Redondeo
• Operaciones Financieras
• ...
25. Enlaces de interés
JSR-354 Monedas y DineroJSR-354 Monedas y Dinero
Página del proyecto en Java.net
http://java.net/projects/javamoney
JSR
Encuentras la información de la especificación, equipo de trabajo, etc.
https://jcp.org/en/jsr/detail?id=354
Proyecto en Github
Encuentras las últimas fuentes y ejemplos
http://javamoney.github.io/
Blogs de referencia
Encuentras ejemplos y otras notas usadas también en esta presentación
http://www.mscharhag.com/2014/12/java-jsr-354-money-and-currency-api.html