1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.lang3.time;
19
20 import static org.apache.commons.lang3.LangAssertions.assertIllegalArgumentException;
21 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
22 import static org.junit.jupiter.api.Assertions.assertEquals;
23 import static org.junit.jupiter.api.Assertions.assertFalse;
24 import static org.junit.jupiter.api.Assertions.assertNotEquals;
25 import static org.junit.jupiter.api.Assertions.assertNotNull;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27
28 import java.lang.reflect.Constructor;
29 import java.lang.reflect.Modifier;
30 import java.time.Duration;
31 import java.util.Calendar;
32 import java.util.TimeZone;
33
34 import org.apache.commons.lang3.AbstractLangTest;
35 import org.apache.commons.lang3.time.DurationFormatUtils.Token;
36 import org.junit.jupiter.api.Test;
37 import org.junitpioneer.jupiter.DefaultTimeZone;
38
39
40
41
42
43
44
45 class DurationFormatUtilsTest extends AbstractLangTest {
46
47 private static final int FOUR_YEARS = 365 * 3 + 366;
48
49 private void assertEqualDuration(final String expected, final int[] start, final int[] end, final String format) {
50 assertEqualDuration(null, expected, start, end, format);
51 }
52
53 private void assertEqualDuration(final String message, final String expected, final int[] start, final int[] end, final String format) {
54 final Calendar cal1 = Calendar.getInstance();
55 cal1.set(start[0], start[1], start[2], start[3], start[4], start[5]);
56 cal1.set(Calendar.MILLISECOND, 0);
57 final Calendar cal2 = Calendar.getInstance();
58 cal2.set(end[0], end[1], end[2], end[3], end[4], end[5]);
59 cal2.set(Calendar.MILLISECOND, 0);
60 final long milli1 = cal1.getTime().getTime();
61 final long milli2 = cal2.getTime().getTime();
62 final String result = DurationFormatUtils.formatPeriod(milli1, milli2, format);
63 if (message == null) {
64 assertEquals(expected, result);
65 } else {
66 assertEquals(expected, result, message);
67 }
68 }
69
70 private void bruteForce(final int year, final int month, final int day, final String format, final int calendarType) {
71 final String msg = year + "-" + month + "-" + day + " to ";
72 final Calendar c = Calendar.getInstance();
73 c.set(year, month, day, 0, 0, 0);
74 final int[] array1 = { year, month, day, 0, 0, 0 };
75 final int[] array2 = { year, month, day, 0, 0, 0 };
76 for (int i = 0; i < FOUR_YEARS; i++) {
77 array2[0] = c.get(Calendar.YEAR);
78 array2[1] = c.get(Calendar.MONTH);
79 array2[2] = c.get(Calendar.DAY_OF_MONTH);
80 final String tmpMsg = msg + array2[0] + "-" + array2[1] + "-" + array2[2] + " at ";
81 assertEqualDuration(tmpMsg + i, Integer.toString(i), array1, array2, format);
82 c.add(calendarType, 1);
83 }
84 }
85
86 private DurationFormatUtils.Token createTokenWithCount(final CharSequence value, final int count) {
87 final DurationFormatUtils.Token token = new DurationFormatUtils.Token(value, false, -1);
88
89 assertNotNull(token.toString());
90 for (int i = 1; i < count; i++) {
91 token.increment();
92 assertNotNull(token.toString());
93 }
94 return token;
95 }
96
97 @Test
98 void testAlternatingLiteralOptionals() {
99 final String format = "['d'dH'h'][m'm']['s's]['ms'S]";
100 assertEquals("d1", DurationFormatUtils.formatDuration(Duration.ofDays(1).toMillis(), format));
101 assertEquals("1h", DurationFormatUtils.formatDuration(Duration.ofHours(1).toMillis(), format));
102 assertEquals("1m", DurationFormatUtils.formatDuration(Duration.ofMinutes(1).toMillis(), format));
103 assertEquals("s1", DurationFormatUtils.formatDuration(Duration.ofSeconds(1).toMillis(), format));
104 assertEquals("ms001", DurationFormatUtils.formatDuration(Duration.ofMillis(1).toMillis(), format));
105 assertEquals("d1s1", DurationFormatUtils.formatDuration(Duration.ofDays(1).plusSeconds(1).toMillis(), format));
106 assertEquals("d11h", DurationFormatUtils.formatDuration(Duration.ofDays(1).plusHours(1).toMillis(), format));
107 assertEquals("d11h1m", DurationFormatUtils.formatDuration(Duration.ofDays(1).plusHours(1).plusMinutes(1).toMillis(), format));
108 assertEquals("d11h1ms1", DurationFormatUtils.formatDuration(Duration.ofDays(1).plusHours(1).plusMinutes(1).plusSeconds(1).toMillis(), format));
109 assertEquals("d11h1ms1ms001",
110 DurationFormatUtils.formatDuration(Duration.ofDays(1).plusHours(1).plusMinutes(1).plusSeconds(1).plusMillis(1).toMillis(), format));
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 @Test
145 @DefaultTimeZone(TimeZones.GMT_ID)
146 void testEdgeDurations() {
147
148 TimeZone.setDefault(FastTimeZone.getGmtTimeZone());
149 assertEqualDuration("01", new int[] { 2006, 0, 15, 0, 0, 0 }, new int[] { 2006, 2, 10, 0, 0, 0 }, "MM");
150 assertEqualDuration("12", new int[] { 2005, 0, 15, 0, 0, 0 }, new int[] { 2006, 0, 15, 0, 0, 0 }, "MM");
151 assertEqualDuration("12", new int[] { 2005, 0, 15, 0, 0, 0 }, new int[] { 2006, 0, 16, 0, 0, 0 }, "MM");
152 assertEqualDuration("11", new int[] { 2005, 0, 15, 0, 0, 0 }, new int[] { 2006, 0, 14, 0, 0, 0 }, "MM");
153
154 assertEqualDuration("01 26", new int[] { 2006, 0, 15, 0, 0, 0 }, new int[] { 2006, 2, 10, 0, 0, 0 }, "MM dd");
155 assertEqualDuration("54", new int[] { 2006, 0, 15, 0, 0, 0 }, new int[] { 2006, 2, 10, 0, 0, 0 }, "dd");
156
157 assertEqualDuration("09 12", new int[] { 2006, 1, 20, 0, 0, 0 }, new int[] { 2006, 11, 4, 0, 0, 0 }, "MM dd");
158 assertEqualDuration("287", new int[] { 2006, 1, 20, 0, 0, 0 }, new int[] { 2006, 11, 4, 0, 0, 0 }, "dd");
159
160 assertEqualDuration("11 30", new int[] { 2006, 0, 2, 0, 0, 0 }, new int[] { 2007, 0, 1, 0, 0, 0 }, "MM dd");
161 assertEqualDuration("364", new int[] { 2006, 0, 2, 0, 0, 0 }, new int[] { 2007, 0, 1, 0, 0, 0 }, "dd");
162
163 assertEqualDuration("12 00", new int[] { 2006, 0, 1, 0, 0, 0 }, new int[] { 2007, 0, 1, 0, 0, 0 }, "MM dd");
164 assertEqualDuration("365", new int[] { 2006, 0, 1, 0, 0, 0 }, new int[] { 2007, 0, 1, 0, 0, 0 }, "dd");
165
166 assertEqualDuration("31", new int[] { 2006, 0, 1, 0, 0, 0 }, new int[] { 2006, 1, 1, 0, 0, 0 }, "dd");
167
168 assertEqualDuration("92", new int[] { 2005, 9, 1, 0, 0, 0 }, new int[] { 2006, 0, 1, 0, 0, 0 }, "dd");
169 assertEqualDuration("77", new int[] { 2005, 9, 16, 0, 0, 0 }, new int[] { 2006, 0, 1, 0, 0, 0 }, "dd");
170
171
172 assertEqualDuration("136", new int[] { 2005, 9, 16, 0, 0, 0 }, new int[] { 2006, 2, 1, 0, 0, 0 }, "dd");
173
174 assertEqualDuration("136", new int[] { 2004, 9, 16, 0, 0, 0 }, new int[] { 2005, 2, 1, 0, 0, 0 }, "dd");
175
176 assertEqualDuration("137", new int[] { 2003, 9, 16, 0, 0, 0 }, new int[] { 2004, 2, 1, 0, 0, 0 }, "dd");
177
178 assertEqualDuration("135", new int[] { 2003, 9, 16, 0, 0, 0 }, new int[] { 2004, 1, 28, 0, 0, 0 }, "dd");
179
180 assertEqualDuration("364", new int[] { 2007, 0, 2, 0, 0, 0 }, new int[] { 2008, 0, 1, 0, 0, 0 }, "dd");
181 assertEqualDuration("729", new int[] { 2006, 0, 2, 0, 0, 0 }, new int[] { 2008, 0, 1, 0, 0, 0 }, "dd");
182
183 assertEqualDuration("365", new int[] { 2007, 2, 2, 0, 0, 0 }, new int[] { 2008, 2, 1, 0, 0, 0 }, "dd");
184 assertEqualDuration("333", new int[] { 2007, 1, 2, 0, 0, 0 }, new int[] { 2008, 0, 1, 0, 0, 0 }, "dd");
185
186 assertEqualDuration("28", new int[] { 2008, 1, 2, 0, 0, 0 }, new int[] { 2008, 2, 1, 0, 0, 0 }, "dd");
187 assertEqualDuration("393", new int[] { 2007, 1, 2, 0, 0, 0 }, new int[] { 2008, 2, 1, 0, 0, 0 }, "dd");
188
189 assertEqualDuration("369", new int[] { 2004, 0, 29, 0, 0, 0 }, new int[] { 2005, 1, 1, 0, 0, 0 }, "dd");
190
191 assertEqualDuration("338", new int[] { 2004, 1, 29, 0, 0, 0 }, new int[] { 2005, 1, 1, 0, 0, 0 }, "dd");
192
193 assertEqualDuration("28", new int[] { 2004, 2, 8, 0, 0, 0 }, new int[] { 2004, 3, 5, 0, 0, 0 }, "dd");
194
195 assertEqualDuration("48", new int[] { 1992, 1, 29, 0, 0, 0 }, new int[] { 1996, 1, 29, 0, 0, 0 }, "M");
196
197
198
199 assertEqualDuration("11", new int[] { 1996, 1, 29, 0, 0, 0 }, new int[] { 1997, 1, 28, 0, 0, 0 }, "M");
200
201 assertEqualDuration("11 28", new int[] { 1996, 1, 29, 0, 0, 0 }, new int[] { 1997, 1, 28, 0, 0, 0 }, "M d");
202
203 }
204
205 @Test
206 void testEmptyOptionals() {
207 assertEquals("", DurationFormatUtils.formatDuration(0L, "[d'd'][H'h'][m'm'][s's']"));
208 assertEquals("", DurationFormatUtils.formatDuration(0L, "['d''h''m''s's]"));
209 }
210
211 @Test
212 void testFormatDuration() {
213 long duration = 0;
214 assertEquals("0", DurationFormatUtils.formatDuration(duration, "y"));
215 assertEquals("0", DurationFormatUtils.formatDuration(duration, "M"));
216 assertEquals("0", DurationFormatUtils.formatDuration(duration, "d"));
217 assertEquals("0", DurationFormatUtils.formatDuration(duration, "H"));
218 assertEquals("0", DurationFormatUtils.formatDuration(duration, "m"));
219 assertEquals("0", DurationFormatUtils.formatDuration(duration, "s"));
220 assertEquals("0", DurationFormatUtils.formatDuration(duration, "S"));
221 assertEquals("0000", DurationFormatUtils.formatDuration(duration, "SSSS"));
222 assertEquals("0000", DurationFormatUtils.formatDuration(duration, "yyyy"));
223 assertEquals("0000", DurationFormatUtils.formatDuration(duration, "yyMM"));
224
225 duration = 60 * 1000;
226 assertEquals("0", DurationFormatUtils.formatDuration(duration, "y"));
227 assertEquals("0", DurationFormatUtils.formatDuration(duration, "M"));
228 assertEquals("0", DurationFormatUtils.formatDuration(duration, "d"));
229 assertEquals("0", DurationFormatUtils.formatDuration(duration, "H"));
230 assertEquals("1", DurationFormatUtils.formatDuration(duration, "m"));
231 assertEquals("60", DurationFormatUtils.formatDuration(duration, "s"));
232 assertEquals("60000", DurationFormatUtils.formatDuration(duration, "S"));
233 assertEquals("01:00", DurationFormatUtils.formatDuration(duration, "mm:ss"));
234
235 final Calendar base = Calendar.getInstance();
236 base.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
237 base.set(Calendar.MILLISECOND, 0);
238
239 final Calendar cal = Calendar.getInstance();
240 cal.set(2003, Calendar.FEBRUARY, 1, 0, 0, 0);
241 cal.set(Calendar.MILLISECOND, 0);
242 duration = cal.getTime().getTime() - base.getTime().getTime();
243
244
245 final int days = 366 + 365 + 365 + 31;
246 assertEquals("0 0 " + days, DurationFormatUtils.formatDuration(duration, "y M d"));
247 }
248
249 @Test
250 void testFormatDurationHMS() {
251 long time = 0;
252 assertEquals("00:00:00.000", DurationFormatUtils.formatDurationHMS(time));
253
254 time = 1;
255 assertEquals("00:00:00.001", DurationFormatUtils.formatDurationHMS(time));
256
257 time = 15;
258 assertEquals("00:00:00.015", DurationFormatUtils.formatDurationHMS(time));
259
260 time = 165;
261 assertEquals("00:00:00.165", DurationFormatUtils.formatDurationHMS(time));
262
263 time = 1675;
264 assertEquals("00:00:01.675", DurationFormatUtils.formatDurationHMS(time));
265
266 time = 13465;
267 assertEquals("00:00:13.465", DurationFormatUtils.formatDurationHMS(time));
268
269 time = 72789;
270 assertEquals("00:01:12.789", DurationFormatUtils.formatDurationHMS(time));
271
272 time = 12789 + 32 * 60000;
273 assertEquals("00:32:12.789", DurationFormatUtils.formatDurationHMS(time));
274
275 time = 12789 + 62 * 60000;
276 assertEquals("01:02:12.789", DurationFormatUtils.formatDurationHMS(time));
277 }
278
279 @Test
280 void testFormatDurationISO() {
281 assertEquals("P0Y0M0DT0H0M0.000S", DurationFormatUtils.formatDurationISO(0L));
282 assertEquals("P0Y0M0DT0H0M0.001S", DurationFormatUtils.formatDurationISO(1L));
283 assertEquals("P0Y0M0DT0H0M0.010S", DurationFormatUtils.formatDurationISO(10L));
284 assertEquals("P0Y0M0DT0H0M0.100S", DurationFormatUtils.formatDurationISO(100L));
285 assertEquals("P0Y0M0DT0H1M15.321S", DurationFormatUtils.formatDurationISO(75321L));
286 }
287
288
289
290
291 @Test
292 void testFormatDurationPluralWords() {
293 final long oneSecond = 1000;
294 final long oneMinute = oneSecond * 60;
295 final long oneHour = oneMinute * 60;
296 final long oneDay = oneHour * 24;
297 String text;
298
299 text = DurationFormatUtils.formatDurationWords(oneSecond, false, false);
300 assertEquals("0 days 0 hours 0 minutes 1 second", text);
301 text = DurationFormatUtils.formatDurationWords(oneSecond * 2, false, false);
302 assertEquals("0 days 0 hours 0 minutes 2 seconds", text);
303 text = DurationFormatUtils.formatDurationWords(oneSecond * 11, false, false);
304 assertEquals("0 days 0 hours 0 minutes 11 seconds", text);
305
306 text = DurationFormatUtils.formatDurationWords(oneMinute, false, false);
307 assertEquals("0 days 0 hours 1 minute 0 seconds", text);
308 text = DurationFormatUtils.formatDurationWords(oneMinute * 2, false, false);
309 assertEquals("0 days 0 hours 2 minutes 0 seconds", text);
310 text = DurationFormatUtils.formatDurationWords(oneMinute * 11, false, false);
311 assertEquals("0 days 0 hours 11 minutes 0 seconds", text);
312 text = DurationFormatUtils.formatDurationWords(oneMinute + oneSecond, false, false);
313 assertEquals("0 days 0 hours 1 minute 1 second", text);
314
315 text = DurationFormatUtils.formatDurationWords(oneHour, false, false);
316 assertEquals("0 days 1 hour 0 minutes 0 seconds", text);
317 text = DurationFormatUtils.formatDurationWords(oneHour * 2, false, false);
318 assertEquals("0 days 2 hours 0 minutes 0 seconds", text);
319 text = DurationFormatUtils.formatDurationWords(oneHour * 11, false, false);
320 assertEquals("0 days 11 hours 0 minutes 0 seconds", text);
321 text = DurationFormatUtils.formatDurationWords(oneHour + oneMinute + oneSecond, false, false);
322 assertEquals("0 days 1 hour 1 minute 1 second", text);
323
324 text = DurationFormatUtils.formatDurationWords(oneDay, false, false);
325 assertEquals("1 day 0 hours 0 minutes 0 seconds", text);
326 text = DurationFormatUtils.formatDurationWords(oneDay * 2, false, false);
327 assertEquals("2 days 0 hours 0 minutes 0 seconds", text);
328 text = DurationFormatUtils.formatDurationWords(oneDay * 11, false, false);
329 assertEquals("11 days 0 hours 0 minutes 0 seconds", text);
330 text = DurationFormatUtils.formatDurationWords(oneDay + oneHour + oneMinute + oneSecond, false, false);
331 assertEquals("1 day 1 hour 1 minute 1 second", text);
332 }
333
334 @Test
335 void testFormatDurationWords() {
336 String text;
337
338 text = DurationFormatUtils.formatDurationWords(50 * 1000, true, false);
339 assertEquals("50 seconds", text);
340 text = DurationFormatUtils.formatDurationWords(65 * 1000, true, false);
341 assertEquals("1 minute 5 seconds", text);
342 text = DurationFormatUtils.formatDurationWords(120 * 1000, true, false);
343 assertEquals("2 minutes 0 seconds", text);
344 text = DurationFormatUtils.formatDurationWords(121 * 1000, true, false);
345 assertEquals("2 minutes 1 second", text);
346 text = DurationFormatUtils.formatDurationWords(72 * 60 * 1000, true, false);
347 assertEquals("1 hour 12 minutes 0 seconds", text);
348 text = DurationFormatUtils.formatDurationWords(24 * 60 * 60 * 1000, true, false);
349 assertEquals("1 day 0 hours 0 minutes 0 seconds", text);
350
351 text = DurationFormatUtils.formatDurationWords(50 * 1000, true, true);
352 assertEquals("50 seconds", text);
353 text = DurationFormatUtils.formatDurationWords(65 * 1000, true, true);
354 assertEquals("1 minute 5 seconds", text);
355 text = DurationFormatUtils.formatDurationWords(120 * 1000, true, true);
356 assertEquals("2 minutes", text);
357 text = DurationFormatUtils.formatDurationWords(121 * 1000, true, true);
358 assertEquals("2 minutes 1 second", text);
359 text = DurationFormatUtils.formatDurationWords(72 * 60 * 1000, true, true);
360 assertEquals("1 hour 12 minutes", text);
361 text = DurationFormatUtils.formatDurationWords(24 * 60 * 60 * 1000, true, true);
362 assertEquals("1 day", text);
363
364 text = DurationFormatUtils.formatDurationWords(50 * 1000, false, true);
365 assertEquals("0 days 0 hours 0 minutes 50 seconds", text);
366 text = DurationFormatUtils.formatDurationWords(65 * 1000, false, true);
367 assertEquals("0 days 0 hours 1 minute 5 seconds", text);
368 text = DurationFormatUtils.formatDurationWords(120 * 1000, false, true);
369 assertEquals("0 days 0 hours 2 minutes", text);
370 text = DurationFormatUtils.formatDurationWords(121 * 1000, false, true);
371 assertEquals("0 days 0 hours 2 minutes 1 second", text);
372 text = DurationFormatUtils.formatDurationWords(72 * 60 * 1000, false, true);
373 assertEquals("0 days 1 hour 12 minutes", text);
374 text = DurationFormatUtils.formatDurationWords(24 * 60 * 60 * 1000, false, true);
375 assertEquals("1 day", text);
376
377 text = DurationFormatUtils.formatDurationWords(50 * 1000, false, false);
378 assertEquals("0 days 0 hours 0 minutes 50 seconds", text);
379 text = DurationFormatUtils.formatDurationWords(65 * 1000, false, false);
380 assertEquals("0 days 0 hours 1 minute 5 seconds", text);
381 text = DurationFormatUtils.formatDurationWords(120 * 1000, false, false);
382 assertEquals("0 days 0 hours 2 minutes 0 seconds", text);
383 text = DurationFormatUtils.formatDurationWords(121 * 1000, false, false);
384 assertEquals("0 days 0 hours 2 minutes 1 second", text);
385 text = DurationFormatUtils.formatDurationWords(72 * 60 * 1000, false, false);
386 assertEquals("0 days 1 hour 12 minutes 0 seconds", text);
387 text = DurationFormatUtils.formatDurationWords(24 * 60 * 60 * 1000 + 72 * 60 * 1000, false, false);
388 assertEquals("1 day 1 hour 12 minutes 0 seconds", text);
389 text = DurationFormatUtils.formatDurationWords(2 * 24 * 60 * 60 * 1000 + 72 * 60 * 1000, false, false);
390 assertEquals("2 days 1 hour 12 minutes 0 seconds", text);
391 for (int i = 2; i < 31; i++) {
392 text = DurationFormatUtils.formatDurationWords(i * 24 * 60 * 60 * 1000L, false, false);
393 assertEquals(i + " days 0 hours 0 minutes 0 seconds", text);
394 }
395 }
396
397 @Test
398 void testFormatNegativeDuration() {
399 assertIllegalArgumentException(() -> DurationFormatUtils.formatDuration(-5000, "S", true));
400 }
401
402 @Test
403 void testFormatNegativeDurationHMS() {
404 assertIllegalArgumentException(() -> DurationFormatUtils.formatDurationHMS(-5000));
405 }
406
407 @Test
408 void testFormatNegativeDurationISO() {
409 assertIllegalArgumentException(() -> DurationFormatUtils.formatDurationISO(-5000));
410 }
411
412 @Test
413 void testFormatNegativeDurationWords() {
414 assertIllegalArgumentException(() -> DurationFormatUtils.formatDurationWords(-5000, true, true));
415 }
416
417 @Test
418 void testFormatPeriod() {
419 final Calendar cal1970 = Calendar.getInstance();
420 cal1970.set(1970, Calendar.JANUARY, 1, 0, 0, 0);
421 cal1970.set(Calendar.MILLISECOND, 0);
422 final long time1970 = cal1970.getTime().getTime();
423
424 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "y"));
425 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "M"));
426 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "d"));
427 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "H"));
428 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "m"));
429 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "s"));
430 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "S"));
431 assertEquals("0000", DurationFormatUtils.formatPeriod(time1970, time1970, "SSSS"));
432 assertEquals("0000", DurationFormatUtils.formatPeriod(time1970, time1970, "yyyy"));
433 assertEquals("0000", DurationFormatUtils.formatPeriod(time1970, time1970, "yyMM"));
434
435 long time = time1970 + 60 * 1000;
436 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time, "y"));
437 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time, "M"));
438 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time, "d"));
439 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time, "H"));
440 assertEquals("1", DurationFormatUtils.formatPeriod(time1970, time, "m"));
441 assertEquals("60", DurationFormatUtils.formatPeriod(time1970, time, "s"));
442 assertEquals("60000", DurationFormatUtils.formatPeriod(time1970, time, "S"));
443 assertEquals("01:00", DurationFormatUtils.formatPeriod(time1970, time, "mm:ss"));
444
445 final Calendar cal = Calendar.getInstance();
446 cal.set(1973, Calendar.JULY, 1, 0, 0, 0);
447 cal.set(Calendar.MILLISECOND, 0);
448 time = cal.getTime().getTime();
449 assertEquals("36", DurationFormatUtils.formatPeriod(time1970, time, "yM"));
450 assertEquals("3 years 6 months", DurationFormatUtils.formatPeriod(time1970, time, "y' years 'M' months'"));
451 assertEquals("03/06", DurationFormatUtils.formatPeriod(time1970, time, "yy/MM"));
452
453 cal.set(1973, Calendar.NOVEMBER, 1, 0, 0, 0);
454 cal.set(Calendar.MILLISECOND, 0);
455 time = cal.getTime().getTime();
456 assertEquals("310", DurationFormatUtils.formatPeriod(time1970, time, "yM"));
457 assertEquals("3 years 10 months", DurationFormatUtils.formatPeriod(time1970, time, "y' years 'M' months'"));
458 assertEquals("03/10", DurationFormatUtils.formatPeriod(time1970, time, "yy/MM"));
459
460 cal.set(1974, Calendar.JANUARY, 1, 0, 0, 0);
461 cal.set(Calendar.MILLISECOND, 0);
462 time = cal.getTime().getTime();
463 assertEquals("40", DurationFormatUtils.formatPeriod(time1970, time, "yM"));
464 assertEquals("4 years 0 months", DurationFormatUtils.formatPeriod(time1970, time, "y' ''years' M 'months'"));
465 assertEquals("4 years 0 months", DurationFormatUtils.formatPeriod(time1970, time, "y' years 'M' months'"));
466 assertEquals("4years 0months", DurationFormatUtils.formatPeriod(time1970, time, "y'years 'M'months'"));
467 assertEquals("04/00", DurationFormatUtils.formatPeriod(time1970, time, "yy/MM"));
468 assertEquals("48", DurationFormatUtils.formatPeriod(time1970, time, "M"));
469 assertEquals("48", DurationFormatUtils.formatPeriod(time1970, time, "MM"));
470 assertEquals("048", DurationFormatUtils.formatPeriod(time1970, time, "MMM"));
471
472 assertEquals("hello", DurationFormatUtils.formatPeriod(time1970, time, "'hello'"));
473 assertEquals("helloworld", DurationFormatUtils.formatPeriod(time1970, time, "'hello''world'"));
474 }
475
476 @Test
477 void testFormatPeriodeStartGreaterEnd() {
478 assertIllegalArgumentException(() -> DurationFormatUtils.formatPeriod(5000, 2500, "yy/MM"));
479 }
480
481 @SuppressWarnings("deprecation")
482 @Test
483 void testFormatPeriodISO() {
484 final TimeZone timeZone = TimeZones.getTimeZone("GMT-3");
485 final Calendar base = Calendar.getInstance(timeZone);
486 base.set(1970, Calendar.JANUARY, 1, 0, 0, 0);
487 base.set(Calendar.MILLISECOND, 0);
488
489 final Calendar cal = Calendar.getInstance(timeZone);
490 cal.set(2002, Calendar.FEBRUARY, 23, 9, 11, 12);
491 cal.set(Calendar.MILLISECOND, 1);
492 String text;
493
494 text = DateFormatUtils.format(cal, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), timeZone);
495 assertEquals("2002-02-23T09:11:12-03:00", text);
496
497 text = DurationFormatUtils.formatPeriod(base.getTime().getTime(), cal.getTime().getTime(),
498 DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN, false, timeZone);
499 assertEquals("P32Y1M22DT9H11M12.001S", text);
500
501 cal.set(1971, Calendar.FEBRUARY, 3, 10, 30, 0);
502 cal.set(Calendar.MILLISECOND, 0);
503 text = DurationFormatUtils.formatPeriod(base.getTime().getTime(), cal.getTime().getTime(),
504 DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN, false, timeZone);
505 assertEquals("P1Y1M2DT10H30M0.000S", text);
506
507
508 }
509
510 @Test
511 void testFormatPeriodISOAcrossMonths() {
512 final TimeZone tz = TimeZones.getTimeZone("GMT-3");
513
514 final Calendar start = Calendar.getInstance(tz);
515 start.clear();
516 start.set(2020, Calendar.JANUARY, 31);
517 final Calendar end = Calendar.getInstance(tz);
518 end.clear();
519 end.set(2020, Calendar.FEBRUARY, 1);
520 final String result = DurationFormatUtils.formatPeriod(start.getTimeInMillis(), end.getTimeInMillis(), DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN,
521 false, tz);
522 assertEquals("P0Y0M1DT0H0M0.000S", result);
523 }
524
525 @Test
526 void testFormatPeriodISOLeapYearBoundary() {
527 final TimeZone tz = TimeZones.getTimeZone("GMT-3");
528
529 final Calendar start = Calendar.getInstance(tz);
530 start.clear();
531 start.set(2020, Calendar.FEBRUARY, 29);
532 final Calendar end = Calendar.getInstance(tz);
533 end.clear();
534 end.set(2020, Calendar.MARCH, 1);
535 final String result = DurationFormatUtils.formatPeriod(start.getTimeInMillis(), end.getTimeInMillis(), DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN,
536 false, tz);
537 assertEquals("P0Y0M1DT0H0M0.000S", result);
538 }
539
540 @Test
541 void testFormatPeriodISOMethod() {
542 assertEquals("P0Y0M0DT0H0M0.000S", DurationFormatUtils.formatPeriodISO(0L, 0L));
543 assertEquals("P0Y0M0DT0H0M1.000S", DurationFormatUtils.formatPeriodISO(0L, 1000L));
544 assertEquals("P0Y0M0DT0H1M1.000S", DurationFormatUtils.formatPeriodISO(0L, 61000L));
545 }
546
547 @Test
548 void testFormatPeriodISOStartGreaterEnd() {
549 assertIllegalArgumentException(() -> DurationFormatUtils.formatPeriodISO(5000, 2000));
550 }
551
552
553
554
555 @Test
556 void testFourYears() {
557 final Calendar c = Calendar.getInstance();
558 c.set(2004, 0, 1, 0, 0, 0);
559 for (int i = 0; i < FOUR_YEARS; i++) {
560 bruteForce(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH), "d", Calendar.DAY_OF_MONTH);
561 c.add(Calendar.DAY_OF_MONTH, 1);
562 }
563 }
564
565
566 @Test
567 void testJiraLang281() {
568 assertEqualDuration("09", new int[] { 2005, 11, 31, 0, 0, 0 }, new int[] { 2006, 9, 6, 0, 0, 0 }, "MM");
569 }
570
571 @Test
572 void testLANG815() {
573 final Calendar calendar = Calendar.getInstance();
574 calendar.set(2012, Calendar.JULY, 30, 0, 0, 0);
575 final long startMillis = calendar.getTimeInMillis();
576
577 calendar.set(2012, Calendar.SEPTEMBER, 8);
578 final long endMillis = calendar.getTimeInMillis();
579
580 assertEquals("1 9", DurationFormatUtils.formatPeriod(startMillis, endMillis, "M d"));
581 }
582
583 @Test
584 void testLANG981() {
585 assertIllegalArgumentException(() -> DurationFormatUtils.lexx("'yMdHms''S"));
586 }
587 @Test
588 void testLANG982() {
589 assertEquals("61.999", DurationFormatUtils.formatDuration(61999, "s.S"));
590 assertEquals("1 1999", DurationFormatUtils.formatDuration(61999, "m S"));
591 assertEquals("61.999", DurationFormatUtils.formatDuration(61999, "s.SSS"));
592 assertEquals("1 1999", DurationFormatUtils.formatDuration(61999, "m SSS"));
593 assertEquals("61.0999", DurationFormatUtils.formatDuration(61999, "s.SSSS"));
594 assertEquals("1 1999", DurationFormatUtils.formatDuration(61999, "m SSSS"));
595 assertEquals("61.00999", DurationFormatUtils.formatDuration(61999, "s.SSSSS"));
596 assertEquals("1 01999", DurationFormatUtils.formatDuration(61999, "m SSSSS"));
597 }
598
599 @Test
600 void testLANG984() {
601 assertEquals("0", DurationFormatUtils.formatDuration(0, "S"));
602 assertEquals(Integer.toString(Integer.MAX_VALUE), DurationFormatUtils.formatDuration(Integer.MAX_VALUE, "S"));
603 long maxIntPlus = Integer.MAX_VALUE;
604 maxIntPlus++;
605 assertEquals(Long.toString(maxIntPlus), DurationFormatUtils.formatDuration(maxIntPlus, "S"));
606 assertEquals(Long.toString(Long.MAX_VALUE), DurationFormatUtils.formatDuration(Long.MAX_VALUE, "S"));
607 }
608
609 @Test
610 void testLexx() {
611
612 assertArrayEquals(new DurationFormatUtils.Token[] {
613 createTokenWithCount(DurationFormatUtils.y, 1),
614 createTokenWithCount(DurationFormatUtils.M, 1),
615 createTokenWithCount(DurationFormatUtils.d, 1),
616 createTokenWithCount(DurationFormatUtils.H, 1),
617 createTokenWithCount(DurationFormatUtils.m, 1),
618 createTokenWithCount(DurationFormatUtils.s, 1),
619 createTokenWithCount(DurationFormatUtils.S, 1) }, DurationFormatUtils.lexx("yMdHmsS"));
620
621
622 assertArrayEquals(new DurationFormatUtils.Token[] {
623 createTokenWithCount(DurationFormatUtils.H, 2),
624 createTokenWithCount(new StringBuilder(":"), 1),
625 createTokenWithCount(DurationFormatUtils.m, 2),
626 createTokenWithCount(new StringBuilder(":"), 1),
627 createTokenWithCount(DurationFormatUtils.s, 2),
628 createTokenWithCount(new StringBuilder("."), 1),
629 createTokenWithCount(DurationFormatUtils.S, 3) }, DurationFormatUtils.lexx("HH:mm:ss.SSS"));
630
631
632 assertArrayEquals(new DurationFormatUtils.Token[] {
633 createTokenWithCount(new StringBuilder("P"), 1),
634 createTokenWithCount(DurationFormatUtils.y, 4),
635 createTokenWithCount(new StringBuilder("Y"), 1),
636 createTokenWithCount(DurationFormatUtils.M, 1),
637 createTokenWithCount(new StringBuilder("M"), 1),
638 createTokenWithCount(DurationFormatUtils.d, 1),
639 createTokenWithCount(new StringBuilder("DT"), 1),
640 createTokenWithCount(DurationFormatUtils.H, 1),
641 createTokenWithCount(new StringBuilder("H"), 1),
642 createTokenWithCount(DurationFormatUtils.m, 1),
643 createTokenWithCount(new StringBuilder("M"), 1),
644 createTokenWithCount(DurationFormatUtils.s, 1),
645 createTokenWithCount(new StringBuilder("."), 1),
646 createTokenWithCount(DurationFormatUtils.S, 3),
647 createTokenWithCount(new StringBuilder("S"), 1) }, DurationFormatUtils.lexx(DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN));
648
649
650 final DurationFormatUtils.Token token = createTokenWithCount(DurationFormatUtils.y, 4);
651 assertEquals(token, token);
652 assertEquals(token.hashCode(), token.hashCode());
653 assertNotEquals(token, new Object(), "Token equal to non-Token class.");
654 final Token token2 = createTokenWithCount("", 1);
655 assertNotEquals(token, token2, "Token equal to Token with wrong value class.");
656 assertNotEquals(token.hashCode(), token2.hashCode());
657 assertNotEquals(token, createTokenWithCount(DurationFormatUtils.y, 1), "Token equal to Token with different count.");
658 final DurationFormatUtils.Token numToken = createTokenWithCount("1", 4);
659 assertEquals(numToken, numToken, "Token with Number value not equal to itself.");
660 }
661
662 @Test
663 void testLiteralPrefixOptionalToken() {
664 assertEquals(DurationFormatUtils.formatDuration(10000L, "s's'"), DurationFormatUtils.formatDuration(10000L, "['['d']']['<'H'>']['{'m'}']s's'"));
665 assertEquals(DurationFormatUtils.formatDuration(10000L, "s's'"), DurationFormatUtils.formatDuration(10000L, "['{'m'}']s's'"));
666 }
667
668
669 @Test
670 void testLowDurations() {
671 for (int hr = 0; hr < 24; hr++) {
672 for (int min = 0; min < 60; min++) {
673 for (int sec = 0; sec < 60; sec++) {
674 assertEqualDuration(hr + ":" + min + ":" + sec, new int[] { 2000, 0, 1, 0, 0, 0, 0 }, new int[] { 2000, 0, 1, hr, min, sec }, "H:m:s");
675 }
676 }
677 }
678 }
679
680 @Test
681 void testMultipleOptionalBlocks() {
682 assertEquals(DurationFormatUtils.formatDuration(Duration.ofHours(1).toMillis(), "'[['H']]'"),
683 DurationFormatUtils.formatDuration(Duration.ofHours(1).toMillis(), "['{'d'}']['[['H']]']"));
684 assertEquals(DurationFormatUtils.formatDuration(Duration.ofDays(1).toMillis(), "['{'d'}']"),
685 DurationFormatUtils.formatDuration(Duration.ofDays(1).toMillis(), "['{'d'}']['['H']']"));
686 }
687
688 @Test
689 void testOptionalLiteralSpecialCharacters() {
690 assertEquals(
691 DurationFormatUtils.formatDuration(10000L, "s's'"),
692 DurationFormatUtils.formatDuration(10000L, "['['m']']s's'"));
693 }
694
695 @Test
696 void testOptionalToken() {
697
698
699 assertEquals(
700 DurationFormatUtils.formatDuration(915361000L, "d'd'H'h'm'm's's'"),
701 DurationFormatUtils.formatDuration(915361000L, "[d'd'H'h'm'm']s's'"));
702
703 assertEquals(
704 DurationFormatUtils.formatDuration(9153610L, "H'h'm'm's's'"),
705 DurationFormatUtils.formatDuration(9153610L, "[d'd'H'h'm'm']s's'"));
706
707 assertEquals(
708 DurationFormatUtils.formatDuration(915361L, "m'm's's'"),
709 DurationFormatUtils.formatDuration(915361L, "[d'd'H'h'm'm']s's'"));
710
711 assertEquals(
712 DurationFormatUtils.formatDuration(9153L, "s's'"),
713 DurationFormatUtils.formatDuration(9153L, "[d'd'H'h'm'm']s's'"));
714
715 assertEquals(
716 DurationFormatUtils.formatDuration(9153L, "s's'"),
717 DurationFormatUtils.formatDuration(9153L, "[d'd'H'h'm'm']s's'"));
718
719 assertEquals(
720 DurationFormatUtils.formatPeriod(9153610L, 915361000L, "d'd'H'h'm'm's's'"),
721 DurationFormatUtils.formatPeriod(9153610L, 915361000L, "[d'd'H'h'm'm']s's'"));
722
723 assertEquals(
724 DurationFormatUtils.formatPeriod(915361L, 9153610L, "H'h'm'm's's'"),
725 DurationFormatUtils.formatPeriod(915361L, 9153610L, "[d'd'H'h'm'm']s's'"));
726
727 assertEquals(
728 DurationFormatUtils.formatPeriod(9153L, 915361L, "m'm's's'"),
729 DurationFormatUtils.formatPeriod(9153L, 915361L, "[d'd'H'h'm'm']s's'"));
730
731 assertEquals(
732 DurationFormatUtils.formatPeriod(0L, 9153L, "s's'"),
733 DurationFormatUtils.formatPeriod(0L, 9153L, "[d'd'H'h'm'm']s's'"));
734
735
736
737 assertEquals("2h32m33s610ms", DurationFormatUtils.formatDuration(9153610L, "[d'd'H'h'm'm's's']S'ms'"));
738
739 assertEquals("15m15s361ms", DurationFormatUtils.formatDuration(915361L, "[d'd'H'h'm'm's's']S'ms'"));
740
741 assertEquals("9s153ms", DurationFormatUtils.formatDuration(9153L, "[d'd'H'h'm'm's's']S'ms'"));
742
743 assertEquals("915ms", DurationFormatUtils.formatDuration(915L, "[d'd'H'h'm'm's's']S'ms'"));
744
745
746
747 assertEquals(
748 DurationFormatUtils.formatPeriod(915361L, 9153610L, "H'h''h2'm'm's's'"),
749 DurationFormatUtils.formatPeriod(915361L, 9153610L, "[d'd''d2'H'h''h2'm'm']s's'"));
750 }
751
752 @Test
753 void testUnmatchedOptionalTokens() {
754 assertIllegalArgumentException(() -> DurationFormatUtils.formatDuration(1, "[s"));
755 assertIllegalArgumentException(() -> DurationFormatUtils.formatDuration(1, "[[s"));
756 assertIllegalArgumentException(() -> DurationFormatUtils.formatDuration(1, "[s]]"));
757 }
758 }