001    /*
002     *  Copyright 2001-2009 Stephen Colebourne
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.joda.time;
017    
018    import java.io.ByteArrayInputStream;
019    import java.io.ByteArrayOutputStream;
020    import java.io.ObjectInputStream;
021    import java.io.ObjectOutputStream;
022    import java.util.Arrays;
023    import java.util.Locale;
024    
025    import junit.framework.TestCase;
026    import junit.framework.TestSuite;
027    
028    import org.joda.time.chrono.BuddhistChronology;
029    import org.joda.time.chrono.CopticChronology;
030    import org.joda.time.chrono.GregorianChronology;
031    import org.joda.time.chrono.ISOChronology;
032    import org.joda.time.format.DateTimeFormat;
033    import org.joda.time.format.DateTimeFormatter;
034    
035    /**
036     * This class is a Junit unit test for TimeOfDay.
037     *
038     * @author Stephen Colebourne
039     */
040    public class TestTimeOfDay_Basics extends TestCase {
041    
042        private static final DateTimeZone PARIS = DateTimeZone.forID("Europe/Paris");
043        private static final DateTimeZone LONDON = DateTimeZone.forID("Europe/London");
044        private static final DateTimeZone TOKYO = DateTimeZone.forID("Asia/Tokyo");
045        private static final int OFFSET = 1;
046        private static final Chronology COPTIC_PARIS = CopticChronology.getInstance(PARIS);
047        private static final Chronology COPTIC_LONDON = CopticChronology.getInstance(LONDON);
048        private static final Chronology COPTIC_TOKYO = CopticChronology.getInstance(TOKYO);
049        private static final Chronology COPTIC_UTC = CopticChronology.getInstanceUTC();
050        private static final Chronology ISO_PARIS = ISOChronology.getInstance(PARIS);
051        private static final Chronology ISO_LONDON = ISOChronology.getInstance(LONDON);
052        private static final Chronology ISO_TOKYO = ISOChronology.getInstance(TOKYO);
053        private static final Chronology ISO_UTC = ISOChronology.getInstanceUTC();
054        private static final Chronology BUDDHIST_PARIS = BuddhistChronology.getInstance(PARIS);
055        private static final Chronology BUDDHIST_LONDON = BuddhistChronology.getInstance(LONDON);
056        private static final Chronology BUDDHIST_TOKYO = BuddhistChronology.getInstance(TOKYO);
057        private static final Chronology BUDDHIST_UTC = BuddhistChronology.getInstanceUTC();
058        
059        private long TEST_TIME_NOW =
060                10L * DateTimeConstants.MILLIS_PER_HOUR
061                + 20L * DateTimeConstants.MILLIS_PER_MINUTE
062                + 30L * DateTimeConstants.MILLIS_PER_SECOND
063                + 40L;
064                
065        private long TEST_TIME1 =
066            1L * DateTimeConstants.MILLIS_PER_HOUR
067            + 2L * DateTimeConstants.MILLIS_PER_MINUTE
068            + 3L * DateTimeConstants.MILLIS_PER_SECOND
069            + 4L;
070            
071        private long TEST_TIME2 =
072            1L * DateTimeConstants.MILLIS_PER_DAY
073            + 5L * DateTimeConstants.MILLIS_PER_HOUR
074            + 6L * DateTimeConstants.MILLIS_PER_MINUTE
075            + 7L * DateTimeConstants.MILLIS_PER_SECOND
076            + 8L;
077            
078        private DateTimeZone zone = null;
079    
080        public static void main(String[] args) {
081            junit.textui.TestRunner.run(suite());
082        }
083    
084        public static TestSuite suite() {
085            return new TestSuite(TestTimeOfDay_Basics.class);
086        }
087    
088        public TestTimeOfDay_Basics(String name) {
089            super(name);
090        }
091    
092        protected void setUp() throws Exception {
093            DateTimeUtils.setCurrentMillisFixed(TEST_TIME_NOW);
094            zone = DateTimeZone.getDefault();
095            DateTimeZone.setDefault(LONDON);
096        }
097    
098        protected void tearDown() throws Exception {
099            DateTimeUtils.setCurrentMillisSystem();
100            DateTimeZone.setDefault(zone);
101            zone = null;
102        }
103    
104        //-----------------------------------------------------------------------
105        public void testGet() {
106            TimeOfDay test = new TimeOfDay();
107            assertEquals(10 + OFFSET, test.get(DateTimeFieldType.hourOfDay()));
108            assertEquals(20, test.get(DateTimeFieldType.minuteOfHour()));
109            assertEquals(30, test.get(DateTimeFieldType.secondOfMinute()));
110            assertEquals(40, test.get(DateTimeFieldType.millisOfSecond()));
111            try {
112                test.get(null);
113                fail();
114            } catch (IllegalArgumentException ex) {}
115            try {
116                test.get(DateTimeFieldType.dayOfMonth());
117                fail();
118            } catch (IllegalArgumentException ex) {}
119        }
120    
121        public void testSize() {
122            TimeOfDay test = new TimeOfDay();
123            assertEquals(4, test.size());
124        }
125    
126        public void testGetFieldType() {
127            TimeOfDay test = new TimeOfDay(COPTIC_PARIS);
128            assertSame(DateTimeFieldType.hourOfDay(), test.getFieldType(0));
129            assertSame(DateTimeFieldType.minuteOfHour(), test.getFieldType(1));
130            assertSame(DateTimeFieldType.secondOfMinute(), test.getFieldType(2));
131            assertSame(DateTimeFieldType.millisOfSecond(), test.getFieldType(3));
132            try {
133                test.getFieldType(-1);
134            } catch (IndexOutOfBoundsException ex) {}
135            try {
136                test.getFieldType(5);
137            } catch (IndexOutOfBoundsException ex) {}
138        }
139    
140        public void testGetFieldTypes() {
141            TimeOfDay test = new TimeOfDay(COPTIC_PARIS);
142            DateTimeFieldType[] fields = test.getFieldTypes();
143            assertSame(DateTimeFieldType.hourOfDay(), fields[0]);
144            assertSame(DateTimeFieldType.minuteOfHour(), fields[1]);
145            assertSame(DateTimeFieldType.secondOfMinute(), fields[2]);
146            assertSame(DateTimeFieldType.millisOfSecond(), fields[3]);
147            assertNotSame(test.getFieldTypes(), test.getFieldTypes());
148        }
149    
150        public void testGetField() {
151            TimeOfDay test = new TimeOfDay(COPTIC_PARIS);
152            assertSame(CopticChronology.getInstanceUTC().hourOfDay(), test.getField(0));
153            assertSame(CopticChronology.getInstanceUTC().minuteOfHour(), test.getField(1));
154            assertSame(CopticChronology.getInstanceUTC().secondOfMinute(), test.getField(2));
155            assertSame(CopticChronology.getInstanceUTC().millisOfSecond(), test.getField(3));
156            try {
157                test.getField(-1);
158            } catch (IndexOutOfBoundsException ex) {}
159            try {
160                test.getField(5);
161            } catch (IndexOutOfBoundsException ex) {}
162        }
163    
164        public void testGetFields() {
165            TimeOfDay test = new TimeOfDay(COPTIC_PARIS);
166            DateTimeField[] fields = test.getFields();
167            assertSame(CopticChronology.getInstanceUTC().hourOfDay(), fields[0]);
168            assertSame(CopticChronology.getInstanceUTC().minuteOfHour(), fields[1]);
169            assertSame(CopticChronology.getInstanceUTC().secondOfMinute(), fields[2]);
170            assertSame(CopticChronology.getInstanceUTC().millisOfSecond(), fields[3]);
171            assertNotSame(test.getFields(), test.getFields());
172        }
173    
174        public void testGetValue() {
175            TimeOfDay test = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS);
176            assertEquals(10, test.getValue(0));
177            assertEquals(20, test.getValue(1));
178            assertEquals(30, test.getValue(2));
179            assertEquals(40, test.getValue(3));
180            try {
181                test.getValue(-1);
182            } catch (IndexOutOfBoundsException ex) {}
183            try {
184                test.getValue(5);
185            } catch (IndexOutOfBoundsException ex) {}
186        }
187    
188        public void testGetValues() {
189            TimeOfDay test = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS);
190            int[] values = test.getValues();
191            assertEquals(10, values[0]);
192            assertEquals(20, values[1]);
193            assertEquals(30, values[2]);
194            assertEquals(40, values[3]);
195            assertNotSame(test.getValues(), test.getValues());
196        }
197    
198        public void testIsSupported() {
199            TimeOfDay test = new TimeOfDay(COPTIC_PARIS);
200            assertEquals(true, test.isSupported(DateTimeFieldType.hourOfDay()));
201            assertEquals(true, test.isSupported(DateTimeFieldType.minuteOfHour()));
202            assertEquals(true, test.isSupported(DateTimeFieldType.secondOfMinute()));
203            assertEquals(true, test.isSupported(DateTimeFieldType.millisOfSecond()));
204            assertEquals(false, test.isSupported(DateTimeFieldType.dayOfMonth()));
205        }
206    
207        public void testEqualsHashCode() {
208            TimeOfDay test1 = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS);
209            TimeOfDay test2 = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS);
210            assertEquals(true, test1.equals(test2));
211            assertEquals(true, test2.equals(test1));
212            assertEquals(true, test1.equals(test1));
213            assertEquals(true, test2.equals(test2));
214            assertEquals(true, test1.hashCode() == test2.hashCode());
215            assertEquals(true, test1.hashCode() == test1.hashCode());
216            assertEquals(true, test2.hashCode() == test2.hashCode());
217            
218            TimeOfDay test3 = new TimeOfDay(15, 20, 30, 40);
219            assertEquals(false, test1.equals(test3));
220            assertEquals(false, test2.equals(test3));
221            assertEquals(false, test3.equals(test1));
222            assertEquals(false, test3.equals(test2));
223            assertEquals(false, test1.hashCode() == test3.hashCode());
224            assertEquals(false, test2.hashCode() == test3.hashCode());
225            
226            assertEquals(false, test1.equals("Hello"));
227            assertEquals(true, test1.equals(new MockInstant()));
228            assertEquals(false, test1.equals(MockPartial.EMPTY_INSTANCE));
229        }
230    
231        class MockInstant extends MockPartial {
232            public Chronology getChronology() {
233                return CopticChronology.getInstanceUTC();
234            }
235            public DateTimeField[] getFields() {
236                return new DateTimeField[] {
237                    CopticChronology.getInstanceUTC().hourOfDay(),
238                    CopticChronology.getInstanceUTC().minuteOfHour(),
239                    CopticChronology.getInstanceUTC().secondOfMinute(),
240                    CopticChronology.getInstanceUTC().millisOfSecond(),
241                };
242            }
243            public int[] getValues() {
244                return new int[] {10, 20, 30, 40};
245            }
246        }
247    
248        //-----------------------------------------------------------------------
249        public void testCompareTo() {
250            TimeOfDay test1 = new TimeOfDay(10, 20, 30, 40);
251            TimeOfDay test1a = new TimeOfDay(10, 20, 30, 40);
252            assertEquals(0, test1.compareTo(test1a));
253            assertEquals(0, test1a.compareTo(test1));
254            assertEquals(0, test1.compareTo(test1));
255            assertEquals(0, test1a.compareTo(test1a));
256            
257            TimeOfDay test2 = new TimeOfDay(10, 20, 35, 40);
258            assertEquals(-1, test1.compareTo(test2));
259            assertEquals(+1, test2.compareTo(test1));
260            
261            TimeOfDay test3 = new TimeOfDay(10, 20, 35, 40, GregorianChronology.getInstanceUTC());
262            assertEquals(-1, test1.compareTo(test3));
263            assertEquals(+1, test3.compareTo(test1));
264            assertEquals(0, test3.compareTo(test2));
265            
266            DateTimeFieldType[] types = new DateTimeFieldType[] {
267                DateTimeFieldType.hourOfDay(),
268                DateTimeFieldType.minuteOfHour(),
269                DateTimeFieldType.secondOfMinute(),
270                DateTimeFieldType.millisOfSecond(),
271            };
272            int[] values = new int[] {10, 20, 30, 40};
273            Partial p = new Partial(types, values);
274            assertEquals(0, test1.compareTo(p));
275            try {
276                test1.compareTo(null);
277                fail();
278            } catch (NullPointerException ex) {}
279    //        try {
280    //            test1.compareTo(new Date());
281    //            fail();
282    //        } catch (ClassCastException ex) {}
283        }
284    
285        //-----------------------------------------------------------------------
286        public void testIsEqual_TOD() {
287            TimeOfDay test1 = new TimeOfDay(10, 20, 30, 40);
288            TimeOfDay test1a = new TimeOfDay(10, 20, 30, 40);
289            assertEquals(true, test1.isEqual(test1a));
290            assertEquals(true, test1a.isEqual(test1));
291            assertEquals(true, test1.isEqual(test1));
292            assertEquals(true, test1a.isEqual(test1a));
293            
294            TimeOfDay test2 = new TimeOfDay(10, 20, 35, 40);
295            assertEquals(false, test1.isEqual(test2));
296            assertEquals(false, test2.isEqual(test1));
297            
298            TimeOfDay test3 = new TimeOfDay(10, 20, 35, 40, GregorianChronology.getInstanceUTC());
299            assertEquals(false, test1.isEqual(test3));
300            assertEquals(false, test3.isEqual(test1));
301            assertEquals(true, test3.isEqual(test2));
302            
303            try {
304                new TimeOfDay(10, 20, 35, 40).isEqual(null);
305                fail();
306            } catch (IllegalArgumentException ex) {}
307        }
308        
309        //-----------------------------------------------------------------------
310        public void testIsBefore_TOD() {
311            TimeOfDay test1 = new TimeOfDay(10, 20, 30, 40);
312            TimeOfDay test1a = new TimeOfDay(10, 20, 30, 40);
313            assertEquals(false, test1.isBefore(test1a));
314            assertEquals(false, test1a.isBefore(test1));
315            assertEquals(false, test1.isBefore(test1));
316            assertEquals(false, test1a.isBefore(test1a));
317            
318            TimeOfDay test2 = new TimeOfDay(10, 20, 35, 40);
319            assertEquals(true, test1.isBefore(test2));
320            assertEquals(false, test2.isBefore(test1));
321            
322            TimeOfDay test3 = new TimeOfDay(10, 20, 35, 40, GregorianChronology.getInstanceUTC());
323            assertEquals(true, test1.isBefore(test3));
324            assertEquals(false, test3.isBefore(test1));
325            assertEquals(false, test3.isBefore(test2));
326            
327            try {
328                new TimeOfDay(10, 20, 35, 40).isBefore(null);
329                fail();
330            } catch (IllegalArgumentException ex) {}
331        }
332        
333        //-----------------------------------------------------------------------
334        public void testIsAfter_TOD() {
335            TimeOfDay test1 = new TimeOfDay(10, 20, 30, 40);
336            TimeOfDay test1a = new TimeOfDay(10, 20, 30, 40);
337            assertEquals(false, test1.isAfter(test1a));
338            assertEquals(false, test1a.isAfter(test1));
339            assertEquals(false, test1.isAfter(test1));
340            assertEquals(false, test1a.isAfter(test1a));
341            
342            TimeOfDay test2 = new TimeOfDay(10, 20, 35, 40);
343            assertEquals(false, test1.isAfter(test2));
344            assertEquals(true, test2.isAfter(test1));
345            
346            TimeOfDay test3 = new TimeOfDay(10, 20, 35, 40, GregorianChronology.getInstanceUTC());
347            assertEquals(false, test1.isAfter(test3));
348            assertEquals(true, test3.isAfter(test1));
349            assertEquals(false, test3.isAfter(test2));
350            
351            try {
352                new TimeOfDay(10, 20, 35, 40).isAfter(null);
353                fail();
354            } catch (IllegalArgumentException ex) {}
355        }
356        
357        //-----------------------------------------------------------------------
358        public void testWithChronologyRetainFields_Chrono() {
359            TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS);
360            TimeOfDay test = base.withChronologyRetainFields(BUDDHIST_TOKYO);
361            check(base, 10, 20, 30, 40);
362            assertEquals(COPTIC_UTC, base.getChronology());
363            check(test, 10, 20, 30, 40);
364            assertEquals(BUDDHIST_UTC, test.getChronology());
365        }
366    
367        public void testWithChronologyRetainFields_sameChrono() {
368            TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS);
369            TimeOfDay test = base.withChronologyRetainFields(COPTIC_TOKYO);
370            assertSame(base, test);
371        }
372    
373        public void testWithChronologyRetainFields_nullChrono() {
374            TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS);
375            TimeOfDay test = base.withChronologyRetainFields(null);
376            check(base, 10, 20, 30, 40);
377            assertEquals(COPTIC_UTC, base.getChronology());
378            check(test, 10, 20, 30, 40);
379            assertEquals(ISO_UTC, test.getChronology());
380        }
381    
382        //-----------------------------------------------------------------------
383        public void testWithField1() {
384            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
385            TimeOfDay result = test.withField(DateTimeFieldType.hourOfDay(), 15);
386            
387            assertEquals(new TimeOfDay(10, 20, 30, 40), test);
388            assertEquals(new TimeOfDay(15, 20, 30, 40), result);
389        }
390    
391        public void testWithField2() {
392            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
393            try {
394                test.withField(null, 6);
395                fail();
396            } catch (IllegalArgumentException ex) {}
397        }
398    
399        public void testWithField3() {
400            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
401            try {
402                test.withField(DateTimeFieldType.dayOfMonth(), 6);
403                fail();
404            } catch (IllegalArgumentException ex) {}
405        }
406    
407        public void testWithField4() {
408            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
409            TimeOfDay result = test.withField(DateTimeFieldType.hourOfDay(), 10);
410            assertSame(test, result);
411        }
412    
413        //-----------------------------------------------------------------------
414        public void testWithFieldAdded1() {
415            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
416            TimeOfDay result = test.withFieldAdded(DurationFieldType.hours(), 6);
417            
418            assertEquals(new TimeOfDay(10, 20, 30, 40), test);
419            assertEquals(new TimeOfDay(16, 20, 30, 40), result);
420        }
421    
422        public void testWithFieldAdded2() {
423            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
424            try {
425                test.withFieldAdded(null, 0);
426                fail();
427            } catch (IllegalArgumentException ex) {}
428        }
429    
430        public void testWithFieldAdded3() {
431            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
432            try {
433                test.withFieldAdded(null, 6);
434                fail();
435            } catch (IllegalArgumentException ex) {}
436        }
437    
438        public void testWithFieldAdded4() {
439            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
440            TimeOfDay result = test.withFieldAdded(DurationFieldType.hours(), 0);
441            assertSame(test, result);
442        }
443    
444        public void testWithFieldAdded5() {
445            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
446            try {
447                test.withFieldAdded(DurationFieldType.days(), 6);
448                fail();
449            } catch (IllegalArgumentException ex) {}
450        }
451    
452        public void testWithFieldAdded6() {
453            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
454            TimeOfDay result = test.withFieldAdded(DurationFieldType.hours(), 16);
455            
456            assertEquals(new TimeOfDay(10, 20, 30, 40), test);
457            assertEquals(new TimeOfDay(2, 20, 30, 40), result);
458        }
459    
460        public void testWithFieldAdded7() {
461            TimeOfDay test = new TimeOfDay(23, 59, 59, 999);
462            TimeOfDay result = test.withFieldAdded(DurationFieldType.millis(), 1);
463            assertEquals(new TimeOfDay(0, 0, 0, 0), result);
464            
465            test = new TimeOfDay(23, 59, 59, 999);
466            result = test.withFieldAdded(DurationFieldType.seconds(), 1);
467            assertEquals(new TimeOfDay(0, 0, 0, 999), result);
468            
469            test = new TimeOfDay(23, 59, 59, 999);
470            result = test.withFieldAdded(DurationFieldType.minutes(), 1);
471            assertEquals(new TimeOfDay(0, 0, 59, 999), result);
472            
473            test = new TimeOfDay(23, 59, 59, 999);
474            result = test.withFieldAdded(DurationFieldType.hours(), 1);
475            assertEquals(new TimeOfDay(0, 59, 59, 999), result);
476        }
477    
478        public void testWithFieldAdded8() {
479            TimeOfDay test = new TimeOfDay(0, 0, 0, 0);
480            TimeOfDay result = test.withFieldAdded(DurationFieldType.millis(), -1);
481            assertEquals(new TimeOfDay(23, 59, 59, 999), result);
482            
483            test = new TimeOfDay(0, 0, 0, 0);
484            result = test.withFieldAdded(DurationFieldType.seconds(), -1);
485            assertEquals(new TimeOfDay(23, 59, 59, 0), result);
486            
487            test = new TimeOfDay(0, 0, 0, 0);
488            result = test.withFieldAdded(DurationFieldType.minutes(), -1);
489            assertEquals(new TimeOfDay(23, 59, 0, 0), result);
490            
491            test = new TimeOfDay(0, 0, 0, 0);
492            result = test.withFieldAdded(DurationFieldType.hours(), -1);
493            assertEquals(new TimeOfDay(23, 0, 0, 0), result);
494        }
495    
496        //-----------------------------------------------------------------------
497        public void testPlus_RP() {
498            TimeOfDay test = new TimeOfDay(10, 20, 30, 40, BuddhistChronology.getInstance());
499            TimeOfDay result = test.plus(new Period(1, 2, 3, 4, 5, 6, 7, 8));
500            TimeOfDay expected = new TimeOfDay(15, 26, 37, 48, BuddhistChronology.getInstance());
501            assertEquals(expected, result);
502            
503            result = test.plus((ReadablePeriod) null);
504            assertSame(test, result);
505        }
506    
507        public void testPlusHours_int() {
508            TimeOfDay test = new TimeOfDay(1, 2, 3, 4, BuddhistChronology.getInstance());
509            TimeOfDay result = test.plusHours(1);
510            TimeOfDay expected = new TimeOfDay(2, 2, 3, 4, BuddhistChronology.getInstance());
511            assertEquals(expected, result);
512            
513            result = test.plusHours(0);
514            assertSame(test, result);
515        }
516    
517        public void testPlusMinutes_int() {
518            TimeOfDay test = new TimeOfDay(1, 2, 3, 4, BuddhistChronology.getInstance());
519            TimeOfDay result = test.plusMinutes(1);
520            TimeOfDay expected = new TimeOfDay(1, 3, 3, 4, BuddhistChronology.getInstance());
521            assertEquals(expected, result);
522            
523            result = test.plusMinutes(0);
524            assertSame(test, result);
525        }
526    
527        public void testPlusSeconds_int() {
528            TimeOfDay test = new TimeOfDay(1, 2, 3, 4, BuddhistChronology.getInstance());
529            TimeOfDay result = test.plusSeconds(1);
530            TimeOfDay expected = new TimeOfDay(1, 2, 4, 4, BuddhistChronology.getInstance());
531            assertEquals(expected, result);
532            
533            result = test.plusSeconds(0);
534            assertSame(test, result);
535        }
536    
537        public void testPlusMillis_int() {
538            TimeOfDay test = new TimeOfDay(1, 2, 3, 4, BuddhistChronology.getInstance());
539            TimeOfDay result = test.plusMillis(1);
540            TimeOfDay expected = new TimeOfDay(1, 2, 3, 5, BuddhistChronology.getInstance());
541            assertEquals(expected, result);
542            
543            result = test.plusMillis(0);
544            assertSame(test, result);
545        }
546    
547        //-----------------------------------------------------------------------
548        public void testMinus_RP() {
549            TimeOfDay test = new TimeOfDay(10, 20, 30, 40, BuddhistChronology.getInstance());
550            TimeOfDay result = test.minus(new Period(1, 1, 1, 1, 1, 1, 1, 1));
551            TimeOfDay expected = new TimeOfDay(9, 19, 29, 39, BuddhistChronology.getInstance());
552            assertEquals(expected, result);
553            
554            result = test.minus((ReadablePeriod) null);
555            assertSame(test, result);
556        }
557    
558        public void testMinusHours_int() {
559            TimeOfDay test = new TimeOfDay(1, 2, 3, 4, BuddhistChronology.getInstance());
560            TimeOfDay result = test.minusHours(1);
561            TimeOfDay expected = new TimeOfDay(0, 2, 3, 4, BuddhistChronology.getInstance());
562            assertEquals(expected, result);
563            
564            result = test.minusHours(0);
565            assertSame(test, result);
566        }
567    
568        public void testMinusMinutes_int() {
569            TimeOfDay test = new TimeOfDay(1, 2, 3, 4, BuddhistChronology.getInstance());
570            TimeOfDay result = test.minusMinutes(1);
571            TimeOfDay expected = new TimeOfDay(1, 1, 3, 4, BuddhistChronology.getInstance());
572            assertEquals(expected, result);
573            
574            result = test.minusMinutes(0);
575            assertSame(test, result);
576        }
577    
578        public void testMinusSeconds_int() {
579            TimeOfDay test = new TimeOfDay(1, 2, 3, 4, BuddhistChronology.getInstance());
580            TimeOfDay result = test.minusSeconds(1);
581            TimeOfDay expected = new TimeOfDay(1, 2, 2, 4, BuddhistChronology.getInstance());
582            assertEquals(expected, result);
583            
584            result = test.minusSeconds(0);
585            assertSame(test, result);
586        }
587    
588        public void testMinusMillis_int() {
589            TimeOfDay test = new TimeOfDay(1, 2, 3, 4, BuddhistChronology.getInstance());
590            TimeOfDay result = test.minusMillis(1);
591            TimeOfDay expected = new TimeOfDay(1, 2, 3, 3, BuddhistChronology.getInstance());
592            assertEquals(expected, result);
593            
594            result = test.minusMillis(0);
595            assertSame(test, result);
596        }
597    
598        //-----------------------------------------------------------------------
599        public void testToLocalTime() {
600            TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_UTC);
601            LocalTime test = base.toLocalTime();
602            assertEquals(new LocalTime(10, 20, 30, 40, COPTIC_UTC), test);
603        }
604    
605        //-----------------------------------------------------------------------
606        public void testToDateTimeToday() {
607            TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS); // PARIS irrelevant
608            DateTime dt = new DateTime(2004, 6, 9, 6, 7, 8, 9);
609            DateTimeUtils.setCurrentMillisFixed(dt.getMillis());
610            
611            DateTime test = base.toDateTimeToday();
612            check(base, 10, 20, 30, 40);
613            DateTime expected = new DateTime(dt.getMillis(), COPTIC_LONDON);
614            expected = expected.hourOfDay().setCopy(10);
615            expected = expected.minuteOfHour().setCopy(20);
616            expected = expected.secondOfMinute().setCopy(30);
617            expected = expected.millisOfSecond().setCopy(40);
618            assertEquals(expected, test);
619        }
620    
621        //-----------------------------------------------------------------------
622        public void testToDateTimeToday_Zone() {
623            TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS); // PARIS irrelevant
624            DateTime dt = new DateTime(2004, 6, 9, 6, 7, 8, 9);
625            DateTimeUtils.setCurrentMillisFixed(dt.getMillis());
626            
627            DateTime test = base.toDateTimeToday(TOKYO);
628            check(base, 10, 20, 30, 40);
629            DateTime expected = new DateTime(dt.getMillis(), COPTIC_TOKYO);
630            expected = expected.hourOfDay().setCopy(10);
631            expected = expected.minuteOfHour().setCopy(20);
632            expected = expected.secondOfMinute().setCopy(30);
633            expected = expected.millisOfSecond().setCopy(40);
634            assertEquals(expected, test);
635        }
636    
637        public void testToDateTimeToday_nullZone() {
638            TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS); // PARIS irrelevant
639            DateTime dt = new DateTime(2004, 6, 9, 6, 7, 8, 9);
640            DateTimeUtils.setCurrentMillisFixed(dt.getMillis());
641            
642            DateTime test = base.toDateTimeToday((DateTimeZone) null);
643            check(base, 10, 20, 30, 40);
644            DateTime expected = new DateTime(dt.getMillis(), COPTIC_LONDON);
645            expected = expected.hourOfDay().setCopy(10);
646            expected = expected.minuteOfHour().setCopy(20);
647            expected = expected.secondOfMinute().setCopy(30);
648            expected = expected.millisOfSecond().setCopy(40);
649            assertEquals(expected, test);
650        }
651    
652        // Removed as too complex
653    //    /**
654    //     * Merges two partial together, taking account of the different chronologies.
655    //     *
656    //     * @param main  the main partial
657    //     * @param base  the partial to use as a base to merge on top of
658    //     * @param instant  the instant to start from and to use for missing fields
659    //     * @return the merged instant
660    //     */
661    //    public long merge(ReadablePartial main, ReadablePartial base, long instant) {
662    //        DateTimeZone zone = main.getChronology().getZone();
663    //        instant = base.getChronology().withZone(zone).set(base, instant);
664    //        return set(main, instant);
665    //    }
666    //
667    //    //-----------------------------------------------------------------------
668    //    /**
669    //     * Converts this object to a DateTime using a YearMonthDay to fill in the
670    //     * missing fields and using the default time zone.
671    //     * This instance is immutable and unaffected by this method call.
672    //     * <p>
673    //     * The resulting chronology is determined by the chronology of this
674    //     * TimeOfDay plus the time zone.
675    //     * <p>
676    //     * This method makes use of the chronology of the specified YearMonthDay
677    //     * in the calculation. This can be significant when mixing chronologies.
678    //     * If the YearMonthDay is in the same chronology as this instance the
679    //     * method will perform exactly as you might expect.
680    //     * <p>
681    //     * If the chronologies differ, then both this TimeOfDay and the YearMonthDay
682    //     * are converted to the destination chronology and then merged. As a result
683    //     * it may be the case that the year, monthOfYear and dayOfMonth fields on
684    //     * the result are different from the values returned by the methods on the
685    //     * YearMonthDay.
686    //     * <p>
687    //     * See {@link DateTime#withFields(ReadablePartial)} for an algorithm that
688    //     * ignores the chronology.
689    //     *
690    //     * @param date  the date to use, null means today
691    //     * @return the DateTime instance
692    //     */
693    //    public DateTime toDateTime(YearMonthDay date) {
694    //        return toDateTime(date, null);
695    //    }
696    //
697    //    /**
698    //     * Converts this object to a DateTime using a YearMonthDay to fill in the
699    //     * missing fields.
700    //     * This instance is immutable and unaffected by this method call.
701    //     * <p>
702    //     * The resulting chronology is determined by the chronology of this
703    //     * TimeOfDay plus the time zone.
704    //     * <p>
705    //     * This method makes use of the chronology of the specified YearMonthDay
706    //     * in the calculation. This can be significant when mixing chronologies.
707    //     * If the YearMonthDay is in the same chronology as this instance the
708    //     * method will perform exactly as you might expect.
709    //     * <p>
710    //     * If the chronologies differ, then both this TimeOfDay and the YearMonthDay
711    //     * are converted to the destination chronology and then merged. As a result
712    //     * it may be the case that the year, monthOfYear and dayOfMonth fields on
713    //     * the result are different from the values returned by the methods on the
714    //     * YearMonthDay.
715    //     * <p>
716    //     * See {@link DateTime#withFields(ReadablePartial)} for an algorithm that
717    //     * ignores the chronology and just assigns the fields.
718    //     *
719    //     * @param date  the date to use, null means today
720    //     * @param zone  the zone to get the DateTime in, null means default
721    //     * @return the DateTime instance
722    //     */
723    //    public DateTime toDateTime(YearMonthDay date, DateTimeZone zone) {
724    //        Chronology chrono = getChronology().withZone(zone);
725    //        if (date == null) {
726    //            DateTime dt = new DateTime(chrono);
727    //            return dt.withFields(this);
728    //        } else {
729    //            long millis = chrono.merge(this, date, DateTimeUtils.currentTimeMillis());
730    //            return new DateTime(millis, chrono);
731    //        }
732    //    }
733    //
734    //    //-----------------------------------------------------------------------
735    //    public void testToDateTime_YMD() {
736    //        TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS); // PARIS irrelevant
737    //        YearMonthDay ymd = new YearMonthDay(new DateMidnight(2004, 6, 9), BUDDHIST_TOKYO);
738    //        
739    //        DateTime test = base.toDateTime(ymd);
740    //        check(base, 10, 20, 30, 40);
741    //        DateTime expected = new DateTime(ymd.toDateMidnight(LONDON), COPTIC_LONDON);
742    //        expected = expected.hourOfDay().setCopy(10);
743    //        expected = expected.minuteOfHour().setCopy(20);
744    //        expected = expected.secondOfMinute().setCopy(30);
745    //        expected = expected.millisOfSecond().setCopy(40);
746    //        assertEquals(expected, test);
747    //    }
748    //
749    //    public void testToDateTime_nullYMD() {
750    //        TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS); // PARIS irrelevant
751    //        
752    //        DateTime test = base.toDateTime((YearMonthDay) null);
753    //        check(base, 10, 20, 30, 40);
754    //        DateTime expected = new DateTime(COPTIC_LONDON);
755    //        expected = expected.hourOfDay().setCopy(10);
756    //        expected = expected.minuteOfHour().setCopy(20);
757    //        expected = expected.secondOfMinute().setCopy(30);
758    //        expected = expected.millisOfSecond().setCopy(40);
759    //        assertEquals(expected, test);
760    //    }
761    //
762    //    //-----------------------------------------------------------------------
763    //    public void testToDateTime_YMD_Zone() {
764    //        TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS); // PARIS irrelevant
765    //        YearMonthDay ymd = new YearMonthDay(new DateMidnight(2004, 6, 9), BUDDHIST_LONDON);
766    //        
767    //        DateTime test = base.toDateTime(ymd, TOKYO);
768    //        check(base, 10, 20, 30, 40);
769    //        DateTime expected = new DateTime(ymd.toDateMidnight(TOKYO), COPTIC_TOKYO);
770    //        expected = expected.hourOfDay().setCopy(10);
771    //        expected = expected.minuteOfHour().setCopy(20);
772    //        expected = expected.secondOfMinute().setCopy(30);
773    //        expected = expected.millisOfSecond().setCopy(40);
774    //        assertEquals(expected, test);
775    //    }
776    //
777    //    public void testToDateTime_YMD_nullZone() {
778    //        TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS); // PARIS irrelevant
779    //        YearMonthDay ymd = new YearMonthDay(new DateMidnight(2004, 6, 9), BUDDHIST_LONDON);
780    //        
781    //        DateTime test = base.toDateTime(ymd, null);
782    //        check(base, 10, 20, 30, 40);
783    //        DateTime expected = new DateTime(ymd.toDateMidnight(LONDON), COPTIC_LONDON);
784    //        expected = expected.hourOfDay().setCopy(10);
785    //        expected = expected.minuteOfHour().setCopy(20);
786    //        expected = expected.secondOfMinute().setCopy(30);
787    //        expected = expected.millisOfSecond().setCopy(40);
788    //        assertEquals(expected, test);
789    //    }
790    //
791    //    public void testToDateTime_nullYMD_Zone() {
792    //        TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS); // PARIS irrelevant
793    //        
794    //        DateTime test = base.toDateTime((YearMonthDay) null, TOKYO);
795    //        check(base, 10, 20, 30, 40);
796    //        DateTime expected = new DateTime(COPTIC_TOKYO);
797    //        expected = expected.hourOfDay().setCopy(10);
798    //        expected = expected.minuteOfHour().setCopy(20);
799    //        expected = expected.secondOfMinute().setCopy(30);
800    //        expected = expected.millisOfSecond().setCopy(40);
801    //        assertEquals(expected, test);
802    //    }
803    
804        //-----------------------------------------------------------------------
805        public void testToDateTime_RI() {
806            TimeOfDay base = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS);
807            DateTime dt = new DateTime(0L); // LONDON zone
808            assertEquals("1970-01-01T01:00:00.000+01:00", dt.toString());
809            
810            DateTime test = base.toDateTime(dt);
811            check(base, 10, 20, 30, 40);
812            assertEquals("1970-01-01T01:00:00.000+01:00", dt.toString());
813            assertEquals("1970-01-01T10:20:30.040+01:00", test.toString());
814        }
815    
816        public void testToDateTime_nullRI() {
817            TimeOfDay base = new TimeOfDay(1, 2, 3, 4);
818            DateTimeUtils.setCurrentMillisFixed(TEST_TIME2);
819            
820            DateTime test = base.toDateTime((ReadableInstant) null);
821            check(base, 1, 2, 3, 4);
822            assertEquals("1970-01-02T01:02:03.004+01:00", test.toString());
823        }
824    
825        //-----------------------------------------------------------------------
826        public void testWithers() {
827            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
828            check(test.withHourOfDay(6), 6, 20, 30, 40);
829            check(test.withMinuteOfHour(6), 10, 6, 30, 40);
830            check(test.withSecondOfMinute(6), 10, 20, 6, 40);
831            check(test.withMillisOfSecond(6), 10, 20, 30, 6);
832            try {
833                test.withHourOfDay(-1);
834                fail();
835            } catch (IllegalArgumentException ex) {}
836            try {
837                test.withHourOfDay(24);
838                fail();
839            } catch (IllegalArgumentException ex) {}
840        }
841    
842        //-----------------------------------------------------------------------
843        public void testProperty() {
844            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
845            assertEquals(test.hourOfDay(), test.property(DateTimeFieldType.hourOfDay()));
846            assertEquals(test.minuteOfHour(), test.property(DateTimeFieldType.minuteOfHour()));
847            assertEquals(test.secondOfMinute(), test.property(DateTimeFieldType.secondOfMinute()));
848            assertEquals(test.millisOfSecond(), test.property(DateTimeFieldType.millisOfSecond()));
849            try {
850                test.property(DateTimeFieldType.millisOfDay());
851                fail();
852            } catch (IllegalArgumentException ex) {}
853            try {
854                test.property(null);
855                fail();
856            } catch (IllegalArgumentException ex) {}
857        }
858    
859        //-----------------------------------------------------------------------
860        public void testSerialization() throws Exception {
861            TimeOfDay test = new TimeOfDay(10, 20, 30, 40, COPTIC_PARIS);
862            
863            ByteArrayOutputStream baos = new ByteArrayOutputStream();
864            ObjectOutputStream oos = new ObjectOutputStream(baos);
865            oos.writeObject(test);
866            byte[] bytes = baos.toByteArray();
867            oos.close();
868            
869            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
870            ObjectInputStream ois = new ObjectInputStream(bais);
871            TimeOfDay result = (TimeOfDay) ois.readObject();
872            ois.close();
873            
874            assertEquals(test, result);
875            assertTrue(Arrays.equals(test.getValues(), result.getValues()));
876            assertTrue(Arrays.equals(test.getFields(), result.getFields()));
877            assertEquals(test.getChronology(), result.getChronology());
878        }
879    
880        //-----------------------------------------------------------------------
881        public void testToString() {
882            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
883            assertEquals("T10:20:30.040", test.toString());
884        }
885    
886        //-----------------------------------------------------------------------
887        public void testToString_String() {
888            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
889            assertEquals("\ufffd\ufffd\ufffd\ufffd 10", test.toString("yyyy HH"));
890            assertEquals("T10:20:30.040", test.toString((String) null));
891        }
892    
893        //-----------------------------------------------------------------------
894        public void testToString_String_Locale() {
895            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
896            assertEquals("10 20", test.toString("H m", Locale.ENGLISH));
897            assertEquals("T10:20:30.040", test.toString(null, Locale.ENGLISH));
898            assertEquals("10 20", test.toString("H m", null));
899            assertEquals("T10:20:30.040", test.toString(null, null));
900        }
901    
902        //-----------------------------------------------------------------------
903        public void testToString_DTFormatter() {
904            TimeOfDay test = new TimeOfDay(10, 20, 30, 40);
905            assertEquals("\ufffd\ufffd\ufffd\ufffd 10", test.toString(DateTimeFormat.forPattern("yyyy HH")));
906            assertEquals("T10:20:30.040", test.toString((DateTimeFormatter) null));
907        }
908    
909        //-----------------------------------------------------------------------
910        private void check(TimeOfDay test, int hour, int min, int sec, int milli) {
911            assertEquals(hour, test.getHourOfDay());
912            assertEquals(min, test.getMinuteOfHour());
913            assertEquals(sec, test.getSecondOfMinute());
914            assertEquals(milli, test.getMillisOfSecond());
915        }
916    }