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.hipparchus.util.FastMath;
20 import org.orekit.annotation.DefaultDataContext;
21 import org.orekit.data.DataContext;
22 import org.orekit.propagation.analytical.gnss.data.GNSSConstants;
23 import org.orekit.utils.Constants;
24
25 /**
26 * Container for date in GLONASS form.
27 * @author Bryan Cazabonne
28 * @see AbsoluteDate
29 * @see "GLONASS Interface Control Document v1.0, 2016"
30 * @since 10.0
31 */
32 public class GLONASSDate implements TimeStamped {
33
34 /** Constant for date computation. */
35 private static final int C1 = 44195;
36
37 /** Constant for date computation. */
38 private static final int C2 = 45290;
39
40 /** The number of the current day in a four year interval N<sub>a</sub>. */
41 private final int na;
42
43 /** The number of the current four year interval N<sub>4</sub>. */
44 private final int n4;
45
46 /** Number of seconds since N<sub>a</sub>. */
47 private final double secInNa;
48
49 /** Current Julian date JD0. */
50 private final double jd0;
51
52 /** Greenwich Mean Sidereal Time (rad). */
53 private final double gmst;
54
55 /** Corresponding date. */
56 private final AbsoluteDate date;
57
58 /** Build an instance corresponding to a GLONASS date.
59 *
60 * <p>This method uses the {@link DataContext#getDefault() default data context}.
61 *
62 * @param na the number of the current day in a four year interval
63 * @param n4 the number of the current four year interval
64 * @param secInNa the number of seconds since na start
65 * @see #GLONASSDate(int, int, double, TimeScale)
66 */
67 @DefaultDataContext
68 public GLONASSDate(final int na, final int n4, final double secInNa) {
69 this(na, n4, secInNa, DataContext.getDefault().getTimeScales().getGLONASS());
70 }
71
72 /**
73 * Build an instance corresponding to a GLONASS date.
74 *
75 * @param na the number of the current day in a four year interval
76 * @param n4 the number of the current four year interval
77 * @param secInNa the number of seconds since na start
78 * @param glonass time scale.
79 * @since 10.1
80 */
81 public GLONASSDate(final int na,
82 final int n4,
83 final double secInNa,
84 final TimeScale glonass) {
85 this.na = na;
86 this.n4 = n4;
87 this.secInNa = secInNa;
88 // Compute JD0
89 final int ratio = FastMath.round((float) (na - 3) / (25 + C1 + C2));
90 this.jd0 = 1461 * (n4 - 1) + na + 2450082.5 - ratio;
91 // GMST
92 this.gmst = computeGMST();
93 this.date = computeDate(glonass);
94 }
95
96 /** Build an instance from an absolute date.
97 *
98 * <p>This method uses the {@link DataContext#getDefault() default data context}.
99 *
100 * @param date absolute date to consider
101 * @see #GLONASSDate(AbsoluteDate, TimeScale)
102 */
103 @DefaultDataContext
104 public GLONASSDate(final AbsoluteDate date) {
105 this(date, DataContext.getDefault().getTimeScales().getGLONASS());
106 }
107
108 /**
109 * Build an instance from an absolute date.
110 *
111 * @param date absolute date to consider
112 * @param glonass time scale.
113 * @since 10.1
114 */
115 public GLONASSDate(final AbsoluteDate date, final TimeScale glonass) {
116 final DateTimeComponents dateTime = date.getComponents(glonass);
117 // N4
118 final int year = dateTime.getDate().getYear();
119 this.n4 = ((int) (year - 1996) / 4) + 1;
120 // Na
121 final int start = 1996 + 4 * (n4 - 1);
122 final double duration = date.durationFrom(new AbsoluteDate(start, 1, 1, glonass));
123 this.na = (int) (duration / 86400) + 1;
124 this.secInNa = dateTime.getTime().getSecondsInLocalDay();
125 // Compute JD0
126 final int ratio = FastMath.round((float) (na - 3) / (25 + C1 + C2));
127 this.jd0 = 1461 * (n4 - 1) + na + 2450082.5 - ratio;
128 // GMST
129 this.gmst = computeGMST();
130 this.date = date;
131 }
132
133 @Override
134 public AbsoluteDate getDate() {
135 return date;
136 }
137
138 /** Get the number of seconds since N<sub>a</sub> start.
139 * @return number of seconds since N<sub>a</sub> start
140 */
141 public double getSecInDay() {
142 return secInNa;
143 }
144
145 /** Get the number of the current day in a four year interval.
146 * @return the number of the current day in a four year interval
147 */
148 public int getDayNumber() {
149 return na;
150 }
151
152 /** Get the number of the current four year interval.
153 * @return the number of the current four year interval
154 */
155 public int getIntervalNumber() {
156 return n4;
157 }
158
159 /** Get the current Julian date JD0.
160 * @return the current date JD0
161 */
162 public double getJD0() {
163 return jd0;
164 }
165
166 /** Get the Greenwich Mean Sidereal Time.
167 * @return the Greenwich Mean Sidereal Time (rad)
168 */
169 public double getGMST() {
170 return gmst;
171 }
172
173 /** Compute the Greenwich Mean Sidereal Time using the current Julian date JD0.
174 * @return the Greenwich Mean Sidereal Time (rad)
175 */
176 private double computeGMST() {
177 final double ref = 2451545.0;
178 // Earth's rotation angle in radians
179 final double era = 2. * GNSSConstants.GLONASS_PI *
180 (0.7790572732640 + 1.00273781191135448 * (jd0 - ref));
181 // Time from Epoch 2000 (1st January, 00:00 UTC) till current Epoch in Julian centuries
182 final double time = (jd0 - ref) / Constants.JULIAN_CENTURY;
183 // Time to the power n
184 final double time2 = time * time;
185 final double time3 = time2 * time;
186 final double time4 = time2 * time2;
187 final double time5 = time2 * time3;
188 // GMST computation
189 final double gTime = era + 7.03270726e-8 + time * 2.23603658710194e-2 +
190 time2 * 6.7465784654e-6 - time3 * 2.1332e-12 - time4 * 1.452308e-10 - time5 * 1.784e-13;
191 return gTime;
192 }
193
194 /** Compute the GLONASS date.
195 * @return the date
196 * @param glonass time scale.
197 */
198 private AbsoluteDate computeDate(final TimeScale glonass) {
199 // Compute the number of Julian day for the current date
200 final double jdn = jd0 + 0.5;
201 // Coefficients
202 final int a = (int) (jdn + 32044);
203 final int b = (4 * a + 3) / 146097;
204 final int c = a - (146097 * b) / 4;
205 final int d = (4 * c + 3) / 1461;
206 final int e = c - (1461 * d) / 4;
207 final int m = (5 * e + 2) / 153;
208 // Year, month and day
209 final int day = e - (153 * m + 2) / 5 + 1;
210 final int month = m + 3 - 12 * (m / 10);
211 final int year = 100 * b + d - 4800 + m / 10;
212 return new AbsoluteDate(new DateComponents(year, month, day),
213 new TimeComponents(secInNa),
214 glonass);
215 }
216
217 }