1   /* Copyright 2002-2022 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS 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  package org.orekit.time;
18  
19  
20  import org.hamcrest.CoreMatchers;
21  import org.hamcrest.MatcherAssert;
22  import org.hipparchus.util.FastMath;
23  import org.junit.Assert;
24  import org.junit.Test;
25  
26  
27  public class DateTimeComponentsTest {
28  
29      @SuppressWarnings("unlikely-arg-type")
30      @Test
31      public void testComparisons() {
32          DateTimeComponents[] dates = {
33                  new DateTimeComponents(2003,  1,  1, 7, 15, 33),
34                  new DateTimeComponents(2003,  1,  1, 7, 15, 34),
35                  new DateTimeComponents(2003,  1,  1, 7, 16, 34),
36                  new DateTimeComponents(2003,  1,  1, 8, 16, 34),
37                  new DateTimeComponents(2003,  1,  2, 8, 16, 34),
38                  new DateTimeComponents(2003,  2,  2, 8, 16, 34),
39                  new DateTimeComponents(2004,  2,  2, 8, 16, 34)
40          };
41          for (int i = 0; i < dates.length; ++i) {
42              for (int j = 0; j < dates.length; ++j) {
43                  Assert.assertEquals(i  < j, dates[i].compareTo(dates[j])  < 0);
44                  Assert.assertEquals(i  > j, dates[j].compareTo(dates[i])  < 0);
45                  Assert.assertEquals(i == j, dates[i].compareTo(dates[j]) == 0);
46                  Assert.assertEquals(i  > j, dates[i].compareTo(dates[j])  > 0);
47                  Assert.assertEquals(i  < j, dates[j].compareTo(dates[i])  > 0);
48              }
49          }
50          Assert.assertFalse(dates[0].equals(this));
51          Assert.assertFalse(dates[0].equals(dates[0].getDate()));
52          Assert.assertFalse(dates[0].equals(dates[0].getTime()));
53      }
54  
55      @Test
56      public void testOffset() {
57          DateTimeComponents reference = new DateTimeComponents(2005, 12, 31, 23, 59, 59);
58          DateTimeComponents expected  = new DateTimeComponents(2006,  1,  1,  0,  0,  0);
59          Assert.assertEquals(expected, new DateTimeComponents(reference, 1));
60      }
61  
62      @Test
63      public void testSymmetry() {
64          DateTimeComponents reference1 = new DateTimeComponents(2005, 12, 31, 12, 0, 0);
65          DateTimeComponents reference2 = new DateTimeComponents(2006,  1,  1,  1, 2, 3);
66          for (double dt = -100000; dt < 100000; dt += 100) {
67              Assert.assertEquals(dt, new DateTimeComponents(reference1, dt).offsetFrom(reference1), 1.0e-15);
68              Assert.assertEquals(dt, new DateTimeComponents(reference2, dt).offsetFrom(reference2), 1.0e-15);
69          }
70      }
71  
72      @Test
73      public void testString() {
74          final DateTimeComponents date =
75              new DateTimeComponents(DateComponents.J2000_EPOCH, TimeComponents.H12);
76          Assert.assertEquals("2000-01-01T12:00:00.000+00:00", date.toString());
77      }
78  
79      @Test
80      public void testMonth() {
81          Assert.assertEquals(new DateTimeComponents(2011, 2, 23),
82                              new DateTimeComponents(2011, Month.FEBRUARY, 23));
83          Assert.assertEquals(new DateTimeComponents(2011, 2, 23, 1, 2, 3.4),
84                              new DateTimeComponents(2011, Month.FEBRUARY, 23, 1, 2, 3.4));
85      }
86  
87      @Test
88      public void testParse() {
89          String s = "2000-01-02T03:04:05.000";
90          Assert.assertEquals(s, DateTimeComponents.parseDateTime(s).toStringWithoutUtcOffset());
91          s = "2000-01-02T03:04:05.000+00:00";
92          Assert.assertEquals(s, DateTimeComponents.parseDateTime(s).toString());
93      }
94  
95      @Test(expected=IllegalArgumentException.class)
96      public void testBadDay() {
97          DateTimeComponents.parseDateTime("2000-02-30T03:04:05.000+00:00");
98      }
99  
100     @Test
101     public void testLocalTime() {
102         final DateTimeComponents dtc = DateTimeComponents.parseDateTime("2000-02-29T03:04:05.000+00:01");
103         Assert.assertEquals(1, dtc.getTime().getMinutesFromUTC());
104     }
105 
106     /**
107      * This test is for offsets from UTC. The corresponding test in AbsoluteDateTest
108      * handles UTC.
109      */
110     @Test
111     public void testToStringRfc3339() {
112         // setup
113         int m = 779; // 12 hours, 59 minutes
114         final double sixtyOne = FastMath.nextDown(61.0);
115 
116         // action + verify
117         check(2009, 1, 1, 12, 0, 0, m, "2009-01-01T12:00:00+12:59");
118         check(2009, 1, 1, 12, 0, 0, -m, "2009-01-01T12:00:00-12:59");
119         check(2009, 1, 1, 12, 0, 0, 1, "2009-01-01T12:00:00+00:01");
120         check(2009, 1, 1, 12, 0, 0, -1, "2009-01-01T12:00:00-00:01");
121         // 00:00:00 local time
122         check(2009, 1, 1, 0, 0, 0, 59, "2009-01-01T00:00:00+00:59");
123         check(2009, 1, 1, 0, 0, 0, -59, "2009-01-01T00:00:00-00:59");
124         check(2009, 1, 1, 0, 0, 0, 0, "2009-01-01T00:00:00Z");
125         // 00:00:00 UTC, but in a time zone
126         check(2009, 1, 2, 1, 0, 0, 60, "2009-01-02T01:00:00+01:00");
127         check(2009, 1, 1, 23, 0, 0, -60, "2009-01-01T23:00:00-01:00");
128         // leap seconds
129         check(2009, 12, 31, 23, 59, sixtyOne, m, "2009-12-31T23:59:60.99999999999999+12:59");
130         check(2009, 12, 31, 23, 59, sixtyOne, -m, "2009-12-31T23:59:60.99999999999999-12:59");
131         check(9999, 2, 3, 4, 5, 60.5, 60, "9999-02-03T04:05:60.5+01:00");
132         check(9999, 2, 3, 4, 5, 60.5, -60, "9999-02-03T04:05:60.5-01:00");
133         // time zone offsets larger than 99:59?
134         // TimeComponents should limit time zone offset to valid values.
135         // toString will just format the values given
136         check(2009, 1, 1, 12, 0, 0, 100*60, "2009-01-01T12:00:00+100:00");
137         check(2009, 1, 1, 12, 0, 0, -100*60, "2009-01-01T12:00:00-100:00");
138         // same for negative years
139         check(-1, 1, 1, 12, 0, 0, m, "-001-01-01T12:00:00+12:59");
140         check(-1, 1, 1, 12, 0, 0, -m, "-001-01-01T12:00:00-12:59");
141         check(-1000, 1, 1, 12, 0, 0, m, "-1000-01-01T12:00:00+12:59");
142         check(-1000, 1, 1, 12, 0, 0, -m, "-1000-01-01T12:00:00-12:59");
143     }
144 
145     private static void check(
146             int year, int month, int day, int hour, int minute, double second,
147             int minutesFromUtc,
148             String expected) {
149         DateTimeComponents actual = new DateTimeComponents(
150                 new DateComponents(year, month, day),
151                 new TimeComponents(hour, minute, second, minutesFromUtc));
152 
153         MatcherAssert.assertThat(actual.toStringRfc3339(), CoreMatchers.is(expected));
154     }
155 
156     @Test
157     public void testToStringRounding() {
158         // these tests were copied from AbsoluteDateTest
159         check(2015, 9, 30, 7, 54, 60 - 9.094947e-13, 60,
160                 "2015-09-30T07:54:59.99999999999909+00:00",
161                 "2015-09-30T07:55:00.000+00:00",
162                 "2015-09-30T07:55:00+00:00");
163         check(2008, 2, 29, 23, 59, 59.9994, 60,
164                 "2008-02-29T23:59:59.99940000000000+00:00",
165                 "2008-02-29T23:59:59.999+00:00",
166                 "2008-03-01T00:00:00+00:00");
167         check(2008, 2, 29, 23, 59, 59.9996, 60,
168                 "2008-02-29T23:59:59.99960000000000+00:00",
169                 "2008-03-01T00:00:00.000+00:00",
170                 "2008-03-01T00:00:00+00:00");
171         // check a leap second
172         check(2015, 6, 30, 23, 59, 59.999999, 61,
173                 "2015-06-30T23:59:59.99999900000000+00:00",
174                 "2015-06-30T23:59:60.000+00:00",
175                 "2015-06-30T23:59:60+00:00");
176         check(2015, 6, 30, 23, 59, 60.5, 61,
177                 "2015-06-30T23:59:60.50000000000000+00:00",
178                 "2015-06-30T23:59:60.500+00:00",
179                 "2015-07-01T00:00:00+00:00");
180         // check a bigger leap second. First leap was 1.422818 s.
181         // TODO can't run this test because of #707
182         //check(1960, 12, 31, 23, 59, 61.42281, 62,
183         //        "1960-12-31T23:59:61.42281000000000+00:00",
184         //        "1960-12-31T23:59:61.42300000000000+00:00", // TODO this date is invalid
185         //        "1961-01-01T00:00:00+00:00");
186     }
187 
188     private void check(int year, int month, int day, int hour, int minute, double second,
189                        int minuteDuration, String full, String medium, String shor) {
190         DateTimeComponents dtc =
191                 new DateTimeComponents(year, month, day, hour, minute, second);
192         MatcherAssert.assertThat(dtc.toString(minuteDuration), CoreMatchers.is(medium));
193         MatcherAssert.assertThat(dtc.toString(minuteDuration, 3), CoreMatchers.is(medium));
194         MatcherAssert.assertThat(dtc.toString(minuteDuration, 0), CoreMatchers.is(shor));
195         MatcherAssert.assertThat(dtc.toString(minuteDuration, 14), CoreMatchers.is(full));
196     }
197 
198     @Test
199     public void testToStringRoundingUtcOffset() {
200         DateTimeComponents dtc =
201                 new DateTimeComponents(new DateComponents(2000, 12, 31), new TimeComponents(23, 59, 59.9, -92));
202         MatcherAssert.assertThat(dtc.toString(60), CoreMatchers.is("2000-12-31T23:59:59.900-01:32"));
203         MatcherAssert.assertThat(dtc.toString(60, 3), CoreMatchers.is("2000-12-31T23:59:59.900-01:32"));
204         MatcherAssert.assertThat(dtc.toString(60, 0), CoreMatchers.is("2001-01-01T00:00:00-01:32"));
205         MatcherAssert.assertThat(dtc.toString(60, 14), CoreMatchers.is("2000-12-31T23:59:59.90000000000000-01:32"));
206     }
207 
208     @Test
209     public void testToStringWithoutUtcOffsetRoundingUtcOffset() {
210         DateTimeComponents dtc =
211                 new DateTimeComponents(new DateComponents(2000, 12, 31), new TimeComponents(23, 59, 59.9, -92));
212         MatcherAssert.assertThat(dtc.toStringWithoutUtcOffset(60, 3), CoreMatchers.is("2000-12-31T23:59:59.900"));
213         MatcherAssert.assertThat(dtc.toStringWithoutUtcOffset(60, 0), CoreMatchers.is("2001-01-01T00:00:00"));
214         MatcherAssert.assertThat(dtc.toStringWithoutUtcOffset(60, 14), CoreMatchers.is("2000-12-31T23:59:59.90000000000000"));
215     }
216 
217 }