29
29
/**
30
30
* Support {@code Duration} parsing and printing in several styles, as listed in
31
31
* {@link DurationFormat.Style}.
32
+ *
32
33
* <p>Some styles may not enforce any unit to be present, defaulting to {@code DurationFormat.Unit#MILLIS}
33
34
* in that case. Methods in this class offer overloads that take a {@link DurationFormat.Unit} to
34
35
* be used as a fall-back instead of the ultimate MILLIS default.
40
41
*/
41
42
public abstract class DurationFormatterUtils {
42
43
43
- private DurationFormatterUtils () {
44
- // singleton
45
- }
44
+ private static final Pattern ISO_8601_PATTERN = Pattern .compile ("^[+-]?[pP].*$" );
46
45
47
- /**
48
- * Parse the given value to a duration.
49
- * @param value the value to parse
50
- * @param style the style in which to parse
51
- * @return a duration
52
- */
53
- public static Duration parse (String value , DurationFormat .Style style ) {
54
- return parse (value , style , null );
55
- }
46
+ private static final Pattern SIMPLE_PATTERN = Pattern .compile ("^([+-]?\\ d+)([a-zA-Z]{0,2})$" );
47
+
48
+ private static final Pattern COMPOSITE_PATTERN = Pattern .compile ("^([+-]?)\\ (?\\ s?(\\ d+d)?\\ s?(\\ d+h)?\\ s?(\\ d+m)?" +
49
+ "\\ s?(\\ d+s)?\\ s?(\\ d+ms)?\\ s?(\\ d+us)?\\ s?(\\ d+ns)?\\ )?$" );
56
50
57
- /**
58
- * Parse the given value to a duration.
59
- * @param value the value to parse
60
- * @param style the style in which to parse
61
- * @param unit the duration unit to use if the value doesn't specify one ({@code null}
62
- * will default to ms)
63
- * @return a duration
64
- */
65
- public static Duration parse (String value , DurationFormat .Style style , DurationFormat .@ Nullable Unit unit ) {
66
- Assert .hasText (value , () -> "Value must not be empty" );
67
- return switch (style ) {
68
- case ISO8601 -> parseIso8601 (value );
69
- case SIMPLE -> parseSimple (value , unit );
70
- case COMPOSITE -> parseComposite (value );
71
- };
72
- }
73
51
74
52
/**
75
53
* Print the specified duration in the specified style.
@@ -98,27 +76,30 @@ public static String print(Duration value, DurationFormat.Style style, DurationF
98
76
}
99
77
100
78
/**
101
- * Detect the style then parse the value to return a duration.
79
+ * Parse the given value to a duration.
102
80
* @param value the value to parse
103
- * @return the parsed duration
104
- * @throws IllegalArgumentException if the value is not a known style or cannot be
105
- * parsed
81
+ * @param style the style in which to parse
82
+ * @return a duration
106
83
*/
107
- public static Duration detectAndParse (String value ) {
108
- return detectAndParse (value , null );
84
+ public static Duration parse (String value , DurationFormat . Style style ) {
85
+ return parse (value , style , null );
109
86
}
110
87
111
88
/**
112
- * Detect the style then parse the value to return a duration.
89
+ * Parse the given value to a duration.
113
90
* @param value the value to parse
91
+ * @param style the style in which to parse
114
92
* @param unit the duration unit to use if the value doesn't specify one ({@code null}
115
93
* will default to ms)
116
- * @return the parsed duration
117
- * @throws IllegalArgumentException if the value is not a known style or cannot be
118
- * parsed
94
+ * @return a duration
119
95
*/
120
- public static Duration detectAndParse (String value , DurationFormat .@ Nullable Unit unit ) {
121
- return parse (value , detect (value ), unit );
96
+ public static Duration parse (String value , DurationFormat .Style style , DurationFormat .@ Nullable Unit unit ) {
97
+ Assert .hasText (value , () -> "Value must not be empty" );
98
+ return switch (style ) {
99
+ case ISO8601 -> parseIso8601 (value );
100
+ case SIMPLE -> parseSimple (value , unit );
101
+ case COMPOSITE -> parseComposite (value );
102
+ };
122
103
}
123
104
124
105
/**
@@ -142,10 +123,30 @@ public static DurationFormat.Style detect(String value) {
142
123
throw new IllegalArgumentException ("'" + value + "' is not a valid duration, cannot detect any known style" );
143
124
}
144
125
145
- private static final Pattern ISO_8601_PATTERN = Pattern .compile ("^[+-]?[pP].*$" );
146
- private static final Pattern SIMPLE_PATTERN = Pattern .compile ("^([+-]?\\ d+)([a-zA-Z]{0,2})$" );
147
- private static final Pattern COMPOSITE_PATTERN = Pattern .compile ("^([+-]?)\\ (?\\ s?(\\ d+d)?\\ s?(\\ d+h)?\\ s?(\\ d+m)?" +
148
- "\\ s?(\\ d+s)?\\ s?(\\ d+ms)?\\ s?(\\ d+us)?\\ s?(\\ d+ns)?\\ )?$" );
126
+ /**
127
+ * Detect the style then parse the value to return a duration.
128
+ * @param value the value to parse
129
+ * @return the parsed duration
130
+ * @throws IllegalArgumentException if the value is not a known style or cannot be
131
+ * parsed
132
+ */
133
+ public static Duration detectAndParse (String value ) {
134
+ return detectAndParse (value , null );
135
+ }
136
+
137
+ /**
138
+ * Detect the style then parse the value to return a duration.
139
+ * @param value the value to parse
140
+ * @param unit the duration unit to use if the value doesn't specify one ({@code null}
141
+ * will default to ms)
142
+ * @return the parsed duration
143
+ * @throws IllegalArgumentException if the value is not a known style or cannot be
144
+ * parsed
145
+ */
146
+ public static Duration detectAndParse (String value , DurationFormat .@ Nullable Unit unit ) {
147
+ return parse (value , detect (value ), unit );
148
+ }
149
+
149
150
150
151
private static Duration parseIso8601 (String value ) {
151
152
try {
@@ -156,6 +157,11 @@ private static Duration parseIso8601(String value) {
156
157
}
157
158
}
158
159
160
+ private static String printSimple (Duration duration , DurationFormat .@ Nullable Unit unit ) {
161
+ unit = (unit == null ? DurationFormat .Unit .MILLIS : unit );
162
+ return unit .print (duration );
163
+ }
164
+
159
165
private static Duration parseSimple (String text , DurationFormat .@ Nullable Unit fallbackUnit ) {
160
166
try {
161
167
Matcher matcher = SIMPLE_PATTERN .matcher (text );
@@ -172,34 +178,6 @@ private static Duration parseSimple(String text, DurationFormat.@Nullable Unit f
172
178
}
173
179
}
174
180
175
- private static String printSimple (Duration duration , DurationFormat .@ Nullable Unit unit ) {
176
- unit = (unit == null ? DurationFormat .Unit .MILLIS : unit );
177
- return unit .print (duration );
178
- }
179
-
180
- private static Duration parseComposite (String text ) {
181
- try {
182
- Matcher matcher = COMPOSITE_PATTERN .matcher (text );
183
- Assert .state (matcher .matches () && matcher .groupCount () > 1 , "Does not match composite duration pattern" );
184
- String sign = matcher .group (1 );
185
- boolean negative = sign != null && sign .equals ("-" );
186
-
187
- Duration result = Duration .ZERO ;
188
- DurationFormat .Unit [] units = DurationFormat .Unit .values ();
189
- for (int i = 2 ; i < matcher .groupCount () + 1 ; i ++) {
190
- String segment = matcher .group (i );
191
- if (StringUtils .hasText (segment )) {
192
- DurationFormat .Unit unit = units [units .length - i + 1 ];
193
- result = result .plus (unit .parse (segment .replace (unit .asSuffix (), "" )));
194
- }
195
- }
196
- return negative ? result .negated () : result ;
197
- }
198
- catch (Exception ex ) {
199
- throw new IllegalArgumentException ("'" + text + "' is not a valid composite duration" , ex );
200
- }
201
- }
202
-
203
181
private static String printComposite (Duration duration ) {
204
182
if (duration .isZero ()) {
205
183
return DurationFormat .Unit .SECONDS .print (duration );
@@ -244,4 +222,27 @@ private static String printComposite(Duration duration) {
244
222
return result .toString ();
245
223
}
246
224
225
+ private static Duration parseComposite (String text ) {
226
+ try {
227
+ Matcher matcher = COMPOSITE_PATTERN .matcher (text );
228
+ Assert .state (matcher .matches () && matcher .groupCount () > 1 , "Does not match composite duration pattern" );
229
+ String sign = matcher .group (1 );
230
+ boolean negative = sign != null && sign .equals ("-" );
231
+
232
+ Duration result = Duration .ZERO ;
233
+ DurationFormat .Unit [] units = DurationFormat .Unit .values ();
234
+ for (int i = 2 ; i < matcher .groupCount () + 1 ; i ++) {
235
+ String segment = matcher .group (i );
236
+ if (StringUtils .hasText (segment )) {
237
+ DurationFormat .Unit unit = units [units .length - i + 1 ];
238
+ result = result .plus (unit .parse (segment .replace (unit .asSuffix (), "" )));
239
+ }
240
+ }
241
+ return negative ? result .negated () : result ;
242
+ }
243
+ catch (Exception ex ) {
244
+ throw new IllegalArgumentException ("'" + text + "' is not a valid composite duration" , ex );
245
+ }
246
+ }
247
+
247
248
}
0 commit comments