1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.provisioning.api.utils;
20
21 import java.text.DecimalFormat;
22 import java.text.DecimalFormatSymbols;
23 import java.text.ParseException;
24 import java.time.LocalDate;
25 import java.time.LocalDateTime;
26 import java.time.OffsetDateTime;
27 import java.time.ZoneOffset;
28 import java.time.format.DateTimeFormatter;
29 import java.time.format.DateTimeParseException;
30 import java.time.temporal.ChronoUnit;
31 import java.time.temporal.TemporalAccessor;
32 import java.util.Arrays;
33 import java.util.Locale;
34 import org.apache.commons.lang3.StringUtils;
35 import org.apache.syncope.common.lib.SyncopeConstants;
36
37
38
39
40 public final class FormatUtils {
41
42 private static final String NO_CONVERSION_PATTERN = "#,##0.###";
43
44 private static final ThreadLocal<DecimalFormat> DECIMAL_FORMAT = ThreadLocal.withInitial(() -> {
45 DecimalFormat df = new DecimalFormat(NO_CONVERSION_PATTERN);
46 df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
47 return df;
48 });
49
50 public static final ZoneOffset DEFAULT_OFFSET = OffsetDateTime.now().getOffset();
51
52 public static String format(final TemporalAccessor temporal) {
53 return OffsetDateTime.from(temporal).
54 truncatedTo(ChronoUnit.SECONDS).
55 format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
56 }
57
58 public static String format(final TemporalAccessor temporal, final String conversionPattern) {
59 return OffsetDateTime.from(temporal).format(DateTimeFormatter.ofPattern(conversionPattern));
60 }
61
62 public static String format(final long number) {
63 return format(number, NO_CONVERSION_PATTERN);
64 }
65
66 public static String format(final long number, final String conversionPattern) {
67 DecimalFormat df = DECIMAL_FORMAT.get();
68
69 String previous = df.toPattern();
70 if (!previous.equals(conversionPattern)) {
71 df.applyPattern(conversionPattern);
72 }
73
74 String formatted = df.format(number);
75
76 if (!previous.equals(conversionPattern)) {
77 df.applyPattern(previous);
78 }
79
80 return formatted;
81 }
82
83 public static String format(final double number) {
84 return format(number, NO_CONVERSION_PATTERN);
85 }
86
87 public static String format(final double number, final String conversionPattern) {
88 DecimalFormat df = DECIMAL_FORMAT.get();
89
90 String previous = df.toPattern();
91 if (!previous.equals(conversionPattern)) {
92 df.applyPattern(conversionPattern);
93 }
94
95 String formatted = df.format(number);
96
97 if (!previous.equals(conversionPattern)) {
98 df.applyPattern(previous);
99 }
100
101 return formatted;
102 }
103
104 public static OffsetDateTime parseDate(final String source)
105 throws DateTimeParseException {
106
107 for (String pattern : SyncopeConstants.DATE_PATTERNS) {
108 try {
109 return parseDate(source, pattern);
110 } catch (DateTimeParseException e) {
111
112 }
113 }
114
115 throw new DateTimeParseException(
116 "Could not parse with any of " + Arrays.asList(SyncopeConstants.DATE_PATTERNS), source, 0);
117 }
118
119 public static OffsetDateTime parseDate(final String source, final String conversionPattern)
120 throws DateTimeParseException {
121
122 DateTimeParseException dtpe;
123
124 DateTimeFormatter dtf = DateTimeFormatter.ofPattern(conversionPattern);
125 try {
126 if (StringUtils.containsIgnoreCase(conversionPattern, "Z")) {
127 return OffsetDateTime.parse(source, dtf);
128 } else {
129 return LocalDateTime.parse(source, dtf).atZone(DEFAULT_OFFSET).toOffsetDateTime();
130 }
131 } catch (DateTimeParseException e) {
132 dtpe = e;
133 }
134 try {
135 return LocalDate.parse(source, dtf).atStartOfDay(ZoneOffset.UTC).toOffsetDateTime();
136 } catch (DateTimeParseException e) {
137 dtpe = e;
138 }
139
140 throw dtpe;
141 }
142
143 public static Number parseNumber(final String source, final String conversionPattern) throws ParseException {
144 DecimalFormat df = DECIMAL_FORMAT.get();
145 df.applyPattern(conversionPattern);
146 return df.parse(source);
147 }
148
149 public static void clear() {
150 DECIMAL_FORMAT.remove();
151 }
152
153 private FormatUtils() {
154
155 }
156 }