1   /* Copyright 2002-2025 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  import org.junit.jupiter.api.Assertions;
20  import org.junit.jupiter.api.Test;
21  import org.orekit.Utils;
22  import org.orekit.errors.OrekitException;
23  import org.orekit.errors.OrekitMessages;
24  
25  public class UTCTAIBulletinAFilesLoaderTest {
26  
27      @Test
28      public void test2006Leap() {
29          Utils.setDataRoot("bulletinA");
30          // this file contains a single leap second on 2006-01-01, from 32s to 33s
31          TimeScalesFactory.addUTCTAIOffsetsLoader(new UTCTAIBulletinAFilesLoader("bulletina-xix-001\\.txt$"));
32  
33          UTCScale utc = TimeScalesFactory.getUTC();
34          AbsoluteDate afterLeap = new AbsoluteDate(1961, 1, 1, 0, 0, 0.0, utc);
35          Assertions.assertEquals(1.4228180,
36                              afterLeap.durationFrom(utc.getFirstKnownLeapSecond()),
37                              1.0e-12);
38          afterLeap = new AbsoluteDate(2006, 1, 1, 0, 0, 0.0, utc);
39          Assertions.assertEquals(1.0,
40                              afterLeap.durationFrom(utc.getLastKnownLeapSecond()),
41                              1.0e-12);
42  
43          // correct values, as the single leap second is close enough
44          checkOffset("2000-01-01", -32.0);
45          checkOffset("2008-01-01", -33.0);
46  
47          // expected wrong estimation as the leap seconds from 1997-01-01 and 1999-01-01 are not known from the file read
48          checkOffset("1996-04-03", -32.0);
49  
50          // expected wrong estimation as the leap seconds from 2009-01-01 and 2012-07-01 are not known from the file read
51          checkOffset("2013-01-22", -33.0);
52  
53      }
54  
55      @Test
56      public void test2009WrongLeap() {
57          Utils.setDataRoot("bulletinA");
58          // this file contains a single leap second on 2009-01-01, from 33s to 34s,
59          // but it has a known ERROR in it, as line 66 reads:
60          //    TAI-UTC(MJD 54832) = 33.0
61          // whereas the value should be 34.0, as the leap second was introduced
62          // just before this day
63          TimeScalesFactory.addUTCTAIOffsetsLoader(new UTCTAIBulletinAFilesLoader("bulletina-xxi-053-original\\.txt$"));
64  
65          UTCScale utc = TimeScalesFactory.getUTC();
66          AbsoluteDate afterLeap = new AbsoluteDate(1961, 1, 1, 0, 0, 0.0, utc);
67          Assertions.assertEquals(1.4228180,
68                              afterLeap.durationFrom(utc.getFirstKnownLeapSecond()),
69                              1.0e-12);
70          afterLeap = new AbsoluteDate(2009, 1, 1, 0, 0, 0.0, utc);
71          Assertions.assertEquals(1.0,
72                              afterLeap.durationFrom(utc.getLastKnownLeapSecond()),
73                              1.0e-12);
74  
75          // expected incorrect values, as the file contains an error
76          checkOffset("2008-01-01", -32.0); // the real value should be -33.0
77          checkOffset("2009-06-30", -33.0); // the real value should be -34.0
78  
79      }
80  
81      @Test
82      public void test2009FixedLeap() {
83          Utils.setDataRoot("bulletinA");
84          // this file is a fixed version of IERS bulletin
85          TimeScalesFactory.addUTCTAIOffsetsLoader(new UTCTAIBulletinAFilesLoader("bulletina-xxi-053-fixed\\.txt$"));
86  
87          UTCScale utc = TimeScalesFactory.getUTC();
88          AbsoluteDate afterLeap = new AbsoluteDate(1961, 1, 1, 0, 0, 0.0, utc);
89          Assertions.assertEquals(1.4228180,
90                              afterLeap.durationFrom(utc.getFirstKnownLeapSecond()),
91                              1.0e-12);
92          afterLeap = new AbsoluteDate(2009, 1, 1, 0, 0, 0.0, utc);
93          Assertions.assertEquals(1.0,
94                              afterLeap.durationFrom(utc.getLastKnownLeapSecond()),
95                              1.0e-12);
96  
97          // correct values, as the original file error has been fixed
98          checkOffset("2008-01-01", -33.0);
99          checkOffset("2009-06-30", -34.0);
100 
101     }
102 
103     @Test
104     public void testNoLeap() {
105         Utils.setDataRoot("bulletinA");
106         // these files contains no leap seconds
107         TimeScalesFactory.addUTCTAIOffsetsLoader(new UTCTAIBulletinAFilesLoader("bulletina-xxvi.*\\.txt$"));
108 
109         UTCScale utc = TimeScalesFactory.getUTC();
110         AbsoluteDate afterLeap = new AbsoluteDate(1961, 1, 1, 0, 0, 0.0, utc);
111         Assertions.assertEquals(1.4228180,
112                             afterLeap.durationFrom(utc.getFirstKnownLeapSecond()),
113                             1.0e-12);
114 
115         // the artificial first leap is big ...
116         afterLeap = new AbsoluteDate(1972, 1, 1, 0, 0, 0.0, utc);
117         Assertions.assertTrue(afterLeap.durationFrom(utc.getLastKnownLeapSecond()) > 25.1);
118 
119         // as there are no leap seconds identified, everything should be at 35s
120         checkOffset("1973-01-01", -35.0);
121         checkOffset("2000-01-01", -35.0);
122         checkOffset("2002-01-01", -35.0);
123         checkOffset("2004-01-01", -35.0);
124         checkOffset("2006-01-01", -35.0);
125         checkOffset("2008-01-01", -35.0);
126         checkOffset("2010-01-01", -35.0);
127         checkOffset("2012-01-01", -35.0);
128         checkOffset("2014-01-01", -35.0);
129         checkOffset("2100-01-01", -35.0);
130 
131     }
132 
133     @Test
134     public void testMissingTimeSteps() {
135         checkException("bulletina-(?:xix|xxii)-001\\.txt",
136                        OrekitMessages.MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES);
137     }
138 
139     @Test
140     public void testMissingRapidSections() {
141         checkException("bulletina-missing-eop-rapid-service.txt",
142                        OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE);
143         checkException("bulletina-missing-eop-rapid-service.txt",
144                        OrekitMessages.NOT_A_SUPPORTED_IERS_DATA_FILE);
145     }
146 
147     @Test
148     public void testMissingData() {
149         checkException("bulletina-truncated-in-prediction-header.txt",
150                        OrekitMessages.UNEXPECTED_END_OF_FILE_AFTER_LINE);
151         checkException("bulletina-truncated-after-prediction-header.txt",
152                        OrekitMessages.UNEXPECTED_END_OF_FILE_AFTER_LINE);
153     }
154 
155     @Test
156     public void testInconsistentDate() {
157         checkException("bulletina-inconsistent-year.txt", OrekitMessages.INCONSISTENT_DATES_IN_IERS_FILE);
158         checkException("bulletina-inconsistent-month.txt", OrekitMessages.INCONSISTENT_DATES_IN_IERS_FILE);
159         checkException("bulletina-inconsistent-day.txt", OrekitMessages.INCONSISTENT_DATES_IN_IERS_FILE);
160     }
161 
162     private void checkOffset(final String s, final double expected) {
163         final AbsoluteDate date = new AbsoluteDate(s, TimeScalesFactory.getTAI());
164         Assertions.assertEquals(expected, TimeScalesFactory.getUTC().offsetFromTAI(date).toDouble(), 10e-8);
165     }
166 
167     private void checkException(String name, OrekitMessages message) {
168         Utils.setDataRoot("bulletinA");
169         TimeScalesFactory.addUTCTAIOffsetsLoader(new UTCTAIBulletinAFilesLoader(name));
170         try {
171             TimeScalesFactory.getUTC();
172             Assertions.fail("an exception should have been thrown");
173         } catch (OrekitException oe) {
174             Assertions.assertEquals(message, oe.getSpecifier());
175         }
176     }
177 
178 }