1 /*
   2  * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package datatype;
  25 
  26 import java.math.BigDecimal;
  27 import java.math.BigInteger;
  28 import java.util.Calendar;
  29 import java.util.Date;
  30 import java.util.GregorianCalendar;
  31 import java.util.TimeZone;
  32 
  33 import javax.xml.datatype.DatatypeConfigurationException;
  34 import javax.xml.datatype.DatatypeConstants;
  35 import javax.xml.datatype.DatatypeFactory;
  36 import javax.xml.datatype.Duration;
  37 import javax.xml.namespace.QName;
  38 
  39 import org.testng.Assert;
  40 import org.testng.AssertJUnit;
  41 import org.testng.annotations.BeforeMethod;
  42 import org.testng.annotations.Listeners;
  43 import org.testng.annotations.Test;
  44 
  45 /*
  46  * @summary Test Duration.
  47  */
  48 @Listeners({jaxp.library.BasePolicy.class})
  49 public class DurationTest {
  50 
  51     private final static boolean DEBUG = true;
  52 
  53     protected Duration duration = null;
  54 
  55     @BeforeMethod
  56     protected void setUp() {
  57         try {
  58             duration = DatatypeFactory.newInstance().newDuration(100);
  59         } catch (DatatypeConfigurationException dce) {
  60             dce.printStackTrace();
  61             Assert.fail("Failed to create instance of DatatypeFactory " + dce.getMessage());
  62         }
  63     }
  64 
  65     @Test
  66     public void testDurationSubtract() {
  67         try {
  68             Duration bigDur = DatatypeFactory.newInstance().newDuration(20000);
  69             Duration smallDur = DatatypeFactory.newInstance().newDuration(10000);
  70             if (smallDur.subtract(bigDur).getSign() != -1) {
  71                 Assert.fail("smallDur.subtract(bigDur).getSign() is not -1");
  72             }
  73             if (bigDur.subtract(smallDur).getSign() != 1) {
  74                 Assert.fail("bigDur.subtract(smallDur).getSign() is not 1");
  75             }
  76             if (smallDur.subtract(smallDur).getSign() != 0) {
  77                 Assert.fail("smallDur.subtract(smallDur).getSign() is not 0");
  78             }
  79         } catch (DatatypeConfigurationException e) {
  80             e.printStackTrace();
  81         }
  82     }
  83 
  84     @Test
  85     public void testDurationMultiply() {
  86         int num = 5000; // millisends. 5 seconds
  87         int factor = 2;
  88         try {
  89             Duration dur = DatatypeFactory.newInstance().newDuration(num);
  90             if (dur.multiply(factor).getSeconds() != 10) {
  91                 Assert.fail("duration.multiply() return wrong value");
  92             }
  93             // factor is 2*10^(-1)
  94             if (dur.multiply(new BigDecimal(new BigInteger("2"), 1)).getSeconds() != 1) {
  95                 Assert.fail("duration.multiply() return wrong value");
  96             }
  97             if (dur.subtract(DatatypeFactory.newInstance().newDuration(1000)).multiply(new BigDecimal(new BigInteger("2"), 1)).getSeconds() != 0) {
  98                 Assert.fail("duration.multiply() return wrong value");
  99             }
 100         } catch (DatatypeConfigurationException e) {
 101             e.printStackTrace();
 102         }
 103     }
 104 
 105     @Test
 106     public void testDurationAndCalendar1() {
 107         int year = 1;
 108         int month = 2;
 109         int day = 3;
 110         int hour = 4;
 111         int min = 5;
 112         int sec = 6;
 113         String lexicalRepresentation = "P" + year + "Y" + month + "M" + day + "DT" + hour + "H" + min + "M" + sec + "S";
 114         try {
 115             Duration dur = DatatypeFactory.newInstance().newDuration(lexicalRepresentation);
 116             System.out.println(dur.toString());
 117             AssertJUnit.assertTrue("year should be 1", dur.getYears() == year);
 118             AssertJUnit.assertTrue("month should be 2", dur.getMonths() == month);
 119             AssertJUnit.assertTrue("day should be 3", dur.getDays() == day);
 120             AssertJUnit.assertTrue("hour should be 4", dur.getHours() == hour);
 121             AssertJUnit.assertTrue("minute should be 5", dur.getMinutes() == min);
 122             AssertJUnit.assertTrue("second should be 6", dur.getSeconds() == sec);
 123         } catch (DatatypeConfigurationException e) {
 124             e.printStackTrace();
 125         }
 126     }
 127 
 128     @Test
 129     public void testDurationAndCalendar2() {
 130         try {
 131             AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("PT10.00099S")
 132                     .getTimeInMillis(new Date()) == 10000);
 133             AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("-PT10.00099S")
 134                     .getTimeInMillis(new Date()) == -10000);
 135             AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("PT10.00099S")
 136                     .getTimeInMillis(new GregorianCalendar()) == 10000);
 137             AssertJUnit.assertTrue("10.00099S means 10 sec since it will be rounded to zero", DatatypeFactory.newInstance().newDuration("-PT10.00099S")
 138                     .getTimeInMillis(new GregorianCalendar()) == -10000);
 139         } catch (DatatypeConfigurationException e) {
 140             e.printStackTrace();
 141         }
 142     }
 143 
 144     @Test
 145     public void testDurationAndCalendar3() {
 146         try {
 147             Calendar cal = new GregorianCalendar();
 148             cal.set(Calendar.SECOND, 59);
 149             DatatypeFactory.newInstance().newDuration(10000).addTo(cal);
 150             AssertJUnit.assertTrue("sec will be 9", cal.get(Calendar.SECOND) == 9);
 151 
 152             Date date = new Date();
 153             date.setSeconds(59);
 154             DatatypeFactory.newInstance().newDuration(10000).addTo(date);
 155             AssertJUnit.assertTrue("sec will be 9", date.getSeconds() == 9);
 156         } catch (DatatypeConfigurationException e) {
 157             e.printStackTrace();
 158         }
 159     }
 160 
 161     @Test
 162     public void testEqualsWithDifferentObjectParam() {
 163 
 164         AssertJUnit.assertFalse("equals method should return false for any object other than Duration", duration.equals(new Integer(0)));
 165     }
 166 
 167     @Test
 168     public void testEqualsWithNullObjectParam() {
 169 
 170         AssertJUnit.assertFalse("equals method should return false for null parameter", duration.equals(null));
 171     }
 172 
 173     @Test
 174     public void testEqualsWithEqualObjectParam() {
 175         try {
 176             AssertJUnit.assertTrue("equals method is expected to return true", duration.equals(DatatypeFactory.newInstance().newDuration(100)));
 177         } catch (DatatypeConfigurationException dce) {
 178             dce.printStackTrace();
 179             Assert.fail("Failed to create instance of DatatypeFactory " + dce.getMessage());
 180         }
 181     }
 182 
 183     /**
 184      * Inspired by CR 5077522 Duration.compare makes mistakes for some values.
 185      */
 186     @Test
 187     public void testCompareWithInderterminateRelation() {
 188 
 189         final String[][] partialOrder = { // partialOrder
 190         { "P1Y", "<>", "P365D" }, { "P1Y", "<>", "P366D" }, { "P1M", "<>", "P28D" }, { "P1M", "<>", "P29D" }, { "P1M", "<>", "P30D" }, { "P1M", "<>", "P31D" },
 191                 { "P5M", "<>", "P150D" }, { "P5M", "<>", "P151D" }, { "P5M", "<>", "P152D" }, { "P5M", "<>", "P153D" }, { "PT2419200S", "<>", "P1M" },
 192                 { "PT2678400S", "<>", "P1M" }, { "PT31536000S", "<>", "P1Y" }, { "PT31622400S", "<>", "P1Y" }, { "PT525600M", "<>", "P1Y" },
 193                 { "PT527040M", "<>", "P1Y" }, { "PT8760H", "<>", "P1Y" }, { "PT8784H", "<>", "P1Y" }, { "P365D", "<>", "P1Y" }, };
 194 
 195         DatatypeFactory df = null;
 196         try {
 197             df = DatatypeFactory.newInstance();
 198         } catch (DatatypeConfigurationException ex) {
 199             ex.printStackTrace();
 200             Assert.fail(ex.toString());
 201         }
 202 
 203         boolean compareErrors = false;
 204 
 205         for (int valueIndex = 0; valueIndex < partialOrder.length; ++valueIndex) {
 206             Duration duration1 = df.newDuration(partialOrder[valueIndex][0]);
 207             Duration duration2 = df.newDuration(partialOrder[valueIndex][2]);
 208             int cmp = duration1.compare(duration2);
 209             int expected = ">".equals(partialOrder[valueIndex][1]) ? DatatypeConstants.GREATER
 210                     : "<".equals(partialOrder[valueIndex][1]) ? DatatypeConstants.LESSER : "==".equals(partialOrder[valueIndex][1]) ? DatatypeConstants.EQUAL
 211                             : DatatypeConstants.INDETERMINATE;
 212 
 213             // just note any errors, do not fail until all cases have been
 214             // tested
 215             if (expected != cmp) {
 216                 compareErrors = true;
 217                 System.err.println("returned " + cmp2str(cmp) + " for durations \'" + duration1 + "\' and " + duration2 + "\', but expected "
 218                         + cmp2str(expected));
 219             }
 220         }
 221 
 222         if (compareErrors) {
 223             // TODO; fix bug, these tests should pass
 224             if (false) {
 225                 Assert.fail("Errors in comparing indeterminate relations, see Stderr");
 226             } else {
 227                 System.err.println("Please fix this bug: " + "Errors in comparing indeterminate relations, see Stderr");
 228             }
 229         }
 230     }
 231 
 232     public static String cmp2str(int cmp) {
 233         return cmp == DatatypeConstants.LESSER ? "LESSER" : cmp == DatatypeConstants.GREATER ? "GREATER" : cmp == DatatypeConstants.EQUAL ? "EQUAL"
 234                 : cmp == DatatypeConstants.INDETERMINATE ? "INDETERMINATE" : "UNDEFINED";
 235     }
 236 
 237     /**
 238      * Inspired by CR 6238220 javax.xml.datatype.Duration has no clear
 239      * description concerning return values range.
 240      */
 241     @Test
 242     public void testNormalizedReturnValues() throws Exception {
 243 
 244         final Object[] TEST_VALUES = {
 245                 // test 61 seconds -> 1 minute, 1 second
 246                 true, // isPositive,
 247                 BigInteger.ZERO, // years,
 248                 BigInteger.ZERO, // months
 249                 BigInteger.ZERO, // days
 250                 BigInteger.ZERO, // hours
 251                 BigInteger.ZERO, // minutes
 252                 new BigDecimal(61), // seconds
 253                 61000L, // durationInMilliSeconds,
 254                 "P0Y0M0DT0H0M61S", // lexicalRepresentation
 255 
 256                 // test - 61 seconds -> - 1 minute, 1 second
 257                 false, // isPositive,
 258                 BigInteger.ZERO, // years,
 259                 BigInteger.ZERO, // months
 260                 BigInteger.ZERO, // days
 261                 BigInteger.ZERO, // hours
 262                 BigInteger.ZERO, // minutes
 263                 new BigDecimal(61), // seconds
 264                 61000L, // durationInMilliSeconds,
 265                 "-P0Y0M0DT0H0M61S", // lexicalRepresentation
 266         };
 267 
 268         final Object[] NORM_VALUES = {
 269                 // test 61 seconds -> 1 minute, 1 second
 270                 true, // normalized isPositive,
 271                 BigInteger.ZERO, // normalized years,
 272                 BigInteger.ZERO, // normalized months
 273                 BigInteger.ZERO, // normalized days
 274                 BigInteger.ZERO, // normalized hours
 275                 BigInteger.ONE, // normalized minutes
 276                 BigDecimal.ONE, // normalized seconds
 277                 61000L, // normalized durationInMilliSeconds,
 278                 "P0Y0M0DT0H1M1.000S", // normalized lexicalRepresentation
 279 
 280                 // test - 61 seconds -> - 1 minute, 1 second
 281                 false, // normalized isPositive,
 282                 BigInteger.ZERO, // normalized years,
 283                 BigInteger.ZERO, // normalized months
 284                 BigInteger.ZERO, // normalized days
 285                 BigInteger.ZERO, // normalized hours
 286                 BigInteger.ONE, // normalized minutes
 287                 BigDecimal.ONE, // normalized seconds
 288                 61000L, // normalized durationInMilliSeconds,
 289                 "-P0Y0M0DT0H1M1.000S" // normalized lexicalRepresentation
 290         };
 291 
 292         for (int onValue = 0; onValue < TEST_VALUES.length; onValue += 9) {
 293             newDurationTester(((Boolean) TEST_VALUES[onValue]).booleanValue(), // isPositive,
 294                     ((Boolean) NORM_VALUES[onValue]).booleanValue(), // normalized
 295                                                                      // isPositive,
 296                     (BigInteger) TEST_VALUES[onValue + 1], // years,
 297                     (BigInteger) NORM_VALUES[onValue + 1], // normalized years,
 298                     (BigInteger) TEST_VALUES[onValue + 2], // months
 299                     (BigInteger) NORM_VALUES[onValue + 2], // normalized months
 300                     (BigInteger) TEST_VALUES[onValue + 3], // days
 301                     (BigInteger) NORM_VALUES[onValue + 3], // normalized days
 302                     (BigInteger) TEST_VALUES[onValue + 4], // hours
 303                     (BigInteger) NORM_VALUES[onValue + 4], // normalized hours
 304                     (BigInteger) TEST_VALUES[onValue + 5], // minutes
 305                     (BigInteger) NORM_VALUES[onValue + 5], // normalized minutes
 306                     (BigDecimal) TEST_VALUES[onValue + 6], // seconds
 307                     (BigDecimal) NORM_VALUES[onValue + 6], // normalized seconds
 308                     ((Long) TEST_VALUES[onValue + 7]).longValue(), // durationInMilliSeconds,
 309                     ((Long) NORM_VALUES[onValue + 7]).longValue(), // normalized
 310                                                                    // durationInMilliSeconds,
 311                     (String) TEST_VALUES[onValue + 8], // lexicalRepresentation
 312                     (String) NORM_VALUES[onValue + 8]); // normalized
 313                                                         // lexicalRepresentation
 314 
 315             newDurationDayTimeTester(((Boolean) TEST_VALUES[onValue]).booleanValue(), // isPositive,
 316                     ((Boolean) NORM_VALUES[onValue]).booleanValue(), // normalized
 317                                                                      // isPositive,
 318                     BigInteger.ZERO, // years,
 319                     BigInteger.ZERO, // normalized years,
 320                     BigInteger.ZERO, // months
 321                     BigInteger.ZERO, // normalized months
 322                     (BigInteger) TEST_VALUES[onValue + 3], // days
 323                     (BigInteger) NORM_VALUES[onValue + 3], // normalized days
 324                     (BigInteger) TEST_VALUES[onValue + 4], // hours
 325                     (BigInteger) NORM_VALUES[onValue + 4], // normalized hours
 326                     (BigInteger) TEST_VALUES[onValue + 5], // minutes
 327                     (BigInteger) NORM_VALUES[onValue + 5], // normalized minutes
 328                     (BigDecimal) TEST_VALUES[onValue + 6], // seconds
 329                     (BigDecimal) NORM_VALUES[onValue + 6], // normalized seconds
 330                     ((Long) TEST_VALUES[onValue + 7]).longValue(), // durationInMilliSeconds,
 331                     ((Long) NORM_VALUES[onValue + 7]).longValue(), // normalized
 332                                                                    // durationInMilliSeconds,
 333                     (String) TEST_VALUES[onValue + 8], // lexicalRepresentation
 334                     (String) NORM_VALUES[onValue + 8]); // normalized
 335                                                         // lexicalRepresentation
 336         }
 337     }
 338 
 339     private void newDurationTester(boolean isPositive, boolean normalizedIsPositive, BigInteger years, BigInteger normalizedYears, BigInteger months,
 340             BigInteger normalizedMonths, BigInteger days, BigInteger normalizedDays, BigInteger hours, BigInteger normalizedHours, BigInteger minutes,
 341             BigInteger normalizedMinutes, BigDecimal seconds, BigDecimal normalizedSeconds, long durationInMilliSeconds, long normalizedDurationInMilliSeconds,
 342             String lexicalRepresentation, String normalizedLexicalRepresentation) {
 343 
 344         DatatypeFactory datatypeFactory = null;
 345         try {
 346             datatypeFactory = DatatypeFactory.newInstance();
 347         } catch (DatatypeConfigurationException ex) {
 348             ex.printStackTrace();
 349             Assert.fail(ex.toString());
 350         }
 351 
 352         // create 4 Durations using the 4 different constructors
 353 
 354         Duration durationBigInteger = datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds);
 355         durationAssertEquals(durationBigInteger, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(),
 356                 normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(),
 357                 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation);
 358 
 359         Duration durationInt = datatypeFactory.newDuration(isPositive, years.intValue(), months.intValue(), days.intValue(), hours.intValue(),
 360                 minutes.intValue(), seconds.intValue());
 361         durationAssertEquals(durationInt, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(),
 362                 normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(),
 363                 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation);
 364 
 365         Duration durationMilliseconds = datatypeFactory.newDuration(durationInMilliSeconds);
 366         durationAssertEquals(durationMilliseconds, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(),
 367                 normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(),
 368                 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation);
 369 
 370         Duration durationLexical = datatypeFactory.newDuration(lexicalRepresentation);
 371         durationAssertEquals(durationLexical, DatatypeConstants.DURATION, normalizedIsPositive, normalizedYears.intValue(), normalizedMonths.intValue(),
 372                 normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(),
 373                 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation);
 374     }
 375 
 376     private void newDurationDayTimeTester(boolean isPositive, boolean normalizedIsPositive, BigInteger years, BigInteger normalizedYears, BigInteger months,
 377             BigInteger normalizedMonths, BigInteger days, BigInteger normalizedDays, BigInteger hours, BigInteger normalizedHours, BigInteger minutes,
 378             BigInteger normalizedMinutes, BigDecimal seconds, BigDecimal normalizedSeconds, long durationInMilliSeconds, long normalizedDurationInMilliSeconds,
 379             String lexicalRepresentation, String normalizedLexicalRepresentation) {
 380 
 381         DatatypeFactory datatypeFactory = null;
 382         try {
 383             datatypeFactory = DatatypeFactory.newInstance();
 384         } catch (DatatypeConfigurationException ex) {
 385             ex.printStackTrace();
 386             Assert.fail(ex.toString());
 387         }
 388 
 389         // create 4 dayTime Durations using the 4 different constructors
 390 
 391         Duration durationDayTimeBigInteger = datatypeFactory.newDurationDayTime(isPositive, days, hours, minutes, seconds.toBigInteger());
 392         durationAssertEquals(durationDayTimeBigInteger, DatatypeConstants.DURATION_DAYTIME, normalizedIsPositive, normalizedYears.intValue(),
 393                 normalizedMonths.intValue(), normalizedDays.intValue(), normalizedHours.intValue(), normalizedMinutes.intValue(), normalizedSeconds.intValue(),
 394                 normalizedDurationInMilliSeconds, normalizedLexicalRepresentation);
 395 
 396         /*
 397          * Duration durationDayTimeInt = datatypeFactory.newDurationDayTime(
 398          * isPositive, days.intValue(), hours.intValue(), minutes.intValue(),
 399          * seconds.intValue()); Duration durationDayTimeMilliseconds =
 400          * datatypeFactory.newDurationDayTime( durationInMilliSeconds); Duration
 401          * durationDayTimeLexical = datatypeFactory.newDurationDayTime(
 402          * lexicalRepresentation);
 403          * Duration durationYearMonthBigInteger =
 404          * datatypeFactory.newDurationYearMonth( isPositive, years, months);
 405          * Duration durationYearMonthInt = datatypeFactory.newDurationYearMonth(
 406          * isPositive, years.intValue(), months.intValue()); Duration
 407          * durationYearMonthMilliseconds = datatypeFactory.newDurationYearMonth(
 408          * durationInMilliSeconds); Duration durationYearMonthLexical =
 409          * datatypeFactory.newDurationYearMonth( lexicalRepresentation) ;
 410          */
 411 
 412     }
 413 
 414     private void durationAssertEquals(Duration duration, QName xmlSchemaType, boolean isPositive, int years, int months, int days, int hours, int minutes,
 415             int seconds, long milliseconds, String lexical) {
 416 
 417         final TimeZone GMT = TimeZone.getTimeZone("GMT");
 418         final GregorianCalendar EPOCH = new GregorianCalendar(GMT);
 419         EPOCH.clear();
 420 
 421         if (DEBUG) {
 422             System.out.println("Testing Duration: " + duration.toString());
 423         }
 424 
 425         // sign
 426         if (DEBUG) {
 427             boolean actual = (duration.getSign() == 1) ? true : false;
 428             System.out.println("sign:");
 429             System.out.println("    expected: \"" + isPositive + "\"");
 430             System.out.println("    actual:   \"" + actual + "\"");
 431         }
 432 
 433         if (DEBUG) {
 434             System.out.println("years:");
 435             System.out.println("    expected: \"" + years + "\"");
 436             System.out.println("    actual:   \"" + duration.getYears() + "\"");
 437         }
 438 
 439         if (DEBUG) {
 440             System.out.println("months:");
 441             System.out.println("    expected: \"" + months + "\"");
 442             System.out.println("    actual:   \"" + duration.getMonths() + "\"");
 443         }
 444 
 445         if (DEBUG) {
 446             System.out.println("days:");
 447             System.out.println("    expected: \"" + days + "\"");
 448             System.out.println("    actual:   \"" + duration.getDays() + "\"");
 449         }
 450 
 451         if (DEBUG) {
 452             System.out.println("hours:");
 453             System.out.println("    expected: \"" + hours + "\"");
 454             System.out.println("    actual:   \"" + duration.getHours() + "\"");
 455         }
 456 
 457         if (DEBUG) {
 458             System.out.println("minutes:");
 459             System.out.println("    expected: \"" + minutes + "\"");
 460             System.out.println("    actual:   \"" + duration.getMinutes() + "\"");
 461         }
 462 
 463         if (DEBUG) {
 464             System.out.println("seconds:");
 465             System.out.println("    expected: \"" + seconds + "\"");
 466             System.out.println("    actual:   \"" + duration.getSeconds() + "\"");
 467         }
 468 
 469         if (DEBUG) {
 470             System.out.println("milliseconds:");
 471             System.out.println("    expected: \"" + milliseconds + "\"");
 472             System.out.println("    actual:   \"" + duration.getTimeInMillis(EPOCH) + "\"");
 473         }
 474 
 475         if (DEBUG) {
 476             System.out.println("lexical:");
 477             System.out.println("    expected: \"" + lexical + "\"");
 478             System.out.println("    actual:   \"" + duration.toString() + "\"");
 479         }
 480 
 481     }
 482 }