1   package org.orekit.files.iirv;
2   
3   import org.junit.jupiter.api.Assertions;
4   import org.junit.jupiter.api.BeforeEach;
5   import org.junit.jupiter.api.Test;
6   import org.orekit.Utils;
7   import org.orekit.annotation.DefaultDataContext;
8   import org.orekit.errors.OrekitIllegalArgumentException;
9   import org.orekit.files.iirv.terms.DayOfYearTerm;
10  import org.orekit.files.iirv.terms.VectorEpochTerm;
11  import org.orekit.time.AbsoluteDate;
12  import org.orekit.time.DateComponents;
13  import org.orekit.time.TimeComponents;
14  import org.orekit.time.TimeScalesFactory;
15  import org.orekit.time.UTCScale;
16  
17  import java.time.Duration;
18  import java.time.Instant;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertThrows;
22  
23  /**
24   * Tests how time variables are handled in IIRV terms
25   */
26  public class IIRVTimeTest {
27      private static UTCScale UTC;
28  
29      /** Sample TimeComponents object to use in tests */
30      private final TimeComponents testTimeComponents = new TimeComponents(17, 1, 22.231);
31  
32      @BeforeEach
33      public void setUp() {
34          // Sets the root of data to read
35          Utils.setDataRoot("regular-data");
36          UTC = TimeScalesFactory.getUTC();
37      }
38  
39      /**
40       * Test initialization of {@link DayOfYearTerm}
41       */
42      @Test
43      @DefaultDataContext
44      void testDayOfYearTerm() {
45          final UTCScale utc = TimeScalesFactory.getUTC();
46  
47          int testDayOfYearAfterLeapDay = 344; // Day of year that occurs after leap day for tests: 344 (Dec. 9, 2024 )
48          int year = 2024;  // Use 2024 as the year in all tests
49  
50          DayOfYearTerm doyTerm = new DayOfYearTerm(testDayOfYearAfterLeapDay);
51          AbsoluteDate absoluteDate4 = new AbsoluteDate(year, 12, 9, utc);
52  
53          // Check the initialized terms are what we expect
54          Assertions.assertEquals(doyTerm, new DayOfYearTerm(absoluteDate4, UTC)); // Constructed from AbsoluteDate
55          Assertions.assertEquals(doyTerm, new DayOfYearTerm("344"));// Constructed from String
56  
57          // Check leap year Dec. 31
58          DayOfYearTerm dayOfYearTermAfterLeapDay = new DayOfYearTerm("366");
59          DateComponents dec31LeapYear = dayOfYearTermAfterLeapDay.getDateComponents(2024);
60          assertEquals(31, dec31LeapYear.getDay());
61          assertEquals(12, dec31LeapYear.getMonth());
62          assertEquals(366, dec31LeapYear.getDayOfYear());
63  
64          // Check date components throw error for a leap year (366 days)
65          assertThrows(OrekitIllegalArgumentException.class,
66              () -> new DayOfYearTerm("366").getDateComponents(2023)
67          );
68  
69          // Check rejected outside date range
70          assertThrows(OrekitIllegalArgumentException.class,
71              () -> new DayOfYearTerm("377").getDateComponents(2023));
72  
73          // Check rejected double value
74          assertThrows(OrekitIllegalArgumentException.class,
75              () -> new DayOfYearTerm("2.2")); // reject double value
76  
77      }
78  
79      @Test
80      @DefaultDataContext
81      void testVectorEpochTerm() {
82  
83          // Construct from TimeComponents
84          final VectorEpochTerm vectorEpoch = new VectorEpochTerm(testTimeComponents);
85  
86          // Construct from String
87          VectorEpochTerm vectorEpochFromStr = new VectorEpochTerm(vectorEpoch.toEncodedString());
88  
89          // Construct from AbsoluteDate
90          AbsoluteDate absoluteDate = new AbsoluteDate(
91              DateComponents.J2000_EPOCH,
92              testTimeComponents,
93              TimeScalesFactory.getUTC()
94          );
95          VectorEpochTerm vectorEpochFromAbsoluteDate = new VectorEpochTerm(absoluteDate, UTC);
96  
97          Assertions.assertEquals(vectorEpoch, vectorEpochFromStr);
98          Assertions.assertEquals(vectorEpoch, vectorEpochFromAbsoluteDate);
99          Assertions.assertEquals("170122231", vectorEpoch.toEncodedString());
100         Assertions.assertEquals("17", vectorEpoch.hh());
101         Assertions.assertEquals("01", vectorEpoch.mm());
102         Assertions.assertEquals("22", vectorEpoch.ss());
103 
104         Assertions.assertEquals(vectorEpoch.toEncodedString(), vectorEpochFromStr.toEncodedString()); // Check consistency
105     }
106 
107 
108     @Test
109     void testTimeRounding() {
110         // Millisecond rounding: 17:01:22.231 -> 17:01:22.232 (up) / 17:01:22.231 (down)
111         final VectorEpochTerm vectorEpochMillisecond = new VectorEpochTerm(testTimeComponents);
112         verifyRoundUpAndDown(vectorEpochMillisecond, "170122231", "170122232");
113 
114         // Second rounding: 17:01:22.999 -> 17:01:23.000 (up) / 17:01:22.999 (down)
115         final VectorEpochTerm vectorEpochSecond = new VectorEpochTerm("170102999");
116         verifyRoundUpAndDown(vectorEpochSecond, "170102999", "170103000");
117 
118         // Minute rounding: 17:01:59.999 -> 17:02:00.000 (up) / 17:01:59.999 (down)
119         final VectorEpochTerm vectorEpochMinute = new VectorEpochTerm("170159999");
120         verifyRoundUpAndDown(vectorEpochMinute, "170159999", "170200000");
121 
122         // Hour rounding: 17:59:59.999 -> 18:00:00.000 (up) / 17:59:59.999 (down)
123         final VectorEpochTerm vectorEpochHour = new VectorEpochTerm("175959999");
124         verifyRoundUpAndDown(vectorEpochHour, "175959999", "180000000");
125 
126         // Test day rounding: 23:59:59.999 -> 00:00:00.000 (up) / 23:59:59.999 (down)
127         final VectorEpochTerm vectorEpochDay = new VectorEpochTerm("235959999");
128         verifyRoundUpAndDown(vectorEpochDay, "235959999", "000000000");
129     }
130 
131     private void verifyRoundUpAndDown(final VectorEpochTerm originalVectorEpoch,
132                                       final String roundedDown,
133                                       final String roundedUp) {
134         AbsoluteDate absoluteDate = new AbsoluteDate(
135             DateComponents.J2000_EPOCH, // arbitrary date
136             originalVectorEpoch.value(),
137             TimeScalesFactory.getUTC());
138         Instant instant = absoluteDate.toInstant(TimeScalesFactory.getTimeScales());
139 
140         // Check rounding down
141         AbsoluteDate absoluteDateRoundDown = new AbsoluteDate(instant.plus(Duration.ofNanos(400000)));
142         VectorEpochTerm epochRoundDown = new VectorEpochTerm(absoluteDateRoundDown, UTC);
143         VectorEpochTerm epochRoundDownExpected = new VectorEpochTerm(roundedDown);
144         Assertions.assertEquals(epochRoundDownExpected, epochRoundDown);
145         Assertions.assertEquals(epochRoundDownExpected, originalVectorEpoch);
146 
147         // Check rounding up
148         AbsoluteDate absoluteDateRoundUp = new AbsoluteDate(instant.plus(Duration.ofNanos(600000)));
149         VectorEpochTerm epochRoundUp = new VectorEpochTerm(absoluteDateRoundUp, UTC);
150         VectorEpochTerm epochRoundUpExpected = new VectorEpochTerm(roundedUp);
151         Assertions.assertEquals(epochRoundUpExpected, epochRoundUp);
152 
153     }
154 
155 }