===================
10.0.0 (2024-03-02)
===================
+* Renamed 'conversion' package to 'conversions'.
* Renamed some methods and variables.
------------------
+++ /dev/null
-/**
- * Macaco
- * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
- * See LICENSE for details.
- */
-
-package com.marcozanon.macaco.conversion;
-
-import com.marcozanon.macaco.MException;
-
-public abstract class MConversionException extends MException {
-
- /* */
-
- public MConversionException() {
- super();
- }
-
- public MConversionException(String message) {
- super(message);
- }
-
- public MConversionException(Throwable error) {
- super(error);
- }
-
- public MConversionException(String message, Throwable error) {
- super(message, error);
- }
-
-}
+++ /dev/null
-/**
- * Macaco
- * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
- * See LICENSE for details.
- */
-
-package com.marcozanon.macaco.conversion;
-
-import com.marcozanon.macaco.MObject;
-import com.marcozanon.macaco.text.MText;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.LinkedHashSet;
-import java.util.Locale;
-import java.util.TimeZone;
-
-public class MDateConverter extends MObject {
-
- protected LinkedHashSet<String> dateFormats = new LinkedHashSet<String>();
- protected Locale locale = null;
- protected TimeZone timeZone = null;
-
- /* */
-
- public MDateConverter(String defaultDateFormat, Locale locale) {
- this(defaultDateFormat, locale, TimeZone.getDefault());
- }
-
- public MDateConverter(String defaultDateFormat, Locale locale, TimeZone timeZone) {
- super();
- //
- this.addDateFormat(defaultDateFormat);
- this.setLocale(locale);
- this.setTimeZone(timeZone);
- }
-
- public MDateConverter(LinkedHashSet<String> dateFormats, Locale locale, TimeZone timeZone) {
- super();
- //
- this.setDateFormats(dateFormats);
- this.setLocale(locale);
- this.setTimeZone(timeZone);
- }
-
- @Override
- public MDateConverter clone() {
- return new MDateConverter(this.getDateFormats(), this.getLocale(), this.getTimeZone());
- }
-
- /* Date formats. */
-
- public void setDateFormats(LinkedHashSet<String> dateFormats) {
- if (null == dateFormats) {
- throw new IllegalArgumentException("Invalid 'dateFormats': null.");
- }
- else if (0 == dateFormats.size()) {
- throw new IllegalArgumentException("Invalid 'dateFormats': empty.");
- }
- else {
- for (String dateFormat: dateFormats) {
- MDateConverter.checkDateFormat(dateFormat);
- }
- }
- //
- synchronized (this.dateFormats) {
- this.dateFormats = dateFormats;
- }
- }
-
- public void addDateFormat(String dateFormat) {
- MDateConverter.checkDateFormat(dateFormat);
- //
- synchronized (this.dateFormats) {
- this.dateFormats.add(dateFormat);
- }
- }
-
- public LinkedHashSet<String> getDateFormats() {
- return this.dateFormats;
- }
-
- public String getDefaultDateFormat() {
- return this.getDateFormats().iterator().next();
- }
-
- public LinkedHashSet<String> getSecondaryDateFormats() {
- LinkedHashSet<String> dateFormats = (LinkedHashSet<String>)this.getDateFormats().clone();
- //
- dateFormats.remove(this.getDefaultDateFormat());
- //
- return dateFormats;
- }
-
- /* Locale. */
-
- protected void setLocale(Locale locale) {
- if (null == locale) {
- throw new IllegalArgumentException("Invalid 'locale': null.");
- }
- //
- this.locale = locale;
- }
-
- public Locale getLocale() {
- return this.locale;
- }
-
- /* Time zone. */
-
- protected void setTimeZone(TimeZone timeZone) {
- if (null == timeZone) {
- throw new IllegalArgumentException("Invalid 'timeZone': null.");
- }
- //
- this.timeZone = timeZone;
- }
-
- public TimeZone getTimeZone() {
- return this.timeZone;
- }
-
- /* Conversions. */
-
- protected static void checkDateFormat(String dateFormat) {
- if (MText.isBlank(dateFormat)) {
- throw new IllegalArgumentException("Invalid 'dateFormat': null or empty.");
- }
- //
- try {
- SimpleDateFormat testDateFormat = new SimpleDateFormat(dateFormat);
- }
- catch (IllegalArgumentException exception) {
- throw new IllegalArgumentException(String.format("Invalid 'dateFormat': %s.", dateFormat)); // no need to propagate exception
- }
- }
-
- protected static Date createDateFromString(String x, String inputDateFormat, Locale inputLocale, TimeZone inputTimeZone) throws MInvalidConversionFormatException {
- if (MText.isBlank(x)) {
- throw new IllegalArgumentException("Invalid 'x': null or empty.");
- }
- MDateConverter.checkDateFormat(inputDateFormat);
- if (null == inputLocale) {
- throw new IllegalArgumentException("Invalid 'inputLocale': null.");
- }
- if (null == inputTimeZone) {
- throw new IllegalArgumentException("Invalid 'inputTimeZone': null.");
- }
- //
- Calendar c1 = Calendar.getInstance(inputTimeZone, inputLocale);
- c1.clear();
- c1.setLenient(false);
- SimpleDateFormat sdf = new SimpleDateFormat(inputDateFormat, inputLocale);
- sdf.setCalendar(c1);
- //
- Date d1 = null;
- try {
- d1 = sdf.parse(x);
- }
- catch (ParseException exception) {
- throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); // no need to propagate exception
- }
- //
- Calendar c2 = Calendar.getInstance(inputTimeZone, inputLocale);
- c2.clear();
- c2.set(Calendar.YEAR, c1.get(Calendar.YEAR));
- c2.set(Calendar.MONTH, c1.get(Calendar.MONTH));
- c2.set(Calendar.DAY_OF_MONTH, c1.get(Calendar.DAY_OF_MONTH));
- c2.set(Calendar.HOUR_OF_DAY, c1.get(Calendar.HOUR_OF_DAY));
- c2.set(Calendar.MINUTE, c1.get(Calendar.MINUTE));
- c2.set(Calendar.SECOND, c1.get(Calendar.SECOND));
- //
- Date d2 = c2.getTime();
- if (!x.equals(sdf.format(d2))) {
- throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat));
- }
- //
- return d2;
- }
-
- protected static String createStringFromDate(Date date, String outputDateFormat, Locale outputLocale, TimeZone outputTimeZone) {
- if (null == date) {
- throw new IllegalArgumentException("Invalid 'date': null.");
- }
- MDateConverter.checkDateFormat(outputDateFormat);
- if (null == outputLocale) {
- throw new IllegalArgumentException("Invalid 'outputLocale': null.");
- }
- if (null == outputTimeZone) {
- throw new IllegalArgumentException("Invalid 'outputTimeZone': null.");
- }
- //
- SimpleDateFormat sdf = new SimpleDateFormat(outputDateFormat, outputLocale);
- sdf.setCalendar(Calendar.getInstance(outputTimeZone, outputLocale));
- //
- return sdf.format(date);
- }
-
- public Date createDateFromString(String x) throws MInvalidConversionFormatException {
- Date y = null;
- for (String dateFormat: this.getDateFormats()) {
- try {
- y = MDateConverter.createDateFromString(x, dateFormat, this.getLocale(), this.getTimeZone());
- //
- return y;
- }
- catch (MInvalidConversionFormatException exception) {
- }
- }
- if (null == y) {
- throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x));
- }
- //
- return y; // necessary to avoid Java compilation errors
- }
-
- public String createStringFromDate(Date x) {
- return MDateConverter.createStringFromDate(x, this.getDefaultDateFormat(), this.getLocale(), this.getTimeZone());
- }
-
- /* Helpers. */
-
- public static Date getFlatDate(Date x) {
- if (null == x) {
- return x;
- }
- //
- Calendar calendar = new GregorianCalendar();
- calendar.setTime(x);
- calendar.set(Calendar.HOUR_OF_DAY, 0);
- calendar.set(Calendar.MINUTE, 0);
- calendar.set(Calendar.SECOND, 0);
- calendar.set(Calendar.MILLISECOND, 0);
- //
- return calendar.getTime();
- }
-
- public static Date getCeilDate(Date x) {
- if (null == x) {
- return x;
- }
- //
- Calendar calendar = new GregorianCalendar();
- calendar.setTime(x);
- calendar.set(Calendar.HOUR_OF_DAY, 23);
- calendar.set(Calendar.MINUTE, 59);
- calendar.set(Calendar.SECOND, 59);
- calendar.set(Calendar.MILLISECOND, 999);
- //
- return calendar.getTime();
- }
-
-}
+++ /dev/null
-/**
- * Macaco
- * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
- * See LICENSE for details.
- */
-
-package com.marcozanon.macaco.conversion;
-
-@SuppressWarnings("serial")
-public class MInvalidConversionFormatException extends MConversionException {
-
- /* */
-
- public MInvalidConversionFormatException() {
- super();
- }
-
- public MInvalidConversionFormatException(String message) {
- super(message);
- }
-
- public MInvalidConversionFormatException(Throwable error) {
- super(error);
- }
-
- public MInvalidConversionFormatException(String message, Throwable error) {
- super(message, error);
- }
-
-}
+++ /dev/null
-/**
- * Macaco
- * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
- * See LICENSE for details.
- */
-
-package com.marcozanon.macaco.conversion;
-
-import com.marcozanon.macaco.MObject;
-import com.marcozanon.macaco.text.MText;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
-import java.time.format.ResolverStyle;
-import java.util.LinkedHashSet;
-import java.util.Locale;
-
-public class MLocalDateConverter extends MObject {
-
- protected LinkedHashSet<String> dateFormats = new LinkedHashSet<String>();
- protected Locale locale = null;
-
- /* */
-
- public MLocalDateConverter(String defaultDateFormat, Locale locale) {
- super();
- //
- this.addDateFormat(defaultDateFormat);
- this.setLocale(locale);
- }
-
- public MLocalDateConverter(LinkedHashSet<String> dateFormats, Locale locale) {
- super();
- //
- this.setDateFormats(dateFormats);
- this.setLocale(locale);
- }
-
- @Override
- public MLocalDateConverter clone() {
- return new MLocalDateConverter(this.getDateFormats(), this.getLocale());
- }
-
- /* Date formats. */
-
- public void setDateFormats(LinkedHashSet<String> dateFormats) {
- if (null == dateFormats) {
- throw new IllegalArgumentException("Invalid 'dateFormats': null.");
- }
- else if (0 == dateFormats.size()) {
- throw new IllegalArgumentException("Invalid 'dateFormats': empty.");
- }
- else {
- for (String dateFormat: dateFormats) {
- MLocalDateConverter.checkDateFormat(dateFormat);
- }
- }
- //
- synchronized (this.dateFormats) {
- this.dateFormats = dateFormats;
- }
- }
-
- public void addDateFormat(String dateFormat) {
- MLocalDateConverter.checkDateFormat(dateFormat);
- //
- synchronized (this.dateFormats) {
- this.dateFormats.add(dateFormat);
- }
- }
-
- public LinkedHashSet<String> getDateFormats() {
- return this.dateFormats;
- }
-
- public String getDefaultDateFormat() {
- return this.getDateFormats().iterator().next();
- }
-
- public LinkedHashSet<String> getSecondaryDateFormats() {
- LinkedHashSet<String> dateFormats = (LinkedHashSet<String>)this.getDateFormats().clone();
- //
- dateFormats.remove(this.getDefaultDateFormat());
- //
- return dateFormats;
- }
-
- /* Locale. */
-
- protected void setLocale(Locale locale) {
- if (null == locale) {
- throw new IllegalArgumentException("Invalid 'locale': null.");
- }
- //
- this.locale = locale;
- }
-
- public Locale getLocale() {
- return this.locale;
- }
-
- /* Conversions. */
-
- protected static void checkDateFormat(String dateFormat) {
- if (MText.isBlank(dateFormat)) {
- throw new IllegalArgumentException("Invalid 'dateFormat': null or empty.");
- }
- //
- try {
- DateTimeFormatter.ofPattern(dateFormat).withResolverStyle(ResolverStyle.STRICT);
- }
- catch (IllegalArgumentException exception) {
- throw new IllegalArgumentException(String.format("Invalid 'dateFormat': %s.", dateFormat)); // no need to propagate exception
- }
- }
-
- protected static LocalDate createDateFromString(String x, String inputDateFormat, Locale inputLocale) throws MInvalidConversionFormatException {
- if (MText.isBlank(x)) {
- throw new IllegalArgumentException("Invalid 'x': null or empty.");
- }
- MLocalDateConverter.checkDateFormat(inputDateFormat);
- if (null == inputLocale) {
- throw new IllegalArgumentException("Invalid 'inputLocale': null.");
- }
- //
- LocalDate d = null;
- try {
- d = LocalDate.parse(x, DateTimeFormatter.ofPattern(inputDateFormat, inputLocale).withResolverStyle(ResolverStyle.STRICT));
- }
- catch (DateTimeParseException exception) {
- throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); // no need to propagate exception
- }
- //
- return d;
- }
-
- protected static String createStringFromDate(LocalDate date, String outputDateFormat, Locale outputLocale) {
- if (null == date) {
- throw new IllegalArgumentException("Invalid 'date': null.");
- }
- MLocalDateConverter.checkDateFormat(outputDateFormat);
- if (null == outputLocale) {
- throw new IllegalArgumentException("Invalid 'outputLocale': null.");
- }
- //
- return date.format(DateTimeFormatter.ofPattern(outputDateFormat, outputLocale).withResolverStyle(ResolverStyle.STRICT));
- }
-
- public LocalDate createDateFromString(String x) throws MInvalidConversionFormatException {
- LocalDate y = null;
- for (String dateFormat: this.getDateFormats()) {
- try {
- y = MLocalDateConverter.createDateFromString(x, dateFormat, this.getLocale());
- //
- return y;
- }
- catch (MInvalidConversionFormatException exception) {
- }
- }
- if (null == y) {
- throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x));
- }
- //
- return y; // necessary to avoid Java compilation errors
- }
-
- public String createStringFromDate(LocalDate x) {
- return MLocalDateConverter.createStringFromDate(x, this.getDefaultDateFormat(), this.getLocale());
- }
-
-}
+++ /dev/null
-/**
- * Macaco
- * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
- * See LICENSE for details.
- */
-
-package com.marcozanon.macaco.conversion;
-
-import com.marcozanon.macaco.MObject;
-import com.marcozanon.macaco.text.MText;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
-import java.time.format.ResolverStyle;
-import java.util.LinkedHashSet;
-import java.util.Locale;
-
-public class MLocalDateTimeConverter extends MObject {
-
- protected LinkedHashSet<String> datetimeFormats = new LinkedHashSet<String>();
- protected Locale locale = null;
-
- /* */
-
- public MLocalDateTimeConverter(String defaultDatetimeFormat, Locale locale) {
- super();
- //
- this.addDatetimeFormat(defaultDatetimeFormat);
- this.setLocale(locale);
- }
-
- public MLocalDateTimeConverter(LinkedHashSet<String> datetimeFormats, Locale locale) {
- super();
- //
- this.setDatetimeFormats(datetimeFormats);
- this.setLocale(locale);
- }
-
- @Override
- public MLocalDateTimeConverter clone() {
- return new MLocalDateTimeConverter(this.getDatetimeFormats(), this.getLocale());
- }
-
- /* Datetime formats. */
-
- public void setDatetimeFormats(LinkedHashSet<String> datetimeFormats) {
- if (null == datetimeFormats) {
- throw new IllegalArgumentException("Invalid 'datetimeFormats': null.");
- }
- else if (0 == datetimeFormats.size()) {
- throw new IllegalArgumentException("Invalid 'datetimeFormats': empty.");
- }
- else {
- for (String datetimeFormat: datetimeFormats) {
- MLocalDateTimeConverter.checkDatetimeFormat(datetimeFormat);
- }
- }
- //
- synchronized (this.datetimeFormats) {
- this.datetimeFormats = datetimeFormats;
- }
- }
-
- public void addDatetimeFormat(String datetimeFormat) {
- MLocalDateTimeConverter.checkDatetimeFormat(datetimeFormat);
- //
- synchronized (this.datetimeFormats) {
- this.datetimeFormats.add(datetimeFormat);
- }
- }
-
- public LinkedHashSet<String> getDatetimeFormats() {
- return this.datetimeFormats;
- }
-
- public String getDefaultDatetimeFormat() {
- return this.getDatetimeFormats().iterator().next();
- }
-
- public LinkedHashSet<String> getSecondaryDatetimeFormats() {
- LinkedHashSet<String> datetimeFormats = (LinkedHashSet<String>)this.getDatetimeFormats().clone();
- //
- datetimeFormats.remove(this.getDefaultDatetimeFormat());
- //
- return datetimeFormats;
- }
-
- /* Locale. */
-
- protected void setLocale(Locale locale) {
- if (null == locale) {
- throw new IllegalArgumentException("Invalid 'locale': null.");
- }
- //
- this.locale = locale;
- }
-
- public Locale getLocale() {
- return this.locale;
- }
-
- /* Conversions. */
-
- protected static void checkDatetimeFormat(String datetimeFormat) {
- if (MText.isBlank(datetimeFormat)) {
- throw new IllegalArgumentException("Invalid 'datetimeFormat': null or empty.");
- }
- //
- try {
- DateTimeFormatter.ofPattern(datetimeFormat).withResolverStyle(ResolverStyle.STRICT);
- }
- catch (IllegalArgumentException exception) {
- throw new IllegalArgumentException(String.format("Invalid 'datetimeFormat': %s.", datetimeFormat)); // no need to propagate exception
- }
- }
-
- protected static LocalDateTime createDatetimeFromString(String x, String inputDatetimeFormat, Locale inputLocale) throws MInvalidConversionFormatException {
- if (MText.isBlank(x)) {
- throw new IllegalArgumentException("Invalid 'x': null or empty.");
- }
- MLocalDateTimeConverter.checkDatetimeFormat(inputDatetimeFormat);
- if (null == inputLocale) {
- throw new IllegalArgumentException("Invalid 'inputLocale': null.");
- }
- //
- LocalDateTime dt = null;
- try {
- dt = LocalDateTime.parse(x, DateTimeFormatter.ofPattern(inputDatetimeFormat, inputLocale).withResolverStyle(ResolverStyle.STRICT));
- }
- catch (DateTimeParseException exception) {
- throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDatetimeFormat)); // no need to propagate exception
- }
- //
- return dt;
- }
-
- protected static String createStringFromDatetime(LocalDateTime datetime, String outputDatetimeFormat, Locale outputLocale) {
- if (null == datetime) {
- throw new IllegalArgumentException("Invalid 'datetime': null.");
- }
- MLocalDateTimeConverter.checkDatetimeFormat(outputDatetimeFormat);
- if (null == outputLocale) {
- throw new IllegalArgumentException("Invalid 'outputLocale': null.");
- }
- //
- return datetime.format(DateTimeFormatter.ofPattern(outputDatetimeFormat, outputLocale).withResolverStyle(ResolverStyle.STRICT));
- }
-
- public LocalDateTime createDatetimeFromString(String x) throws MInvalidConversionFormatException {
- LocalDateTime y = null;
- for (String datetimeFormat: this.getDatetimeFormats()) {
- try {
- y = MLocalDateTimeConverter.createDatetimeFromString(x, datetimeFormat, this.getLocale());
- //
- return y;
- }
- catch (MInvalidConversionFormatException exception) {
- }
- }
- if (null == y) {
- throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x));
- }
- //
- return y; // necessary to avoid Java compilation errors
- }
-
- public String createStringFromDatetime(LocalDateTime x) {
- return MLocalDateTimeConverter.createStringFromDatetime(x, this.getDefaultDatetimeFormat(), this.getLocale());
- }
-
-}
+++ /dev/null
-/**
- * Macaco
- * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
- * See LICENSE for details.
- */
-
-package com.marcozanon.macaco.conversion;
-
-import com.marcozanon.macaco.MObject;
-import com.marcozanon.macaco.text.MText;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.ParsePosition;
-import java.util.LinkedHashSet;
-import java.util.Locale;
-
-public class MNumberConverter extends MObject {
-
- protected LinkedHashSet<String> numberFormats = new LinkedHashSet<String>();
- protected Locale locale = null;
-
- /* */
-
- public MNumberConverter(String defaultNumberFormat, Locale locale) {
- super();
- //
- this.addNumberFormat(defaultNumberFormat);
- this.setLocale(locale);
- }
-
- public MNumberConverter(LinkedHashSet<String> numberFormats, Locale locale) {
- super();
- //
- this.setNumberFormats(numberFormats);
- this.setLocale(locale);
- }
-
- @Override
- public MNumberConverter clone() {
- return new MNumberConverter(this.getNumberFormats(), this.getLocale());
- }
-
- /* Number formats. */
-
- public void setNumberFormats(LinkedHashSet<String> numberFormats) {
- if (null == numberFormats) {
- throw new IllegalArgumentException("Invalid 'numberFormats': null.");
- }
- else if (0 == numberFormats.size()) {
- throw new IllegalArgumentException("Invalid 'numberFormats': empty.");
- }
- else {
- for (String numberFormat: numberFormats) {
- MNumberConverter.checkNumberFormat(numberFormat);
- }
- }
- //
- synchronized (this.numberFormats) {
- this.numberFormats = numberFormats;
- }
- }
-
- public void addNumberFormat(String numberFormat) {
- MNumberConverter.checkNumberFormat(numberFormat);
- //
- synchronized (this.numberFormats) {
- this.numberFormats.add(numberFormat);
- }
- }
-
- public LinkedHashSet<String> getNumberFormats() {
- return this.numberFormats;
- }
-
- public String getDefaultNumberFormat() {
- return this.getNumberFormats().iterator().next();
- }
-
- public LinkedHashSet<String> getSecondaryNumberFormats() {
- LinkedHashSet<String> numberFormats = (LinkedHashSet<String>)this.getNumberFormats().clone();
- //
- numberFormats.remove(this.getDefaultNumberFormat());
- //
- return numberFormats;
- }
-
- /* Locale. */
-
- protected void setLocale(Locale locale) {
- if (null == locale) {
- throw new IllegalArgumentException("Invalid 'locale': null.");
- }
- //
- this.locale = locale;
- }
-
- public Locale getLocale() {
- return this.locale;
- }
-
- /* Conversions. */
-
- protected static void checkNumberFormat(String numberFormat) {
- if (MText.isBlank(numberFormat)) {
- throw new IllegalArgumentException("Invalid 'numberFormat': null or empty.");
- }
- //
- try {
- DecimalFormat testNumberFormat = new DecimalFormat(numberFormat);
- }
- catch (IllegalArgumentException exception) {
- throw new IllegalArgumentException(String.format("Invalid 'numberFormat': %s.", numberFormat)); // no need to propagate exception
- }
- }
-
- protected static BigDecimal createNumberFromString(String x, String inputNumberFormat, Locale inputLocale) throws MInvalidConversionFormatException {
- if (MText.isBlank(x)) {
- throw new IllegalArgumentException("Invalid 'x': null or empty.");
- }
- MNumberConverter.checkNumberFormat(inputNumberFormat);
- if (null == inputLocale) {
- throw new IllegalArgumentException("Invalid 'inputLocale': null.");
- }
- //
- DecimalFormatSymbols dfs = new DecimalFormatSymbols(inputLocale);
- DecimalFormat df = new DecimalFormat(inputNumberFormat, dfs);
- df.setParseBigDecimal(true);
- //
- ParsePosition validPosition = new ParsePosition(0);
- BigDecimal bd = (BigDecimal)df.parse(x, validPosition);
- if (validPosition.getIndex() < x.length()) {
- throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputNumberFormat));
- }
- //
- return bd;
- }
-
- protected static String createStringFromNumber(BigDecimal number, String outputNumberFormat, Locale outputLocale) {
- if (null == number) {
- throw new IllegalArgumentException("Invalid 'number': null.");
- }
- MNumberConverter.checkNumberFormat(outputNumberFormat);
- if (null == outputLocale) {
- throw new IllegalArgumentException("Invalid 'outputLocale': null.");
- }
- //
- DecimalFormatSymbols dfs = new DecimalFormatSymbols(outputLocale);
- DecimalFormat df = new DecimalFormat(outputNumberFormat, dfs);
- df.setRoundingMode(RoundingMode.HALF_UP);
- //
- return df.format(number);
- }
-
- public BigDecimal createNumberFromString(String x) throws MInvalidConversionFormatException {
- BigDecimal y = null;
- for (String numberFormat: this.getNumberFormats()) {
- try {
- y = MNumberConverter.createNumberFromString(x, numberFormat, this.getLocale());
- //
- return y;
- }
- catch (MInvalidConversionFormatException exception) {
- }
- }
- if (null == y) {
- throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x));
- }
- //
- return y; // necessary to avoid Java compilation errors
- }
-
- public String createStringFromNumber(BigDecimal x) {
- return MNumberConverter.createStringFromNumber(x, this.getDefaultNumberFormat(), this.getLocale());
- }
-
-}
--- /dev/null
+/**
+ * Macaco
+ * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
+ * See LICENSE for details.
+ */
+
+package com.marcozanon.macaco.conversions;
+
+import com.marcozanon.macaco.MException;
+
+public abstract class MConversionException extends MException {
+
+ /* */
+
+ public MConversionException() {
+ super();
+ }
+
+ public MConversionException(String message) {
+ super(message);
+ }
+
+ public MConversionException(Throwable error) {
+ super(error);
+ }
+
+ public MConversionException(String message, Throwable error) {
+ super(message, error);
+ }
+
+}
--- /dev/null
+/**
+ * Macaco
+ * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
+ * See LICENSE for details.
+ */
+
+package com.marcozanon.macaco.conversions;
+
+import com.marcozanon.macaco.MObject;
+import com.marcozanon.macaco.text.MText;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class MDateConverter extends MObject {
+
+ protected LinkedHashSet<String> dateFormats = new LinkedHashSet<String>();
+ protected Locale locale = null;
+ protected TimeZone timeZone = null;
+
+ /* */
+
+ public MDateConverter(String defaultDateFormat, Locale locale) {
+ this(defaultDateFormat, locale, TimeZone.getDefault());
+ }
+
+ public MDateConverter(String defaultDateFormat, Locale locale, TimeZone timeZone) {
+ super();
+ //
+ this.addDateFormat(defaultDateFormat);
+ this.setLocale(locale);
+ this.setTimeZone(timeZone);
+ }
+
+ public MDateConverter(LinkedHashSet<String> dateFormats, Locale locale, TimeZone timeZone) {
+ super();
+ //
+ this.setDateFormats(dateFormats);
+ this.setLocale(locale);
+ this.setTimeZone(timeZone);
+ }
+
+ @Override
+ public MDateConverter clone() {
+ return new MDateConverter(this.getDateFormats(), this.getLocale(), this.getTimeZone());
+ }
+
+ /* Date formats. */
+
+ public void setDateFormats(LinkedHashSet<String> dateFormats) {
+ if (null == dateFormats) {
+ throw new IllegalArgumentException("Invalid 'dateFormats': null.");
+ }
+ else if (0 == dateFormats.size()) {
+ throw new IllegalArgumentException("Invalid 'dateFormats': empty.");
+ }
+ else {
+ for (String dateFormat: dateFormats) {
+ MDateConverter.checkDateFormat(dateFormat);
+ }
+ }
+ //
+ synchronized (this.dateFormats) {
+ this.dateFormats = dateFormats;
+ }
+ }
+
+ public void addDateFormat(String dateFormat) {
+ MDateConverter.checkDateFormat(dateFormat);
+ //
+ synchronized (this.dateFormats) {
+ this.dateFormats.add(dateFormat);
+ }
+ }
+
+ public LinkedHashSet<String> getDateFormats() {
+ return this.dateFormats;
+ }
+
+ public String getDefaultDateFormat() {
+ return this.getDateFormats().iterator().next();
+ }
+
+ public LinkedHashSet<String> getSecondaryDateFormats() {
+ LinkedHashSet<String> dateFormats = (LinkedHashSet<String>)this.getDateFormats().clone();
+ //
+ dateFormats.remove(this.getDefaultDateFormat());
+ //
+ return dateFormats;
+ }
+
+ /* Locale. */
+
+ protected void setLocale(Locale locale) {
+ if (null == locale) {
+ throw new IllegalArgumentException("Invalid 'locale': null.");
+ }
+ //
+ this.locale = locale;
+ }
+
+ public Locale getLocale() {
+ return this.locale;
+ }
+
+ /* Time zone. */
+
+ protected void setTimeZone(TimeZone timeZone) {
+ if (null == timeZone) {
+ throw new IllegalArgumentException("Invalid 'timeZone': null.");
+ }
+ //
+ this.timeZone = timeZone;
+ }
+
+ public TimeZone getTimeZone() {
+ return this.timeZone;
+ }
+
+ /* Conversions. */
+
+ protected static void checkDateFormat(String dateFormat) {
+ if (MText.isBlank(dateFormat)) {
+ throw new IllegalArgumentException("Invalid 'dateFormat': null or empty.");
+ }
+ //
+ try {
+ SimpleDateFormat testDateFormat = new SimpleDateFormat(dateFormat);
+ }
+ catch (IllegalArgumentException exception) {
+ throw new IllegalArgumentException(String.format("Invalid 'dateFormat': %s.", dateFormat)); // no need to propagate exception
+ }
+ }
+
+ protected static Date createDateFromString(String x, String inputDateFormat, Locale inputLocale, TimeZone inputTimeZone) throws MInvalidConversionFormatException {
+ if (MText.isBlank(x)) {
+ throw new IllegalArgumentException("Invalid 'x': null or empty.");
+ }
+ MDateConverter.checkDateFormat(inputDateFormat);
+ if (null == inputLocale) {
+ throw new IllegalArgumentException("Invalid 'inputLocale': null.");
+ }
+ if (null == inputTimeZone) {
+ throw new IllegalArgumentException("Invalid 'inputTimeZone': null.");
+ }
+ //
+ Calendar c1 = Calendar.getInstance(inputTimeZone, inputLocale);
+ c1.clear();
+ c1.setLenient(false);
+ SimpleDateFormat sdf = new SimpleDateFormat(inputDateFormat, inputLocale);
+ sdf.setCalendar(c1);
+ //
+ Date d1 = null;
+ try {
+ d1 = sdf.parse(x);
+ }
+ catch (ParseException exception) {
+ throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); // no need to propagate exception
+ }
+ //
+ Calendar c2 = Calendar.getInstance(inputTimeZone, inputLocale);
+ c2.clear();
+ c2.set(Calendar.YEAR, c1.get(Calendar.YEAR));
+ c2.set(Calendar.MONTH, c1.get(Calendar.MONTH));
+ c2.set(Calendar.DAY_OF_MONTH, c1.get(Calendar.DAY_OF_MONTH));
+ c2.set(Calendar.HOUR_OF_DAY, c1.get(Calendar.HOUR_OF_DAY));
+ c2.set(Calendar.MINUTE, c1.get(Calendar.MINUTE));
+ c2.set(Calendar.SECOND, c1.get(Calendar.SECOND));
+ //
+ Date d2 = c2.getTime();
+ if (!x.equals(sdf.format(d2))) {
+ throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat));
+ }
+ //
+ return d2;
+ }
+
+ protected static String createStringFromDate(Date date, String outputDateFormat, Locale outputLocale, TimeZone outputTimeZone) {
+ if (null == date) {
+ throw new IllegalArgumentException("Invalid 'date': null.");
+ }
+ MDateConverter.checkDateFormat(outputDateFormat);
+ if (null == outputLocale) {
+ throw new IllegalArgumentException("Invalid 'outputLocale': null.");
+ }
+ if (null == outputTimeZone) {
+ throw new IllegalArgumentException("Invalid 'outputTimeZone': null.");
+ }
+ //
+ SimpleDateFormat sdf = new SimpleDateFormat(outputDateFormat, outputLocale);
+ sdf.setCalendar(Calendar.getInstance(outputTimeZone, outputLocale));
+ //
+ return sdf.format(date);
+ }
+
+ public Date createDateFromString(String x) throws MInvalidConversionFormatException {
+ Date y = null;
+ for (String dateFormat: this.getDateFormats()) {
+ try {
+ y = MDateConverter.createDateFromString(x, dateFormat, this.getLocale(), this.getTimeZone());
+ //
+ return y;
+ }
+ catch (MInvalidConversionFormatException exception) {
+ }
+ }
+ if (null == y) {
+ throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x));
+ }
+ //
+ return y; // necessary to avoid Java compilation errors
+ }
+
+ public String createStringFromDate(Date x) {
+ return MDateConverter.createStringFromDate(x, this.getDefaultDateFormat(), this.getLocale(), this.getTimeZone());
+ }
+
+ /* Helpers. */
+
+ public static Date getFlatDate(Date x) {
+ if (null == x) {
+ return x;
+ }
+ //
+ Calendar calendar = new GregorianCalendar();
+ calendar.setTime(x);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ //
+ return calendar.getTime();
+ }
+
+ public static Date getCeilDate(Date x) {
+ if (null == x) {
+ return x;
+ }
+ //
+ Calendar calendar = new GregorianCalendar();
+ calendar.setTime(x);
+ calendar.set(Calendar.HOUR_OF_DAY, 23);
+ calendar.set(Calendar.MINUTE, 59);
+ calendar.set(Calendar.SECOND, 59);
+ calendar.set(Calendar.MILLISECOND, 999);
+ //
+ return calendar.getTime();
+ }
+
+}
--- /dev/null
+/**
+ * Macaco
+ * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
+ * See LICENSE for details.
+ */
+
+package com.marcozanon.macaco.conversions;
+
+@SuppressWarnings("serial")
+public class MInvalidConversionFormatException extends MConversionException {
+
+ /* */
+
+ public MInvalidConversionFormatException() {
+ super();
+ }
+
+ public MInvalidConversionFormatException(String message) {
+ super(message);
+ }
+
+ public MInvalidConversionFormatException(Throwable error) {
+ super(error);
+ }
+
+ public MInvalidConversionFormatException(String message, Throwable error) {
+ super(message, error);
+ }
+
+}
--- /dev/null
+/**
+ * Macaco
+ * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
+ * See LICENSE for details.
+ */
+
+package com.marcozanon.macaco.conversions;
+
+import com.marcozanon.macaco.MObject;
+import com.marcozanon.macaco.text.MText;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+
+public class MLocalDateConverter extends MObject {
+
+ protected LinkedHashSet<String> dateFormats = new LinkedHashSet<String>();
+ protected Locale locale = null;
+
+ /* */
+
+ public MLocalDateConverter(String defaultDateFormat, Locale locale) {
+ super();
+ //
+ this.addDateFormat(defaultDateFormat);
+ this.setLocale(locale);
+ }
+
+ public MLocalDateConverter(LinkedHashSet<String> dateFormats, Locale locale) {
+ super();
+ //
+ this.setDateFormats(dateFormats);
+ this.setLocale(locale);
+ }
+
+ @Override
+ public MLocalDateConverter clone() {
+ return new MLocalDateConverter(this.getDateFormats(), this.getLocale());
+ }
+
+ /* Date formats. */
+
+ public void setDateFormats(LinkedHashSet<String> dateFormats) {
+ if (null == dateFormats) {
+ throw new IllegalArgumentException("Invalid 'dateFormats': null.");
+ }
+ else if (0 == dateFormats.size()) {
+ throw new IllegalArgumentException("Invalid 'dateFormats': empty.");
+ }
+ else {
+ for (String dateFormat: dateFormats) {
+ MLocalDateConverter.checkDateFormat(dateFormat);
+ }
+ }
+ //
+ synchronized (this.dateFormats) {
+ this.dateFormats = dateFormats;
+ }
+ }
+
+ public void addDateFormat(String dateFormat) {
+ MLocalDateConverter.checkDateFormat(dateFormat);
+ //
+ synchronized (this.dateFormats) {
+ this.dateFormats.add(dateFormat);
+ }
+ }
+
+ public LinkedHashSet<String> getDateFormats() {
+ return this.dateFormats;
+ }
+
+ public String getDefaultDateFormat() {
+ return this.getDateFormats().iterator().next();
+ }
+
+ public LinkedHashSet<String> getSecondaryDateFormats() {
+ LinkedHashSet<String> dateFormats = (LinkedHashSet<String>)this.getDateFormats().clone();
+ //
+ dateFormats.remove(this.getDefaultDateFormat());
+ //
+ return dateFormats;
+ }
+
+ /* Locale. */
+
+ protected void setLocale(Locale locale) {
+ if (null == locale) {
+ throw new IllegalArgumentException("Invalid 'locale': null.");
+ }
+ //
+ this.locale = locale;
+ }
+
+ public Locale getLocale() {
+ return this.locale;
+ }
+
+ /* Conversions. */
+
+ protected static void checkDateFormat(String dateFormat) {
+ if (MText.isBlank(dateFormat)) {
+ throw new IllegalArgumentException("Invalid 'dateFormat': null or empty.");
+ }
+ //
+ try {
+ DateTimeFormatter.ofPattern(dateFormat).withResolverStyle(ResolverStyle.STRICT);
+ }
+ catch (IllegalArgumentException exception) {
+ throw new IllegalArgumentException(String.format("Invalid 'dateFormat': %s.", dateFormat)); // no need to propagate exception
+ }
+ }
+
+ protected static LocalDate createDateFromString(String x, String inputDateFormat, Locale inputLocale) throws MInvalidConversionFormatException {
+ if (MText.isBlank(x)) {
+ throw new IllegalArgumentException("Invalid 'x': null or empty.");
+ }
+ MLocalDateConverter.checkDateFormat(inputDateFormat);
+ if (null == inputLocale) {
+ throw new IllegalArgumentException("Invalid 'inputLocale': null.");
+ }
+ //
+ LocalDate d = null;
+ try {
+ d = LocalDate.parse(x, DateTimeFormatter.ofPattern(inputDateFormat, inputLocale).withResolverStyle(ResolverStyle.STRICT));
+ }
+ catch (DateTimeParseException exception) {
+ throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDateFormat)); // no need to propagate exception
+ }
+ //
+ return d;
+ }
+
+ protected static String createStringFromDate(LocalDate date, String outputDateFormat, Locale outputLocale) {
+ if (null == date) {
+ throw new IllegalArgumentException("Invalid 'date': null.");
+ }
+ MLocalDateConverter.checkDateFormat(outputDateFormat);
+ if (null == outputLocale) {
+ throw new IllegalArgumentException("Invalid 'outputLocale': null.");
+ }
+ //
+ return date.format(DateTimeFormatter.ofPattern(outputDateFormat, outputLocale).withResolverStyle(ResolverStyle.STRICT));
+ }
+
+ public LocalDate createDateFromString(String x) throws MInvalidConversionFormatException {
+ LocalDate y = null;
+ for (String dateFormat: this.getDateFormats()) {
+ try {
+ y = MLocalDateConverter.createDateFromString(x, dateFormat, this.getLocale());
+ //
+ return y;
+ }
+ catch (MInvalidConversionFormatException exception) {
+ }
+ }
+ if (null == y) {
+ throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x));
+ }
+ //
+ return y; // necessary to avoid Java compilation errors
+ }
+
+ public String createStringFromDate(LocalDate x) {
+ return MLocalDateConverter.createStringFromDate(x, this.getDefaultDateFormat(), this.getLocale());
+ }
+
+}
--- /dev/null
+/**
+ * Macaco
+ * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
+ * See LICENSE for details.
+ */
+
+package com.marcozanon.macaco.conversions;
+
+import com.marcozanon.macaco.MObject;
+import com.marcozanon.macaco.text.MText;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.format.ResolverStyle;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+
+public class MLocalDateTimeConverter extends MObject {
+
+ protected LinkedHashSet<String> datetimeFormats = new LinkedHashSet<String>();
+ protected Locale locale = null;
+
+ /* */
+
+ public MLocalDateTimeConverter(String defaultDatetimeFormat, Locale locale) {
+ super();
+ //
+ this.addDatetimeFormat(defaultDatetimeFormat);
+ this.setLocale(locale);
+ }
+
+ public MLocalDateTimeConverter(LinkedHashSet<String> datetimeFormats, Locale locale) {
+ super();
+ //
+ this.setDatetimeFormats(datetimeFormats);
+ this.setLocale(locale);
+ }
+
+ @Override
+ public MLocalDateTimeConverter clone() {
+ return new MLocalDateTimeConverter(this.getDatetimeFormats(), this.getLocale());
+ }
+
+ /* Datetime formats. */
+
+ public void setDatetimeFormats(LinkedHashSet<String> datetimeFormats) {
+ if (null == datetimeFormats) {
+ throw new IllegalArgumentException("Invalid 'datetimeFormats': null.");
+ }
+ else if (0 == datetimeFormats.size()) {
+ throw new IllegalArgumentException("Invalid 'datetimeFormats': empty.");
+ }
+ else {
+ for (String datetimeFormat: datetimeFormats) {
+ MLocalDateTimeConverter.checkDatetimeFormat(datetimeFormat);
+ }
+ }
+ //
+ synchronized (this.datetimeFormats) {
+ this.datetimeFormats = datetimeFormats;
+ }
+ }
+
+ public void addDatetimeFormat(String datetimeFormat) {
+ MLocalDateTimeConverter.checkDatetimeFormat(datetimeFormat);
+ //
+ synchronized (this.datetimeFormats) {
+ this.datetimeFormats.add(datetimeFormat);
+ }
+ }
+
+ public LinkedHashSet<String> getDatetimeFormats() {
+ return this.datetimeFormats;
+ }
+
+ public String getDefaultDatetimeFormat() {
+ return this.getDatetimeFormats().iterator().next();
+ }
+
+ public LinkedHashSet<String> getSecondaryDatetimeFormats() {
+ LinkedHashSet<String> datetimeFormats = (LinkedHashSet<String>)this.getDatetimeFormats().clone();
+ //
+ datetimeFormats.remove(this.getDefaultDatetimeFormat());
+ //
+ return datetimeFormats;
+ }
+
+ /* Locale. */
+
+ protected void setLocale(Locale locale) {
+ if (null == locale) {
+ throw new IllegalArgumentException("Invalid 'locale': null.");
+ }
+ //
+ this.locale = locale;
+ }
+
+ public Locale getLocale() {
+ return this.locale;
+ }
+
+ /* Conversions. */
+
+ protected static void checkDatetimeFormat(String datetimeFormat) {
+ if (MText.isBlank(datetimeFormat)) {
+ throw new IllegalArgumentException("Invalid 'datetimeFormat': null or empty.");
+ }
+ //
+ try {
+ DateTimeFormatter.ofPattern(datetimeFormat).withResolverStyle(ResolverStyle.STRICT);
+ }
+ catch (IllegalArgumentException exception) {
+ throw new IllegalArgumentException(String.format("Invalid 'datetimeFormat': %s.", datetimeFormat)); // no need to propagate exception
+ }
+ }
+
+ protected static LocalDateTime createDatetimeFromString(String x, String inputDatetimeFormat, Locale inputLocale) throws MInvalidConversionFormatException {
+ if (MText.isBlank(x)) {
+ throw new IllegalArgumentException("Invalid 'x': null or empty.");
+ }
+ MLocalDateTimeConverter.checkDatetimeFormat(inputDatetimeFormat);
+ if (null == inputLocale) {
+ throw new IllegalArgumentException("Invalid 'inputLocale': null.");
+ }
+ //
+ LocalDateTime dt = null;
+ try {
+ dt = LocalDateTime.parse(x, DateTimeFormatter.ofPattern(inputDatetimeFormat, inputLocale).withResolverStyle(ResolverStyle.STRICT));
+ }
+ catch (DateTimeParseException exception) {
+ throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputDatetimeFormat)); // no need to propagate exception
+ }
+ //
+ return dt;
+ }
+
+ protected static String createStringFromDatetime(LocalDateTime datetime, String outputDatetimeFormat, Locale outputLocale) {
+ if (null == datetime) {
+ throw new IllegalArgumentException("Invalid 'datetime': null.");
+ }
+ MLocalDateTimeConverter.checkDatetimeFormat(outputDatetimeFormat);
+ if (null == outputLocale) {
+ throw new IllegalArgumentException("Invalid 'outputLocale': null.");
+ }
+ //
+ return datetime.format(DateTimeFormatter.ofPattern(outputDatetimeFormat, outputLocale).withResolverStyle(ResolverStyle.STRICT));
+ }
+
+ public LocalDateTime createDatetimeFromString(String x) throws MInvalidConversionFormatException {
+ LocalDateTime y = null;
+ for (String datetimeFormat: this.getDatetimeFormats()) {
+ try {
+ y = MLocalDateTimeConverter.createDatetimeFromString(x, datetimeFormat, this.getLocale());
+ //
+ return y;
+ }
+ catch (MInvalidConversionFormatException exception) {
+ }
+ }
+ if (null == y) {
+ throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x));
+ }
+ //
+ return y; // necessary to avoid Java compilation errors
+ }
+
+ public String createStringFromDatetime(LocalDateTime x) {
+ return MLocalDateTimeConverter.createStringFromDatetime(x, this.getDefaultDatetimeFormat(), this.getLocale());
+ }
+
+}
--- /dev/null
+/**
+ * Macaco
+ * Copyright (c) 2009-2024 Marco Zanon <info@marcozanon.com>.
+ * See LICENSE for details.
+ */
+
+package com.marcozanon.macaco.conversions;
+
+import com.marcozanon.macaco.MObject;
+import com.marcozanon.macaco.text.MText;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.ParsePosition;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+
+public class MNumberConverter extends MObject {
+
+ protected LinkedHashSet<String> numberFormats = new LinkedHashSet<String>();
+ protected Locale locale = null;
+
+ /* */
+
+ public MNumberConverter(String defaultNumberFormat, Locale locale) {
+ super();
+ //
+ this.addNumberFormat(defaultNumberFormat);
+ this.setLocale(locale);
+ }
+
+ public MNumberConverter(LinkedHashSet<String> numberFormats, Locale locale) {
+ super();
+ //
+ this.setNumberFormats(numberFormats);
+ this.setLocale(locale);
+ }
+
+ @Override
+ public MNumberConverter clone() {
+ return new MNumberConverter(this.getNumberFormats(), this.getLocale());
+ }
+
+ /* Number formats. */
+
+ public void setNumberFormats(LinkedHashSet<String> numberFormats) {
+ if (null == numberFormats) {
+ throw new IllegalArgumentException("Invalid 'numberFormats': null.");
+ }
+ else if (0 == numberFormats.size()) {
+ throw new IllegalArgumentException("Invalid 'numberFormats': empty.");
+ }
+ else {
+ for (String numberFormat: numberFormats) {
+ MNumberConverter.checkNumberFormat(numberFormat);
+ }
+ }
+ //
+ synchronized (this.numberFormats) {
+ this.numberFormats = numberFormats;
+ }
+ }
+
+ public void addNumberFormat(String numberFormat) {
+ MNumberConverter.checkNumberFormat(numberFormat);
+ //
+ synchronized (this.numberFormats) {
+ this.numberFormats.add(numberFormat);
+ }
+ }
+
+ public LinkedHashSet<String> getNumberFormats() {
+ return this.numberFormats;
+ }
+
+ public String getDefaultNumberFormat() {
+ return this.getNumberFormats().iterator().next();
+ }
+
+ public LinkedHashSet<String> getSecondaryNumberFormats() {
+ LinkedHashSet<String> numberFormats = (LinkedHashSet<String>)this.getNumberFormats().clone();
+ //
+ numberFormats.remove(this.getDefaultNumberFormat());
+ //
+ return numberFormats;
+ }
+
+ /* Locale. */
+
+ protected void setLocale(Locale locale) {
+ if (null == locale) {
+ throw new IllegalArgumentException("Invalid 'locale': null.");
+ }
+ //
+ this.locale = locale;
+ }
+
+ public Locale getLocale() {
+ return this.locale;
+ }
+
+ /* Conversions. */
+
+ protected static void checkNumberFormat(String numberFormat) {
+ if (MText.isBlank(numberFormat)) {
+ throw new IllegalArgumentException("Invalid 'numberFormat': null or empty.");
+ }
+ //
+ try {
+ DecimalFormat testNumberFormat = new DecimalFormat(numberFormat);
+ }
+ catch (IllegalArgumentException exception) {
+ throw new IllegalArgumentException(String.format("Invalid 'numberFormat': %s.", numberFormat)); // no need to propagate exception
+ }
+ }
+
+ protected static BigDecimal createNumberFromString(String x, String inputNumberFormat, Locale inputLocale) throws MInvalidConversionFormatException {
+ if (MText.isBlank(x)) {
+ throw new IllegalArgumentException("Invalid 'x': null or empty.");
+ }
+ MNumberConverter.checkNumberFormat(inputNumberFormat);
+ if (null == inputLocale) {
+ throw new IllegalArgumentException("Invalid 'inputLocale': null.");
+ }
+ //
+ DecimalFormatSymbols dfs = new DecimalFormatSymbols(inputLocale);
+ DecimalFormat df = new DecimalFormat(inputNumberFormat, dfs);
+ df.setParseBigDecimal(true);
+ //
+ ParsePosition validPosition = new ParsePosition(0);
+ BigDecimal bd = (BigDecimal)df.parse(x, validPosition);
+ if (validPosition.getIndex() < x.length()) {
+ throw new MInvalidConversionFormatException(String.format("Invalid 'x' or parsing: %s (input format: %s).", x, inputNumberFormat));
+ }
+ //
+ return bd;
+ }
+
+ protected static String createStringFromNumber(BigDecimal number, String outputNumberFormat, Locale outputLocale) {
+ if (null == number) {
+ throw new IllegalArgumentException("Invalid 'number': null.");
+ }
+ MNumberConverter.checkNumberFormat(outputNumberFormat);
+ if (null == outputLocale) {
+ throw new IllegalArgumentException("Invalid 'outputLocale': null.");
+ }
+ //
+ DecimalFormatSymbols dfs = new DecimalFormatSymbols(outputLocale);
+ DecimalFormat df = new DecimalFormat(outputNumberFormat, dfs);
+ df.setRoundingMode(RoundingMode.HALF_UP);
+ //
+ return df.format(number);
+ }
+
+ public BigDecimal createNumberFromString(String x) throws MInvalidConversionFormatException {
+ BigDecimal y = null;
+ for (String numberFormat: this.getNumberFormats()) {
+ try {
+ y = MNumberConverter.createNumberFromString(x, numberFormat, this.getLocale());
+ //
+ return y;
+ }
+ catch (MInvalidConversionFormatException exception) {
+ }
+ }
+ if (null == y) {
+ throw new MInvalidConversionFormatException(String.format("Invalid 'x': %s.", x));
+ }
+ //
+ return y; // necessary to avoid Java compilation errors
+ }
+
+ public String createStringFromNumber(BigDecimal x) {
+ return MNumberConverter.createStringFromNumber(x, this.getDefaultNumberFormat(), this.getLocale());
+ }
+
+}