public final class FormattingDocumentation extends Object
Do not use SimpleDateFormat
, it does not work with all temporal data types of the SDK:
final LocalDate localDate = LocalDate.now(); final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yy"); assertThatThrownBy(() -> simpleDateFormat.format(localDate)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("Cannot format given Object as a Date");
See the test code.
LocalDate.format(DateTimeFormatter)
with DateTimeFormatter
instead:
final LocalDate localDate = LocalDate.of(2015, 7, 25); assertThat(localDate.format(DateTimeFormatter.ofPattern("dd.MM.yy"))).isEqualTo("25.07.15"); assertThat(localDate.format(DateTimeFormatter.ISO_LOCAL_DATE)).isEqualTo("2015-07-25"); assertThat(localDate.format( DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.GERMANY) )).isEqualTo("25.07.2015"); assertThat(localDate.format( DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(Locale.GERMANY) )).isEqualTo("Samstag, 25. Juli 2015");
See the test code.
final LocalTime localTime = LocalTime.of(16, 35); assertThat(localTime.format(DateTimeFormatter.ofPattern("HH:mm"))).isEqualTo("16:35"); assertThat(localTime.format(DateTimeFormatter.ISO_LOCAL_TIME)).isEqualTo("16:35:00"); assertThat(localTime.format( DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM).withLocale(Locale.GERMANY) )).isEqualTo("16:35:00");
See the test code.
final String timeAsString = "2015-07-09T07:46:40.230Z";//typical date format from the API final ZonedDateTime dateTime = ZonedDateTime.parse(timeAsString); final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"); assertThat(dateTime.format(formatter)).isEqualTo("09.07.2015 07:46"); assertThat(dateTime.withZoneSameInstant(ZoneOffset.UTC).format(formatter)) .overridingErrorMessage("Timezone is UTC, so without transforming the value into the right timezone, " + "the displayed date is not accurate") .isEqualTo("09.07.2015 07:46"); assertThat(dateTime.withZoneSameInstant(ZoneId.of("Europe/Berlin")).format(formatter)) .isEqualTo("09.07.2015 09:46"); assertThat(dateTime.withZoneSameInstant(ZoneId.of("Europe/London")).format(formatter)) .isEqualTo("09.07.2015 08:46"); assertThat(dateTime.withZoneSameInstant(ZoneId.of("America/New_York")).format(formatter)) .isEqualTo("09.07.2015 03:46"); assertThat(dateTime.withZoneSameInstant(ZoneId.of("America/Los_Angeles")).format(formatter)) .isEqualTo("09.07.2015 00:46"); assertThat(dateTime.withZoneSameInstant(ZoneId.of("Europe/Berlin")).format( DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(Locale.GERMANY) )).isEqualTo("Donnerstag, 9. Juli 2015");
See the test code.
final List<MonetaryAmount> monetaryAmounts = asList( MoneyImpl.of(new BigDecimal("1234.56"), Monetary.getCurrency("EUR")), MoneyImpl.of(new BigDecimal("1234.56"), DefaultCurrencyUnits.EUR), MoneyImpl.of("1234.56", "EUR"), MoneyImpl.ofCents(123456, Monetary.getCurrency("EUR")), MoneyImpl.ofCents(123456, Monetary.getCurrency(Locale.GERMANY)),//auto select per county MoneyImpl.ofCents(123456, DefaultCurrencyUnits.EUR), MoneyImpl.ofCents(123456, "EUR") ); monetaryAmounts.forEach(monetaryAmount -> { assertThat(monetaryAmount.getCurrency()).isEqualTo(DefaultCurrencyUnits.EUR); final long centAmount = monetaryAmount.scaleByPowerOfTen(2).getNumber().longValue(); assertThat(centAmount).isEqualTo(123456L); });
See the test code.
For formatting you can just get a formatter per locale.
Example for Germany:
final MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.GERMANY); assertThat(format.format(MoneyImpl.ofCents(123456, "EUR"))).isEqualTo("1.234,56 EUR");
See the test code.
Example for the USA:
final MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.US); assertThat(format.format(MoneyImpl.ofCents(123456, "USD"))).isEqualTo("USD1,234.56");
See the test code.
You can also use the locale and force to use the currency symbol instead of the currency code:
final MonetaryAmountFormat format = MonetaryFormats.getAmountFormat( AmountFormatQueryBuilder.of(Locale.US) .set(CurrencyStyle.SYMBOL) .build() ); final String formatted = format.format(MoneyImpl.ofCents(123456, "USD")); assertThat(formatted).isEqualTo("$1,234.56");
See the test code.
If that is not flexible enough you can specify a pattern:
final MonetaryAmountFormat format = MonetaryFormats.getAmountFormat( AmountFormatQueryBuilder.of(Locale.US) .set(CurrencyStyle.SYMBOL) .set("pattern", "###0.00### ¤") .build() ); final String formatted = format.format(MoneyImpl.ofCents(123456, "USD")); assertThat(formatted).isEqualTo("1234.56 $");
See the test code.
¤ is the currency sign which can be formatted with the styles CurrencyStyle.CODE
, CurrencyStyle.NAME
, CurrencyStyle.NUMERIC_CODE
and CurrencyStyle.SYMBOL
.
Be aware of that there is a difference if you use a locale with a language or a locale with both language and country:
final Locale germany = Locale.GERMANY; assertThat(germany.toLanguageTag()).as("contains language and country").isEqualTo("de-DE"); final Locale german = Locale.GERMAN; assertThat(german.toLanguageTag()).as("contains language").isEqualTo("de"); final MonetaryAmount amount = MoneyImpl.ofCents(123456, "EUR"); final MonetaryAmountFormat formatByLanguageAndCountry = MonetaryFormats.getAmountFormat( AmountFormatQueryBuilder.of(germany) .set(CurrencyStyle.SYMBOL) .build() ); final MonetaryAmountFormat formatByJustLanguage = MonetaryFormats.getAmountFormat( AmountFormatQueryBuilder.of(german) .set(CurrencyStyle.SYMBOL) .build() ); assertThat(formatByLanguageAndCountry.format(amount)).as("contains symbol").isEqualTo("1.234,56 €"); assertThat(formatByJustLanguage.format(amount)).as("contains not symbol").isEqualTo("EUR 1.234,56");
See the test code.
MonetaryQueries.convertMinorPart()
to get the whole amount as cents:
final MonetaryAmount amount = MoneyImpl.of(new BigDecimal("1234.56"), "EUR"); final Long centAmount = amount.query(MonetaryQueries.convertMinorPart()); assertThat(centAmount).isEqualTo(123456);
See the test code.
MonetaryQueries.extractMinorPart()
to get the minor unit (cent) part:
final MonetaryAmount amount = MoneyImpl.of(new BigDecimal("1234.56"), "EUR"); final Long centPart = amount.with(MonetaryOperators.minorPart()).query(MonetaryQueries.extractMinorPart()); assertThat(centPart).isEqualTo(56);
See the test code.
MonetaryQueries.extractMajorPart()
to get the smooth amount:
final MonetaryAmount amount = MoneyImpl.of(new BigDecimal("1234.56"), "EUR"); final Long centAmount = amount.query(MonetaryQueries.extractMajorPart()); assertThat(centAmount).isEqualTo(1234);
See the test code.
By the amount:
final MonetaryAmount a = MoneyImpl.ofCents(-200, "EUR"); final MonetaryAmount b = MoneyImpl.ofCents(100, "EUR"); final MonetaryAmount c = MoneyImpl.ofCents(5000, "EUR"); final List<MonetaryAmount> monetaryAmounts = asList(c, a, b); final Comparator<MonetaryAmount> comparator = MonetaryFunctions.sortNumber();//useful for all the same currency final List<MonetaryAmount> sorted = monetaryAmounts.stream().sorted(comparator).collect(toList()); assertThat(sorted).containsExactly(a, b, c);
See the test code.
By the currency and the amount:
final MonetaryAmount a = MoneyImpl.ofCents(-200, "EUR"); final MonetaryAmount b = MoneyImpl.ofCents(100, "EUR"); final MonetaryAmount c = MoneyImpl.ofCents(5000, "EUR"); final MonetaryAmount d = MoneyImpl.ofCents(100, "USD"); final MonetaryAmount e = MoneyImpl.ofCents(5000, "USD"); final List<MonetaryAmount> monetaryAmounts = asList(c, d, a, e, b); final Comparator<MonetaryAmount> comparator = MonetaryFunctions.sortCurrencyUnit().thenComparing(MonetaryFunctions.sortNumber()); final List<MonetaryAmount> sorted = monetaryAmounts.stream().sorted(comparator).collect(toList()); assertThat(sorted).isEqualTo(asList(a, b, c, d, e));
See the test code.
See JavaMoney Moneta User Guide - Rounding.
final MonetaryAmount amount = MoneyImpl.of(new BigDecimal("13.3750"), "EUR"); final MonetaryAmount rounded = amount.with(Monetary.getDefaultRounding()); assertThat(rounded).isEqualTo(MoneyImpl.of(new BigDecimal("13.38"), "EUR"));
See the test code.
final MonetaryAmount amount = MoneyImpl.of(new BigDecimal("13.3749"), "EUR"); final MonetaryAmount rounded = amount.with(Monetary.getDefaultRounding()); assertThat(rounded).isEqualTo(MoneyImpl.of(new BigDecimal("13.37"), "EUR"));
See the test code.