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