1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.lang3.time; 19 20 import static org.junit.jupiter.api.Assertions.assertArrayEquals; 21 import static org.junit.jupiter.api.Assertions.assertEquals; 22 import static org.junit.jupiter.api.Assertions.assertFalse; 23 import static org.junit.jupiter.api.Assertions.assertNotEquals; 24 import static org.junit.jupiter.api.Assertions.assertNotNull; 25 import static org.junit.jupiter.api.Assertions.assertThrows; 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.util.Calendar; 31 import java.util.TimeZone; 32 33 import org.apache.commons.lang3.AbstractLangTest; 34 import org.junit.jupiter.api.Test; 35 import org.junitpioneer.jupiter.DefaultTimeZone; 36 37 /** 38 * TestCase for DurationFormatUtils. 39 * <p> 40 * NOT THREAD-SAFE. 41 * </p> 42 */ 43 public class DurationFormatUtilsTest extends AbstractLangTest { 44 45 private static final int FOUR_YEARS = 365 * 3 + 366; 46 assertEqualDuration(final String expected, final int[] start, final int[] end, final String format)47 private void assertEqualDuration(final String expected, final int[] start, final int[] end, final String format) { 48 assertEqualDuration(null, expected, start, end, format); 49 } 50 assertEqualDuration(final String message, final String expected, final int[] start, final int[] end, final String format)51 private void assertEqualDuration(final String message, final String expected, final int[] start, final int[] end, final String format) { 52 final Calendar cal1 = Calendar.getInstance(); 53 cal1.set(start[0], start[1], start[2], start[3], start[4], start[5]); 54 cal1.set(Calendar.MILLISECOND, 0); 55 final Calendar cal2 = Calendar.getInstance(); 56 cal2.set(end[0], end[1], end[2], end[3], end[4], end[5]); 57 cal2.set(Calendar.MILLISECOND, 0); 58 final long milli1 = cal1.getTime().getTime(); 59 final long milli2 = cal2.getTime().getTime(); 60 final String result = DurationFormatUtils.formatPeriod(milli1, milli2, format); 61 if (message == null) { 62 assertEquals(expected, result); 63 } else { 64 assertEquals(expected, result, message); 65 } 66 } 67 bruteForce(final int year, final int month, final int day, final String format, final int calendarType)68 private void bruteForce(final int year, final int month, final int day, final String format, final int calendarType) { 69 final String msg = year + "-" + month + "-" + day + " to "; 70 final Calendar c = Calendar.getInstance(); 71 c.set(year, month, day, 0, 0, 0); 72 final int[] array1 = { year, month, day, 0, 0, 0 }; 73 final int[] array2 = { year, month, day, 0, 0, 0 }; 74 for (int i=0; i < FOUR_YEARS; i++) { 75 array2[0] = c.get(Calendar.YEAR); 76 array2[1] = c.get(Calendar.MONTH); 77 array2[2] = c.get(Calendar.DAY_OF_MONTH); 78 final String tmpMsg = msg + array2[0] + "-" + array2[1] + "-" + array2[2] + " at "; 79 assertEqualDuration(tmpMsg + i, Integer.toString(i), array1, array2, format ); 80 c.add(calendarType, 1); 81 } 82 } 83 84 /** https://issues.apache.org/bugzilla/show_bug.cgi?id=38401 */ 85 @Test testBugzilla38401()86 public void testBugzilla38401() { 87 assertEqualDuration("0000/00/30 16:00:00 000", new int[] { 2006, 0, 26, 18, 47, 34 }, 88 new int[] { 2006, 1, 26, 10, 47, 34 }, "yyyy/MM/dd HH:mm:ss SSS"); 89 } 90 91 @Test testConstructor()92 public void testConstructor() { 93 assertNotNull(new DurationFormatUtils()); 94 final Constructor<?>[] cons = DurationFormatUtils.class.getDeclaredConstructors(); 95 assertEquals(1, cons.length); 96 assertTrue(Modifier.isPublic(cons[0].getModifiers())); 97 assertTrue(Modifier.isPublic(DurationFormatUtils.class.getModifiers())); 98 assertFalse(Modifier.isFinal(DurationFormatUtils.class.getModifiers())); 99 } 100 101 @Test testDurationsByBruteForce()102 public void testDurationsByBruteForce() { 103 bruteForce(2006, 0, 1, "d", Calendar.DAY_OF_MONTH); 104 bruteForce(2006, 0, 2, "d", Calendar.DAY_OF_MONTH); 105 bruteForce(2007, 1, 2, "d", Calendar.DAY_OF_MONTH); 106 bruteForce(2004, 1, 29, "d", Calendar.DAY_OF_MONTH); 107 bruteForce(1996, 1, 29, "d", Calendar.DAY_OF_MONTH); 108 109 bruteForce(1969, 1, 28, "M", Calendar.MONTH); // tests for 48 years 110 //bruteForce(1996, 1, 29, "M", Calendar.MONTH); // this will fail 111 } 112 113 /** Attempting to test edge cases in DurationFormatUtils.formatPeriod. */ 114 @Test 115 @DefaultTimeZone(TimeZones.GMT_ID) testEdgeDurations()116 public void testEdgeDurations() { 117 // This test case must use a time zone without DST 118 TimeZone.setDefault(FastTimeZone.getGmtTimeZone()); 119 assertEqualDuration("01", new int[] { 2006, 0, 15, 0, 0, 0 }, 120 new int[] { 2006, 2, 10, 0, 0, 0 }, "MM"); 121 assertEqualDuration("12", new int[] { 2005, 0, 15, 0, 0, 0 }, 122 new int[] { 2006, 0, 15, 0, 0, 0 }, "MM"); 123 assertEqualDuration("12", new int[] { 2005, 0, 15, 0, 0, 0 }, 124 new int[] { 2006, 0, 16, 0, 0, 0 }, "MM"); 125 assertEqualDuration("11", new int[] { 2005, 0, 15, 0, 0, 0 }, 126 new int[] { 2006, 0, 14, 0, 0, 0 }, "MM"); 127 128 assertEqualDuration("01 26", new int[] { 2006, 0, 15, 0, 0, 0 }, 129 new int[] { 2006, 2, 10, 0, 0, 0 }, "MM dd"); 130 assertEqualDuration("54", new int[] { 2006, 0, 15, 0, 0, 0 }, 131 new int[] { 2006, 2, 10, 0, 0, 0 }, "dd"); 132 133 assertEqualDuration("09 12", new int[] { 2006, 1, 20, 0, 0, 0 }, 134 new int[] { 2006, 11, 4, 0, 0, 0 }, "MM dd"); 135 assertEqualDuration("287", new int[] { 2006, 1, 20, 0, 0, 0 }, 136 new int[] { 2006, 11, 4, 0, 0, 0 }, "dd"); 137 138 assertEqualDuration("11 30", new int[] { 2006, 0, 2, 0, 0, 0 }, 139 new int[] { 2007, 0, 1, 0, 0, 0 }, "MM dd"); 140 assertEqualDuration("364", new int[] { 2006, 0, 2, 0, 0, 0 }, 141 new int[] { 2007, 0, 1, 0, 0, 0 }, "dd"); 142 143 assertEqualDuration("12 00", new int[] { 2006, 0, 1, 0, 0, 0 }, 144 new int[] { 2007, 0, 1, 0, 0, 0 }, "MM dd"); 145 assertEqualDuration("365", new int[] { 2006, 0, 1, 0, 0, 0 }, 146 new int[] { 2007, 0, 1, 0, 0, 0 }, "dd"); 147 148 assertEqualDuration("31", new int[] { 2006, 0, 1, 0, 0, 0 }, 149 new int[] { 2006, 1, 1, 0, 0, 0 }, "dd"); 150 151 assertEqualDuration("92", new int[] { 2005, 9, 1, 0, 0, 0 }, 152 new int[] { 2006, 0, 1, 0, 0, 0 }, "dd"); 153 assertEqualDuration("77", new int[] { 2005, 9, 16, 0, 0, 0 }, 154 new int[] { 2006, 0, 1, 0, 0, 0 }, "dd"); 155 156 // test month larger in start than end 157 assertEqualDuration("136", new int[] { 2005, 9, 16, 0, 0, 0 }, 158 new int[] { 2006, 2, 1, 0, 0, 0 }, "dd"); 159 // test when start in leap year 160 assertEqualDuration("136", new int[] { 2004, 9, 16, 0, 0, 0 }, 161 new int[] { 2005, 2, 1, 0, 0, 0 }, "dd"); 162 // test when end in leap year 163 assertEqualDuration("137", new int[] { 2003, 9, 16, 0, 0, 0 }, 164 new int[] { 2004, 2, 1, 0, 0, 0 }, "dd"); 165 // test when end in leap year but less than end of feb 166 assertEqualDuration("135", new int[] { 2003, 9, 16, 0, 0, 0 }, 167 new int[] { 2004, 1, 28, 0, 0, 0 }, "dd"); 168 169 assertEqualDuration("364", new int[] { 2007, 0, 2, 0, 0, 0 }, 170 new int[] { 2008, 0, 1, 0, 0, 0 }, "dd"); 171 assertEqualDuration("729", new int[] { 2006, 0, 2, 0, 0, 0 }, 172 new int[] { 2008, 0, 1, 0, 0, 0 }, "dd"); 173 174 assertEqualDuration("365", new int[] { 2007, 2, 2, 0, 0, 0 }, 175 new int[] { 2008, 2, 1, 0, 0, 0 }, "dd"); 176 assertEqualDuration("333", new int[] { 2007, 1, 2, 0, 0, 0 }, 177 new int[] { 2008, 0, 1, 0, 0, 0 }, "dd"); 178 179 assertEqualDuration("28", new int[] { 2008, 1, 2, 0, 0, 0 }, 180 new int[] { 2008, 2, 1, 0, 0, 0 }, "dd"); 181 assertEqualDuration("393", new int[] { 2007, 1, 2, 0, 0, 0 }, 182 new int[] { 2008, 2, 1, 0, 0, 0 }, "dd"); 183 184 assertEqualDuration("369", new int[] { 2004, 0, 29, 0, 0, 0 }, 185 new int[] { 2005, 1, 1, 0, 0, 0 }, "dd"); 186 187 assertEqualDuration("338", new int[] { 2004, 1, 29, 0, 0, 0 }, 188 new int[] { 2005, 1, 1, 0, 0, 0 }, "dd"); 189 190 assertEqualDuration("28", new int[] { 2004, 2, 8, 0, 0, 0 }, 191 new int[] { 2004, 3, 5, 0, 0, 0 }, "dd"); 192 193 assertEqualDuration("48", new int[] { 1992, 1, 29, 0, 0, 0 }, 194 new int[] { 1996, 1, 29, 0, 0, 0 }, "M"); 195 196 197 // this seems odd - and will fail if I throw it in as a brute force 198 // below as it expects the answer to be 12. It's a tricky edge case 199 assertEqualDuration("11", new int[] { 1996, 1, 29, 0, 0, 0 }, 200 new int[] { 1997, 1, 28, 0, 0, 0 }, "M"); 201 // again - this seems odd 202 assertEqualDuration("11 28", new int[] { 1996, 1, 29, 0, 0, 0 }, 203 new int[] { 1997, 1, 28, 0, 0, 0 }, "M d"); 204 205 } 206 207 @Test testFormatDuration()208 public void testFormatDuration() { 209 long duration = 0; 210 assertEquals("0", DurationFormatUtils.formatDuration(duration, "y")); 211 assertEquals("0", DurationFormatUtils.formatDuration(duration, "M")); 212 assertEquals("0", DurationFormatUtils.formatDuration(duration, "d")); 213 assertEquals("0", DurationFormatUtils.formatDuration(duration, "H")); 214 assertEquals("0", DurationFormatUtils.formatDuration(duration, "m")); 215 assertEquals("0", DurationFormatUtils.formatDuration(duration, "s")); 216 assertEquals("0", DurationFormatUtils.formatDuration(duration, "S")); 217 assertEquals("0000", DurationFormatUtils.formatDuration(duration, "SSSS")); 218 assertEquals("0000", DurationFormatUtils.formatDuration(duration, "yyyy")); 219 assertEquals("0000", DurationFormatUtils.formatDuration(duration, "yyMM")); 220 221 duration = 60 * 1000; 222 assertEquals("0", DurationFormatUtils.formatDuration(duration, "y")); 223 assertEquals("0", DurationFormatUtils.formatDuration(duration, "M")); 224 assertEquals("0", DurationFormatUtils.formatDuration(duration, "d")); 225 assertEquals("0", DurationFormatUtils.formatDuration(duration, "H")); 226 assertEquals("1", DurationFormatUtils.formatDuration(duration, "m")); 227 assertEquals("60", DurationFormatUtils.formatDuration(duration, "s")); 228 assertEquals("60000", DurationFormatUtils.formatDuration(duration, "S")); 229 assertEquals("01:00", DurationFormatUtils.formatDuration(duration, "mm:ss")); 230 231 final Calendar base = Calendar.getInstance(); 232 base.set(2000, Calendar.JANUARY, 1, 0, 0, 0); 233 base.set(Calendar.MILLISECOND, 0); 234 235 final Calendar cal = Calendar.getInstance(); 236 cal.set(2003, Calendar.FEBRUARY, 1, 0, 0, 0); 237 cal.set(Calendar.MILLISECOND, 0); 238 duration = cal.getTime().getTime() - base.getTime().getTime(); // duration from 2000-01-01 to cal 239 // don't use 1970 in test as time zones were less reliable in 1970 than now 240 // remember that duration formatting ignores time zones, working on strict hour lengths 241 final int days = 366 + 365 + 365 + 31; 242 assertEquals("0 0 " + days, DurationFormatUtils.formatDuration(duration, "y M d")); 243 } 244 245 @Test testFormatDurationHMS()246 public void testFormatDurationHMS() { 247 long time = 0; 248 assertEquals("00:00:00.000", DurationFormatUtils.formatDurationHMS(time)); 249 250 time = 1; 251 assertEquals("00:00:00.001", DurationFormatUtils.formatDurationHMS(time)); 252 253 time = 15; 254 assertEquals("00:00:00.015", DurationFormatUtils.formatDurationHMS(time)); 255 256 time = 165; 257 assertEquals("00:00:00.165", DurationFormatUtils.formatDurationHMS(time)); 258 259 time = 1675; 260 assertEquals("00:00:01.675", DurationFormatUtils.formatDurationHMS(time)); 261 262 time = 13465; 263 assertEquals("00:00:13.465", DurationFormatUtils.formatDurationHMS(time)); 264 265 time = 72789; 266 assertEquals("00:01:12.789", DurationFormatUtils.formatDurationHMS(time)); 267 268 time = 12789 + 32 * 60000; 269 assertEquals("00:32:12.789", DurationFormatUtils.formatDurationHMS(time)); 270 271 time = 12789 + 62 * 60000; 272 assertEquals("01:02:12.789", DurationFormatUtils.formatDurationHMS(time)); 273 } 274 275 @Test testFormatDurationISO()276 public void testFormatDurationISO() { 277 assertEquals("P0Y0M0DT0H0M0.000S", DurationFormatUtils.formatDurationISO(0L)); 278 assertEquals("P0Y0M0DT0H0M0.001S", DurationFormatUtils.formatDurationISO(1L)); 279 assertEquals("P0Y0M0DT0H0M0.010S", DurationFormatUtils.formatDurationISO(10L)); 280 assertEquals("P0Y0M0DT0H0M0.100S", DurationFormatUtils.formatDurationISO(100L)); 281 assertEquals("P0Y0M0DT0H1M15.321S", DurationFormatUtils.formatDurationISO(75321L)); 282 } 283 284 /** 285 * Tests that "1 <unit>s" gets converted to "1 <unit>" but that "11 <unit>s" is left alone. 286 */ 287 @Test testFormatDurationPluralWords()288 public void testFormatDurationPluralWords() { 289 final long oneSecond = 1000; 290 final long oneMinute = oneSecond * 60; 291 final long oneHour = oneMinute * 60; 292 final long oneDay = oneHour * 24; 293 String text; 294 295 text = DurationFormatUtils.formatDurationWords(oneSecond, false, false); 296 assertEquals("0 days 0 hours 0 minutes 1 second", text); 297 text = DurationFormatUtils.formatDurationWords(oneSecond * 2, false, false); 298 assertEquals("0 days 0 hours 0 minutes 2 seconds", text); 299 text = DurationFormatUtils.formatDurationWords(oneSecond * 11, false, false); 300 assertEquals("0 days 0 hours 0 minutes 11 seconds", text); 301 302 text = DurationFormatUtils.formatDurationWords(oneMinute, false, false); 303 assertEquals("0 days 0 hours 1 minute 0 seconds", text); 304 text = DurationFormatUtils.formatDurationWords(oneMinute * 2, false, false); 305 assertEquals("0 days 0 hours 2 minutes 0 seconds", text); 306 text = DurationFormatUtils.formatDurationWords(oneMinute * 11, false, false); 307 assertEquals("0 days 0 hours 11 minutes 0 seconds", text); 308 text = DurationFormatUtils.formatDurationWords(oneMinute + oneSecond, false, false); 309 assertEquals("0 days 0 hours 1 minute 1 second", text); 310 311 text = DurationFormatUtils.formatDurationWords(oneHour, false, false); 312 assertEquals("0 days 1 hour 0 minutes 0 seconds", text); 313 text = DurationFormatUtils.formatDurationWords(oneHour * 2, false, false); 314 assertEquals("0 days 2 hours 0 minutes 0 seconds", text); 315 text = DurationFormatUtils.formatDurationWords(oneHour * 11, false, false); 316 assertEquals("0 days 11 hours 0 minutes 0 seconds", text); 317 text = DurationFormatUtils.formatDurationWords(oneHour + oneMinute + oneSecond, false, false); 318 assertEquals("0 days 1 hour 1 minute 1 second", text); 319 320 text = DurationFormatUtils.formatDurationWords(oneDay, false, false); 321 assertEquals("1 day 0 hours 0 minutes 0 seconds", text); 322 text = DurationFormatUtils.formatDurationWords(oneDay * 2, false, false); 323 assertEquals("2 days 0 hours 0 minutes 0 seconds", text); 324 text = DurationFormatUtils.formatDurationWords(oneDay * 11, false, false); 325 assertEquals("11 days 0 hours 0 minutes 0 seconds", text); 326 text = DurationFormatUtils.formatDurationWords(oneDay + oneHour + oneMinute + oneSecond, false, false); 327 assertEquals("1 day 1 hour 1 minute 1 second", text); 328 } 329 330 @Test testFormatDurationWords()331 public void testFormatDurationWords() { 332 String text; 333 334 text = DurationFormatUtils.formatDurationWords(50 * 1000, true, false); 335 assertEquals("50 seconds", text); 336 text = DurationFormatUtils.formatDurationWords(65 * 1000, true, false); 337 assertEquals("1 minute 5 seconds", text); 338 text = DurationFormatUtils.formatDurationWords(120 * 1000, true, false); 339 assertEquals("2 minutes 0 seconds", text); 340 text = DurationFormatUtils.formatDurationWords(121 * 1000, true, false); 341 assertEquals("2 minutes 1 second", text); 342 text = DurationFormatUtils.formatDurationWords(72 * 60 * 1000, true, false); 343 assertEquals("1 hour 12 minutes 0 seconds", text); 344 text = DurationFormatUtils.formatDurationWords(24 * 60 * 60 * 1000, true, false); 345 assertEquals("1 day 0 hours 0 minutes 0 seconds", text); 346 347 text = DurationFormatUtils.formatDurationWords(50 * 1000, true, true); 348 assertEquals("50 seconds", text); 349 text = DurationFormatUtils.formatDurationWords(65 * 1000, true, true); 350 assertEquals("1 minute 5 seconds", text); 351 text = DurationFormatUtils.formatDurationWords(120 * 1000, true, true); 352 assertEquals("2 minutes", text); 353 text = DurationFormatUtils.formatDurationWords(121 * 1000, true, true); 354 assertEquals("2 minutes 1 second", text); 355 text = DurationFormatUtils.formatDurationWords(72 * 60 * 1000, true, true); 356 assertEquals("1 hour 12 minutes", text); 357 text = DurationFormatUtils.formatDurationWords(24 * 60 * 60 * 1000, true, true); 358 assertEquals("1 day", text); 359 360 text = DurationFormatUtils.formatDurationWords(50 * 1000, false, true); 361 assertEquals("0 days 0 hours 0 minutes 50 seconds", text); 362 text = DurationFormatUtils.formatDurationWords(65 * 1000, false, true); 363 assertEquals("0 days 0 hours 1 minute 5 seconds", text); 364 text = DurationFormatUtils.formatDurationWords(120 * 1000, false, true); 365 assertEquals("0 days 0 hours 2 minutes", text); 366 text = DurationFormatUtils.formatDurationWords(121 * 1000, false, true); 367 assertEquals("0 days 0 hours 2 minutes 1 second", text); 368 text = DurationFormatUtils.formatDurationWords(72 * 60 * 1000, false, true); 369 assertEquals("0 days 1 hour 12 minutes", text); 370 text = DurationFormatUtils.formatDurationWords(24 * 60 * 60 * 1000, false, true); 371 assertEquals("1 day", text); 372 373 text = DurationFormatUtils.formatDurationWords(50 * 1000, false, false); 374 assertEquals("0 days 0 hours 0 minutes 50 seconds", text); 375 text = DurationFormatUtils.formatDurationWords(65 * 1000, false, false); 376 assertEquals("0 days 0 hours 1 minute 5 seconds", text); 377 text = DurationFormatUtils.formatDurationWords(120 * 1000, false, false); 378 assertEquals("0 days 0 hours 2 minutes 0 seconds", text); 379 text = DurationFormatUtils.formatDurationWords(121 * 1000, false, false); 380 assertEquals("0 days 0 hours 2 minutes 1 second", text); 381 text = DurationFormatUtils.formatDurationWords(72 * 60 * 1000, false, false); 382 assertEquals("0 days 1 hour 12 minutes 0 seconds", text); 383 text = DurationFormatUtils.formatDurationWords(24 * 60 * 60 * 1000 + 72 * 60 * 1000, false, false); 384 assertEquals("1 day 1 hour 12 minutes 0 seconds", text); 385 text = DurationFormatUtils.formatDurationWords(2 * 24 * 60 * 60 * 1000 + 72 * 60 * 1000, false, false); 386 assertEquals("2 days 1 hour 12 minutes 0 seconds", text); 387 for (int i = 2; i < 31; i++) { 388 text = DurationFormatUtils.formatDurationWords(i * 24 * 60 * 60 * 1000L, false, false); 389 assertEquals(i + " days 0 hours 0 minutes 0 seconds", text); 390 } 391 } 392 393 @Test testFormatNegativeDuration()394 public void testFormatNegativeDuration() { 395 assertThrows(IllegalArgumentException.class, () -> DurationFormatUtils.formatDuration(-5000, "S", true)); 396 } 397 398 @Test testFormatNegativeDurationHMS()399 public void testFormatNegativeDurationHMS() { 400 assertThrows(IllegalArgumentException.class, () -> DurationFormatUtils.formatDurationHMS(-5000)); 401 } 402 403 @Test testFormatNegativeDurationISO()404 public void testFormatNegativeDurationISO() { 405 assertThrows(IllegalArgumentException.class, () -> DurationFormatUtils.formatDurationISO(-5000)); 406 } 407 408 409 @Test testFormatNegativeDurationWords()410 public void testFormatNegativeDurationWords() { 411 assertThrows(IllegalArgumentException.class, () -> DurationFormatUtils.formatDurationWords(-5000, true, true)); 412 } 413 414 @Test testFormatPeriod()415 public void testFormatPeriod() { 416 final Calendar cal1970 = Calendar.getInstance(); 417 cal1970.set(1970, Calendar.JANUARY, 1, 0, 0, 0); 418 cal1970.set(Calendar.MILLISECOND, 0); 419 final long time1970 = cal1970.getTime().getTime(); 420 421 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "y")); 422 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "M")); 423 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "d")); 424 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "H")); 425 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "m")); 426 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "s")); 427 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time1970, "S")); 428 assertEquals("0000", DurationFormatUtils.formatPeriod(time1970, time1970, "SSSS")); 429 assertEquals("0000", DurationFormatUtils.formatPeriod(time1970, time1970, "yyyy")); 430 assertEquals("0000", DurationFormatUtils.formatPeriod(time1970, time1970, "yyMM")); 431 432 long time = time1970 + 60 * 1000; 433 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time, "y")); 434 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time, "M")); 435 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time, "d")); 436 assertEquals("0", DurationFormatUtils.formatPeriod(time1970, time, "H")); 437 assertEquals("1", DurationFormatUtils.formatPeriod(time1970, time, "m")); 438 assertEquals("60", DurationFormatUtils.formatPeriod(time1970, time, "s")); 439 assertEquals("60000", DurationFormatUtils.formatPeriod(time1970, time, "S")); 440 assertEquals("01:00", DurationFormatUtils.formatPeriod(time1970, time, "mm:ss")); 441 442 final Calendar cal = Calendar.getInstance(); 443 cal.set(1973, Calendar.JULY, 1, 0, 0, 0); 444 cal.set(Calendar.MILLISECOND, 0); 445 time = cal.getTime().getTime(); 446 assertEquals("36", DurationFormatUtils.formatPeriod(time1970, time, "yM")); 447 assertEquals("3 years 6 months", DurationFormatUtils.formatPeriod(time1970, time, "y' years 'M' months'")); 448 assertEquals("03/06", DurationFormatUtils.formatPeriod(time1970, time, "yy/MM")); 449 450 cal.set(1973, Calendar.NOVEMBER, 1, 0, 0, 0); 451 cal.set(Calendar.MILLISECOND, 0); 452 time = cal.getTime().getTime(); 453 assertEquals("310", DurationFormatUtils.formatPeriod(time1970, time, "yM")); 454 assertEquals("3 years 10 months", DurationFormatUtils.formatPeriod(time1970, time, "y' years 'M' months'")); 455 assertEquals("03/10", DurationFormatUtils.formatPeriod(time1970, time, "yy/MM")); 456 457 cal.set(1974, Calendar.JANUARY, 1, 0, 0, 0); 458 cal.set(Calendar.MILLISECOND, 0); 459 time = cal.getTime().getTime(); 460 assertEquals("40", DurationFormatUtils.formatPeriod(time1970, time, "yM")); 461 assertEquals("4 years 0 months", DurationFormatUtils.formatPeriod(time1970, time, "y' years 'M' months'")); 462 assertEquals("04/00", DurationFormatUtils.formatPeriod(time1970, time, "yy/MM")); 463 assertEquals("48", DurationFormatUtils.formatPeriod(time1970, time, "M")); 464 assertEquals("48", DurationFormatUtils.formatPeriod(time1970, time, "MM")); 465 assertEquals("048", DurationFormatUtils.formatPeriod(time1970, time, "MMM")); 466 } 467 468 @Test testFormatPeriodeStartGreaterEnd()469 public void testFormatPeriodeStartGreaterEnd() { 470 assertThrows(IllegalArgumentException.class, () -> DurationFormatUtils.formatPeriod(5000, 2500, "yy/MM")); 471 } 472 473 @SuppressWarnings("deprecation") 474 @Test testFormatPeriodISO()475 public void testFormatPeriodISO() { 476 final TimeZone timeZone = TimeZone.getTimeZone("GMT-3"); 477 final Calendar base = Calendar.getInstance(timeZone); 478 base.set(1970, Calendar.JANUARY, 1, 0, 0, 0); 479 base.set(Calendar.MILLISECOND, 0); 480 481 final Calendar cal = Calendar.getInstance(timeZone); 482 cal.set(2002, Calendar.FEBRUARY, 23, 9, 11, 12); 483 cal.set(Calendar.MILLISECOND, 1); 484 String text; 485 // repeat a test from testDateTimeISO to compare extended and not extended. 486 text = DateFormatUtils.format(cal, DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern(), timeZone); 487 assertEquals("2002-02-23T09:11:12-03:00", text); 488 // test fixture is the same as above, but now with extended format. 489 text = DurationFormatUtils.formatPeriod(base.getTime().getTime(), cal.getTime().getTime(), 490 DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN, false, timeZone); 491 assertEquals("P32Y1M22DT9H11M12.001S", text); 492 // test fixture from example in https://www.w3.org/TR/xmlschema-2/#duration 493 cal.set(1971, Calendar.FEBRUARY, 3, 10, 30, 0); 494 cal.set(Calendar.MILLISECOND, 0); 495 text = DurationFormatUtils.formatPeriod(base.getTime().getTime(), cal.getTime().getTime(), 496 DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN, false, timeZone); 497 assertEquals("P1Y1M2DT10H30M0.000S", text); 498 // want a way to say 'don't print the seconds in format()' or other fields for that matter: 499 // assertEquals("P1Y2M3DT10H30M", text); 500 } 501 502 @Test testFormatPeriodISOMethod()503 public void testFormatPeriodISOMethod() { 504 assertEquals("P0Y0M0DT0H0M0.000S", DurationFormatUtils.formatPeriodISO(0L, 0L)); 505 assertEquals("P0Y0M0DT0H0M1.000S", DurationFormatUtils.formatPeriodISO(0L, 1000L)); 506 assertEquals("P0Y0M0DT0H1M1.000S", DurationFormatUtils.formatPeriodISO(0L, 61000L)); 507 } 508 509 @Test testFormatPeriodISOStartGreaterEnd()510 public void testFormatPeriodISOStartGreaterEnd() { 511 assertThrows(IllegalArgumentException.class, () -> DurationFormatUtils.formatPeriodISO(5000, 2000)); 512 } 513 514 // https://issues.apache.org/jira/browse/LANG-281 515 @Test testJiraLang281()516 public void testJiraLang281() { 517 assertEqualDuration("09", new int[] { 2005, 11, 31, 0, 0, 0 }, 518 new int[] { 2006, 9, 6, 0, 0, 0 }, "MM"); 519 } 520 521 @Test testLANG815()522 public void testLANG815() { 523 final Calendar calendar = Calendar.getInstance(); 524 calendar.set(2012, Calendar.JULY, 30, 0, 0, 0); 525 final long startMillis = calendar.getTimeInMillis(); 526 527 calendar.set(2012, Calendar.SEPTEMBER, 8); 528 final long endMillis = calendar.getTimeInMillis(); 529 530 assertEquals("1 9", DurationFormatUtils.formatPeriod(startMillis, endMillis, "M d")); 531 } 532 533 @Test testLANG981()534 public void testLANG981() { // unmatched quote char in lexx 535 assertThrows(IllegalArgumentException.class, () -> DurationFormatUtils.lexx("'yMdHms''S")); 536 } 537 538 @Test testLANG982()539 public void testLANG982() { // More than 3 millisecond digits following a second 540 assertEquals("61.999", DurationFormatUtils.formatDuration(61999, "s.S")); 541 assertEquals("1 1999", DurationFormatUtils.formatDuration(61999, "m S")); 542 assertEquals("61.999", DurationFormatUtils.formatDuration(61999, "s.SSS")); 543 assertEquals("1 1999", DurationFormatUtils.formatDuration(61999, "m SSS")); 544 assertEquals("61.0999", DurationFormatUtils.formatDuration(61999, "s.SSSS")); 545 assertEquals("1 1999", DurationFormatUtils.formatDuration(61999, "m SSSS")); 546 assertEquals("61.00999", DurationFormatUtils.formatDuration(61999, "s.SSSSS")); 547 assertEquals("1 01999", DurationFormatUtils.formatDuration(61999, "m SSSSS")); 548 } 549 550 // Takes a minute to run, so generally turned off 551 // public void testBrutally() { 552 // Calendar c = Calendar.getInstance(); 553 // c.set(2004, 0, 1, 0, 0, 0); 554 // for (int i=0; i < FOUR_YEARS; i++) { 555 // bruteForce(c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH), "d", Calendar.DAY_OF_MONTH ); 556 // c.add(Calendar.DAY_OF_MONTH, 1); 557 // } 558 // } 559 560 @Test testLANG984()561 public void testLANG984() { // Long durations 562 assertEquals("0", DurationFormatUtils.formatDuration(0, "S")); 563 assertEquals(Integer.toString(Integer.MAX_VALUE), DurationFormatUtils.formatDuration(Integer.MAX_VALUE, "S")); 564 long maxIntPlus=Integer.MAX_VALUE; 565 maxIntPlus++; 566 assertEquals(Long.toString(maxIntPlus), DurationFormatUtils.formatDuration(maxIntPlus, "S")); 567 assertEquals(Long.toString(Long.MAX_VALUE), DurationFormatUtils.formatDuration(Long.MAX_VALUE, "S")); 568 } 569 570 @Test testLexx()571 public void testLexx() { 572 // tests each constant 573 assertArrayEquals(new DurationFormatUtils.Token[]{ 574 new DurationFormatUtils.Token(DurationFormatUtils.y, 1), 575 new DurationFormatUtils.Token(DurationFormatUtils.M, 1), 576 new DurationFormatUtils.Token(DurationFormatUtils.d, 1), 577 new DurationFormatUtils.Token(DurationFormatUtils.H, 1), 578 new DurationFormatUtils.Token(DurationFormatUtils.m, 1), 579 new DurationFormatUtils.Token(DurationFormatUtils.s, 1), 580 new DurationFormatUtils.Token(DurationFormatUtils.S, 1)}, DurationFormatUtils.lexx("yMdHmsS")); 581 582 // tests the ISO 8601-like 583 assertArrayEquals(new DurationFormatUtils.Token[]{ 584 new DurationFormatUtils.Token(DurationFormatUtils.H, 2), 585 new DurationFormatUtils.Token(new StringBuilder(":"), 1), 586 new DurationFormatUtils.Token(DurationFormatUtils.m, 2), 587 new DurationFormatUtils.Token(new StringBuilder(":"), 1), 588 new DurationFormatUtils.Token(DurationFormatUtils.s, 2), 589 new DurationFormatUtils.Token(new StringBuilder("."), 1), 590 new DurationFormatUtils.Token(DurationFormatUtils.S, 3)}, DurationFormatUtils.lexx("HH:mm:ss.SSS")); 591 592 // test the iso extended format 593 assertArrayEquals(new DurationFormatUtils.Token[]{ 594 new DurationFormatUtils.Token(new StringBuilder("P"), 1), 595 new DurationFormatUtils.Token(DurationFormatUtils.y, 4), 596 new DurationFormatUtils.Token(new StringBuilder("Y"), 1), 597 new DurationFormatUtils.Token(DurationFormatUtils.M, 1), 598 new DurationFormatUtils.Token(new StringBuilder("M"), 1), 599 new DurationFormatUtils.Token(DurationFormatUtils.d, 1), 600 new DurationFormatUtils.Token(new StringBuilder("DT"), 1), 601 new DurationFormatUtils.Token(DurationFormatUtils.H, 1), 602 new DurationFormatUtils.Token(new StringBuilder("H"), 1), 603 new DurationFormatUtils.Token(DurationFormatUtils.m, 1), 604 new DurationFormatUtils.Token(new StringBuilder("M"), 1), 605 new DurationFormatUtils.Token(DurationFormatUtils.s, 1), 606 new DurationFormatUtils.Token(new StringBuilder("."), 1), 607 new DurationFormatUtils.Token(DurationFormatUtils.S, 3), 608 new DurationFormatUtils.Token(new StringBuilder("S"), 1)}, DurationFormatUtils 609 .lexx(DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN)); 610 611 // test failures in equals 612 final DurationFormatUtils.Token token = new DurationFormatUtils.Token(DurationFormatUtils.y, 4); 613 assertNotEquals(token, new Object(), "Token equal to non-Token class. "); 614 assertNotEquals(token, new DurationFormatUtils.Token(new Object()), "Token equal to Token with wrong value class. "); 615 assertNotEquals(token, new DurationFormatUtils.Token(DurationFormatUtils.y, 1), "Token equal to Token with different count. "); 616 final DurationFormatUtils.Token numToken = new DurationFormatUtils.Token(Integer.valueOf(1), 4); 617 assertEquals(numToken, numToken, "Token with Number value not equal to itself. "); 618 } 619 // Testing the under a day range in DurationFormatUtils.formatPeriod 620 @Test testLowDurations()621 public void testLowDurations() { 622 for (int hr=0; hr < 24; hr++) { 623 for (int min=0; min < 60; min++) { 624 for (int sec=0; sec < 60; sec++) { 625 assertEqualDuration(hr + ":" + min + ":" + sec, 626 new int[] { 2000, 0, 1, 0, 0, 0, 0 }, 627 new int[] { 2000, 0, 1, hr, min, sec }, 628 "H:m:s" 629 ); 630 } 631 } 632 } 633 } 634 635 } 636