1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.time;
18
19 import java.time.Instant;
20 import java.time.OffsetDateTime;
21 import java.time.format.DateTimeFormatter;
22 import java.util.Date;
23 import java.util.TimeZone;
24
25 import java.util.concurrent.TimeUnit;
26 import org.hamcrest.CoreMatchers;
27 import org.hamcrest.MatcherAssert;
28 import org.hipparchus.CalculusFieldElement;
29 import org.hipparchus.Field;
30 import org.hipparchus.analysis.differentiation.*;
31 import org.hipparchus.complex.Complex;
32 import org.hipparchus.complex.ComplexField;
33 import org.hipparchus.complex.FieldComplex;
34 import org.hipparchus.complex.FieldComplexField;
35 import org.hipparchus.dfp.Dfp;
36 import org.hipparchus.dfp.DfpField;
37 import org.hipparchus.util.Binary64;
38 import org.hipparchus.util.Binary64Field;
39 import org.hipparchus.util.FastMath;
40 import org.hipparchus.util.FieldTuple;
41 import org.hipparchus.util.Precision;
42 import org.hipparchus.util.Tuple;
43 import org.junit.jupiter.api.Assertions;
44 import org.junit.jupiter.api.BeforeEach;
45 import org.junit.jupiter.api.Test;
46 import org.orekit.OrekitMatchers;
47 import org.orekit.Utils;
48 import org.orekit.errors.OrekitException;
49 import org.orekit.errors.OrekitIllegalArgumentException;
50 import org.orekit.errors.OrekitMessages;
51 import org.orekit.utils.Constants;
52
53 class FieldAbsoluteDateTest {
54
55 private TimeScale utc;
56
57 @BeforeEach
58 public void setUp() {
59 Utils.setDataRoot("regular-data");
60 utc = TimeScalesFactory.getUTC();
61 }
62
63 @Test
64 void testStandardEpoch() {
65 doTestStandardEpoch(Binary64Field.getInstance());
66 }
67
68 @Test
69 void testStandardEpochStrings() {
70 doTestStandardEpochStrings(Binary64Field.getInstance());
71 }
72
73 @Test
74 void testJulianEpochRate() {
75 doTestJulianEpochRate(Binary64Field.getInstance());
76 }
77
78 @Test
79 void testBesselianEpochRate() {
80 doTestBesselianEpochRate(Binary64Field.getInstance());
81 }
82
83 @Test
84 void testLieske() {
85 doTestLieske(Binary64Field.getInstance());
86 }
87
88 @Test
89 void testParse() {
90 doTestParse(Binary64Field.getInstance());
91 }
92
93 @Test
94 void testLocalTimeParsing() {
95 doTestLocalTimeParsing(Binary64Field.getInstance());
96 }
97
98 @Test
99 void testTimeZoneDisplay() {
100 doTestTimeZoneDisplay(Binary64Field.getInstance());
101 }
102
103 @Test
104 void testLocalTimeLeapSecond() {
105 doTestLocalTimeLeapSecond(Binary64Field.getInstance());
106 }
107
108 @Test
109 void testTimeZoneLeapSecond() {
110 doTestTimeZoneLeapSecond(Binary64Field.getInstance());
111 }
112
113 @Test
114 void testParseLeap() {
115 doTestParseLeap(Binary64Field.getInstance());
116 }
117
118 @Test
119 void testOutput() {
120 doTestOutput(Binary64Field.getInstance());
121 }
122
123 @Test
124 void testJ2000() {
125 doTestJ2000(Binary64Field.getInstance());
126 }
127
128 @Test
129 void testFraction() {
130 doTestFraction(Binary64Field.getInstance());
131 }
132
133 @Test
134 void testScalesOffset() {
135 doTestScalesOffset(Binary64Field.getInstance());
136 }
137
138 @Test
139 void testUTC() {
140 doTestUTC(Binary64Field.getInstance());
141 }
142
143 @Test
144 void test1970() {
145 doTest1970(Binary64Field.getInstance());
146 }
147
148 @Test
149 void test1970Instant() {
150 doTest1970Instant(Binary64Field.getInstance());
151 }
152
153 @Test
154 void testInstantAccuracy() {
155 doTestInstantAccuracy(Binary64Field.getInstance());
156 }
157
158 @Test
159 void testToInstant() {
160 doTestToInstant(Binary64Field.getInstance());
161 }
162
163
164 @Test
165 void testUtcGpsOffset() {
166 doTestUtcGpsOffset(Binary64Field.getInstance());
167 }
168
169 @Test
170 void testGpsDate() {
171 doTestGpsDate(Binary64Field.getInstance());
172 }
173
174 @Test
175 void testMJDDate() {
176 doTestMJDDate(Binary64Field.getInstance());
177 }
178
179 @Test
180 void testJDDate() {
181 doTestJDDate(Binary64Field.getInstance());
182 }
183
184
185 @Test
186 void testIssue1310JDDateInTDB() {
187
188
189
190 final Field<Binary64> field = Binary64Field.getInstance();
191
192 final TDBScale TDBscale = TimeScalesFactory.getTDB();
193 final FieldAbsoluteDate<Binary64> refDate = new FieldAbsoluteDate<>(field,
194 new AbsoluteDate("2023-08-01T00:00:00.000", TDBscale));
195
196
197
198 final FieldAbsoluteDate<Binary64> wrongDate = FieldAbsoluteDate.createJDDate(2460157,
199 field.getOne().multiply(Constants.JULIAN_DAY / 2.0d), TDBscale);
200 final FieldAbsoluteDate<Binary64> properDate = FieldAbsoluteDate.createJDDate(2460157,
201 field.getOne().multiply(Constants.JULIAN_DAY / 2.0d), TDBscale, TimeScalesFactory.getTT());
202
203
204
205
206
207 Assertions.assertEquals(0.0, wrongDate.durationFrom(refDate).getReal(), 1.270e-05);
208
209
210 Assertions.assertEquals(0.0, properDate.durationFrom(refDate).getReal(), 2.132e-13);
211 }
212
213 @Test
214 void testOffsets() {
215 doTestOffsets(Binary64Field.getInstance());
216 }
217
218 @Test
219 void testBeforeAndAfterLeap() {
220 doTestBeforeAndAfterLeap(Binary64Field.getInstance());
221 }
222
223 @Test
224 void testSymmetry() {
225 doTestSymmetry(Binary64Field.getInstance());
226 }
227
228 @Test
229 void testEquals() {
230 doTestEquals(Binary64Field.getInstance());
231 }
232
233 @Test
234 void testIsEqualTo() { doTestIsEqualTo(Binary64Field.getInstance()); }
235
236 @Test
237 void testIsCloseTo() { doTestIsCloseTo(Binary64Field.getInstance()); }
238
239 @Test
240 void testIsBefore() { doTestIsBefore(Binary64Field.getInstance()); }
241
242 @Test
243 void testIsAfter() { doTestIsAfter(Binary64Field.getInstance()); }
244
245 @Test
246 void testIsBeforeOrEqualTo() { doTestIsBeforeOrEqualTo(Binary64Field.getInstance()); }
247
248 @Test
249 void testIsAfterOrEqualTo() { doTestIsAfterOrEqualTo(Binary64Field.getInstance()); }
250
251 @Test
252 void testIsBetween() { doTestIsBetween(Binary64Field.getInstance()); }
253
254 @Test
255 void testIsBetweenOrEqualTo() { doTestIsBetweenOrEqualTo(Binary64Field.getInstance()); }
256
257 @Test
258 void testComponents() {
259 doTestComponents(Binary64Field.getInstance());
260 }
261
262 @Test
263 void testMonth() {
264 doTestMonth(Binary64Field.getInstance());
265 }
266
267 @Test
268 void testCCSDSUnsegmentedNoExtension() {
269 doTestCCSDSUnsegmentedNoExtension(Binary64Field.getInstance());
270 }
271
272 @Test
273 void testCCSDSUnsegmentedWithExtendedPreamble() {
274 doTestCCSDSUnsegmentedWithExtendedPreamble(Binary64Field.getInstance());
275 }
276
277 @Test
278 void testCCSDSDaySegmented() {
279 doTestCCSDSDaySegmented(Binary64Field.getInstance());
280 }
281
282 @Test
283 void testCCSDSCalendarSegmented() {
284 doTestCCSDSCalendarSegmented(Binary64Field.getInstance());
285 }
286
287 @Test
288 void testExpandedConstructors() {
289 doTestExpandedConstructors(Binary64Field.getInstance());
290 }
291
292 @Test
293 void testHashcode() {
294 doTestHashcode(Binary64Field.getInstance());
295 }
296
297 @Test
298 void testInfinity() {
299 doTestInfinity(Binary64Field.getInstance());
300 }
301
302 @Test
303 void testAccuracy() {
304 doTestAccuracy(Binary64Field.getInstance());
305 }
306
307 @Test
308 void testAccuracyIssue348() {
309 doTestAccuracyIssue348(Binary64Field.getInstance());
310 }
311
312 @Test
313 void testIterationAccuracy() {
314 doTestIterationAccuracy(Binary64Field.getInstance());
315 }
316
317 @Test
318 void testIssue142() {
319 doTestIssue142(Binary64Field.getInstance());
320 }
321
322 @Test
323 void testIssue148() {
324 doTestIssue148(Binary64Field.getInstance());
325 }
326
327 @Test
328 void testIssue149() {
329 doTestIssue149(Binary64Field.getInstance());
330 }
331
332 @Test
333 void testWrapAtMinuteEnd() {
334 doTestWrapAtMinuteEnd(Binary64Field.getInstance());
335 }
336
337 @Test
338 void testIssue508() {
339 doTestIssue508(Binary64Field.getInstance());
340 }
341
342 @Test
343 void testGetComponentsIssue681and676and694() {
344 doTestGetComponentsIssue681and676and694(Binary64Field.getInstance());
345 }
346
347 @Test
348 void testNegativeOffsetConstructor() {
349 doTestNegativeOffsetConstructor(Binary64Field.getInstance());
350 }
351
352 @Test
353 void testNegativeOffsetShift() {
354 doTestNegativeOffsetShift(Binary64Field.getInstance());
355 }
356
357 @Test
358 void testGetDayOfYear() {
359 doTestGetDayOfYear(Binary64Field.getInstance());
360 }
361
362 @Test
363 void testHasZeroField() {
364
365
366
367
368 final DSFactory dsFactory = new DSFactory(3, 2);
369 final Field<DerivativeStructure> dsField = dsFactory.getDerivativeField();
370
371
372 final FieldAbsoluteDate<DerivativeStructure> dsConstantDate = new FieldAbsoluteDate<>(dsField);
373 Assertions.assertTrue(dsConstantDate.hasZeroField());
374 Assertions.assertTrue(dsConstantDate.shiftedBy(dsField.getOne()).hasZeroField());
375
376
377 final DerivativeStructure dsDt0 = dsFactory.variable(0, 10.);
378 final DerivativeStructure dsDt1 = dsFactory.variable(1, -100.);
379 final DerivativeStructure dsDt2 = dsFactory.variable(2, 100.);
380 Assertions.assertFalse(dsConstantDate.shiftedBy(dsDt0).hasZeroField());
381 Assertions.assertFalse(dsConstantDate.shiftedBy(dsDt1).hasZeroField());
382 Assertions.assertFalse(dsConstantDate.shiftedBy(dsDt2).hasZeroField());
383 Assertions.assertFalse(dsConstantDate.shiftedBy(dsDt0).shiftedBy(dsDt1).shiftedBy(dsDt2).hasZeroField());
384
385
386
387
388 final Field<UnivariateDerivative1> u1Field = UnivariateDerivative1Field.getInstance();
389
390
391 final FieldAbsoluteDate<UnivariateDerivative1> u1ConstantDate = new FieldAbsoluteDate<>(u1Field);
392 Assertions.assertTrue(u1ConstantDate.hasZeroField());
393 Assertions.assertTrue(u1ConstantDate.shiftedBy(u1Field.getOne()).hasZeroField());
394 Assertions.assertTrue(u1ConstantDate.shiftedBy(new UnivariateDerivative1(10., 0.)).hasZeroField());
395
396
397 Assertions.assertFalse(u1ConstantDate.shiftedBy(new UnivariateDerivative1(10., 10.)).hasZeroField());
398
399
400
401
402 final Field<UnivariateDerivative2> u2Field = UnivariateDerivative2Field.getInstance();
403
404
405 final FieldAbsoluteDate<UnivariateDerivative2> u2ConstantDate = new FieldAbsoluteDate<>(u2Field);
406 Assertions.assertTrue(u2ConstantDate.hasZeroField());
407 Assertions.assertTrue(u2ConstantDate.shiftedBy(u2Field.getOne()).hasZeroField());
408 Assertions.assertTrue(u2ConstantDate.shiftedBy(new UnivariateDerivative2(10., 0., 0.)).hasZeroField());
409
410
411 Assertions.assertFalse(u2ConstantDate.shiftedBy(new UnivariateDerivative2(10., 1., 2.)).hasZeroField());
412
413
414
415
416 final Field<Gradient> gdField = GradientField.getField(2);
417
418
419 final FieldAbsoluteDate<Gradient> gdConstantDate = new FieldAbsoluteDate<>(gdField);
420 Assertions.assertTrue(gdConstantDate.hasZeroField());
421
422
423 final Gradient gdDt0 = Gradient.variable(2, 0, 10.);
424 final Gradient gdDt1 = Gradient.variable(2, 1, -100.);
425 Assertions.assertFalse(gdConstantDate.shiftedBy(gdDt0).hasZeroField());
426 Assertions.assertFalse(gdConstantDate.shiftedBy(gdDt1).hasZeroField());
427 Assertions.assertFalse(gdConstantDate.shiftedBy(gdDt0).shiftedBy(gdDt1).hasZeroField());
428
429
430 final FieldAbsoluteDate<SparseGradient> sgdDate = new FieldAbsoluteDate<>(SparseGradient.createConstant(10.).getField());
431 Assertions.assertTrue(sgdDate.hasZeroField());
432
433
434
435
436 final Field<Complex> cxField = ComplexField.getInstance();
437
438
439 final FieldAbsoluteDate<Complex> cxConstantDate = new FieldAbsoluteDate<>(cxField);
440 Assertions.assertTrue(cxConstantDate.hasZeroField());
441
442 Assertions.assertTrue(cxConstantDate.shiftedBy(new Complex(10., 0.)).hasZeroField());
443
444
445 Assertions.assertFalse(cxConstantDate.shiftedBy(new Complex(-100., 10.)).hasZeroField());
446
447
448 final Binary64Field b64Field = Binary64Field.getInstance();
449 final FieldAbsoluteDate<Binary64> b64Date = new FieldAbsoluteDate<>(b64Field);
450 Assertions.assertTrue(b64Date.hasZeroField());
451
452
453 final FieldAbsoluteDate<Dfp> dfpDate = new FieldAbsoluteDate<>(new DfpField(10));
454 Assertions.assertTrue(dfpDate.hasZeroField());
455
456
457 final FieldAbsoluteDate<FieldComplex<Complex>> fcxDate = new FieldAbsoluteDate<>(FieldComplexField.getField(cxField));
458 Assertions.assertTrue(fcxDate.hasZeroField());
459
460
461 final FieldAbsoluteDate<FieldTuple<DerivativeStructure>> ftpDate = new FieldAbsoluteDate<>(new FieldTuple<>(dsDt0, dsDt1).getField());
462 Assertions.assertTrue(ftpDate.hasZeroField());
463
464
465 final FieldAbsoluteDate<Tuple> tpDate = new FieldAbsoluteDate<>(new Tuple(0., 1.).getField());
466 Assertions.assertTrue(tpDate.hasZeroField());
467
468
469 final FDSFactory<Binary64> fdsFactory = new FDSFactory<>(b64Field, 3, 1);
470 final FieldAbsoluteDate<FieldDerivativeStructure<Binary64>> fdsDate = new FieldAbsoluteDate<>(fdsFactory.constant(1.).getField());
471 Assertions.assertTrue(fdsDate.hasZeroField());
472
473
474 final FieldAbsoluteDate<FieldGradient<Binary64>> fgdDate =
475 new FieldAbsoluteDate<>(new FieldGradient<>(fdsFactory.constant(1.)).getField());
476 Assertions.assertTrue(fgdDate.hasZeroField());
477
478
479 final FieldAbsoluteDate<FieldUnivariateDerivative1<Binary64>> fu1Date = new FieldAbsoluteDate<>(
480 FieldUnivariateDerivative1Field.getUnivariateDerivative1Field(Binary64Field.getInstance()));
481 Assertions.assertTrue(fu1Date.hasZeroField());
482
483
484 final FieldAbsoluteDate<FieldUnivariateDerivative2<Binary64>> fu2Date = new FieldAbsoluteDate<>(
485 FieldUnivariateDerivative2Field.getUnivariateDerivative2Field(Binary64Field.getInstance()));
486 Assertions.assertTrue(fu2Date.hasZeroField());
487 }
488
489 @Test
490 void testDurationFromWithTimeUnit() {
491 doTestDurationFromWithTimeUnit(Binary64Field.getInstance());
492 }
493
494 @Test
495 void testConstructWithTimeUnitOffset() {
496 doTestConstructWithTimeUnitOffset(Binary64Field.getInstance());
497 }
498
499 @Test
500 void testShiftedByWithTimeUnit() {
501 doTestShiftedByWithTimeUnit(Binary64Field.getInstance());
502 }
503
504 @Test
505 void testToStringWithoutUtcOffset() {
506 doTestToStringWithoutUtcOffset(Binary64Field.getInstance());
507 }
508
509
510 private <T extends CalculusFieldElement<T>> void doTestStandardEpoch(final Field<T> field) {
511
512 TimeScale tai = TimeScalesFactory.getTAI();
513 TimeScale tt = TimeScalesFactory.getTT();
514
515 FieldAbsoluteDate<T> JuEp = FieldAbsoluteDate.getJulianEpoch(field);
516 FieldAbsoluteDate<T> MJuEp = FieldAbsoluteDate.getModifiedJulianEpoch(field);
517 FieldAbsoluteDate<T> FiEp = FieldAbsoluteDate.getFiftiesEpoch(field);
518 FieldAbsoluteDate<T> CCSDS = FieldAbsoluteDate.getCCSDSEpoch(field);
519 FieldAbsoluteDate<T> GaEp = FieldAbsoluteDate.getGalileoEpoch(field);
520 FieldAbsoluteDate<T> GPSEp = FieldAbsoluteDate.getGPSEpoch(field);
521 FieldAbsoluteDate<T> JTTEP = FieldAbsoluteDate.getJ2000Epoch(field);
522
523 Assertions.assertEquals(-210866760000000L, JuEp.toDate(tt).getTime());
524 Assertions.assertEquals(-3506716800000L, MJuEp.toDate(tt).getTime());
525 Assertions.assertEquals(-631152000000L, FiEp.toDate(tt).getTime());
526 Assertions.assertEquals(-378691200000L, CCSDS.toDate(tai).getTime());
527 Assertions.assertEquals(935280019000L, GaEp.toDate(tai).getTime());
528 Assertions.assertEquals(315964819000L, GPSEp.toDate(tai).getTime());
529 Assertions.assertEquals(946728000000L, JTTEP.toDate(tt).getTime());
530
531 }
532
533 private <T extends CalculusFieldElement<T>> void doTestStandardEpochStrings(final Field<T> field) {
534
535 Assertions.assertEquals("-4712-01-01T12:00:00.000",
536 FieldAbsoluteDate.getJulianEpoch(field).toString(TimeScalesFactory.getTT()));
537 Assertions.assertEquals("1858-11-17T00:00:00.000",
538 FieldAbsoluteDate.getModifiedJulianEpoch(field).toString(TimeScalesFactory.getTT()));
539 Assertions.assertEquals("1950-01-01T00:00:00.000",
540 FieldAbsoluteDate.getFiftiesEpoch(field).toString(TimeScalesFactory.getTT()));
541 Assertions.assertEquals("1958-01-01T00:00:00.000",
542 FieldAbsoluteDate.getCCSDSEpoch(field).toString(TimeScalesFactory.getTAI()));
543 Assertions.assertEquals("1999-08-21T23:59:47.000",
544 FieldAbsoluteDate.getGalileoEpoch(field).toString(TimeScalesFactory.getUTC()));
545 Assertions.assertEquals("1980-01-06T00:00:00.000",
546 FieldAbsoluteDate.getGPSEpoch(field).toString(TimeScalesFactory.getUTC()));
547 Assertions.assertEquals("2000-01-01T12:00:00.000",
548 FieldAbsoluteDate.getJ2000Epoch(field).toString(TimeScalesFactory.getTT()));
549 Assertions.assertEquals("1970-01-01T00:00:00.000",
550 FieldAbsoluteDate.getJavaEpoch(field).toString(TimeScalesFactory.getUTC()));
551 }
552
553 private <T extends CalculusFieldElement<T>> void doTestJulianEpochRate(final Field<T> field) {
554
555 for (int i = 0; i < 10; ++i) {
556 FieldAbsoluteDate<T> j200i = FieldAbsoluteDate.createJulianEpoch(field.getZero().add(2000.0+i));
557 FieldAbsoluteDate<T> j2000 = FieldAbsoluteDate.getJ2000Epoch(field);
558 double expected = i * Constants.JULIAN_YEAR;
559 Assertions.assertEquals(expected, j200i.durationFrom(j2000).getReal(), 4.0e-15 * expected);
560 }
561
562 }
563
564 private <T extends CalculusFieldElement<T>> void doTestBesselianEpochRate(final Field<T> field) {
565
566 for (int i = 0; i < 10; ++i) {
567 FieldAbsoluteDate<T> b195i = FieldAbsoluteDate.createBesselianEpoch(field.getZero().add(1950.0 + i));
568 FieldAbsoluteDate<T> b1950 = FieldAbsoluteDate.createBesselianEpoch(field.getZero().add(1950.0));
569 double expected = i * Constants.BESSELIAN_YEAR;
570 Assertions.assertEquals(expected, b195i.durationFrom(b1950).getReal(), 4.0e-15 * expected);
571 }
572
573 }
574
575 private <T extends CalculusFieldElement<T>> void doTestLieske(final Field<T> field) {
576
577
578
579
580
581
582
583
584
585 final double publishedEpsilon = 1.0e-6 * Constants.JULIAN_YEAR;
586 checkEpochs(field, 1899.999142, 1900.000000, publishedEpsilon);
587 checkEpochs(field, 1900.000000, 1900.000858, publishedEpsilon);
588 checkEpochs(field, 1950.000000, 1949.999790, publishedEpsilon);
589 checkEpochs(field, 1950.000210, 1950.000000, publishedEpsilon);
590 checkEpochs(field, 2000.000000, 1999.998722, publishedEpsilon);
591 checkEpochs(field, 2000.001278, 2000.000000, publishedEpsilon);
592
593
594 final double accurateEpsilon = 1.2e-13 * Constants.JULIAN_YEAR;
595 checkEpochs(field, 1899.99914161068724704, 1900.00000000000000000, accurateEpsilon);
596 checkEpochs(field, 1900.00000000000000000, 1900.00085837097878165, accurateEpsilon);
597 checkEpochs(field, 1950.00000000000000000, 1949.99979044229979466, accurateEpsilon);
598 checkEpochs(field, 1950.00020956217615449, 1950.00000000000000000, accurateEpsilon);
599 checkEpochs(field, 2000.00000000000000000, 1999.99872251362080766, accurateEpsilon);
600 checkEpochs(field, 2000.00127751366506194, 2000.00000000000000000, accurateEpsilon);
601
602 }
603
604 private <T extends CalculusFieldElement<T>> void checkEpochs(final Field<T> field, final double besselianEpoch, final double julianEpoch, final double epsilon) {
605 final FieldAbsoluteDate<T> b = FieldAbsoluteDate.createBesselianEpoch(field.getZero().add(besselianEpoch));
606 final FieldAbsoluteDate<T> j = FieldAbsoluteDate.createJulianEpoch(field.getZero().add(julianEpoch));
607 Assertions.assertEquals(0.0, b.durationFrom(j).getReal(), epsilon);
608 }
609
610 private <T extends CalculusFieldElement<T>> void doTestParse(final Field<T> field) {
611
612 Assertions.assertEquals(FieldAbsoluteDate.getModifiedJulianEpoch(field),
613 new FieldAbsoluteDate<>(field, "1858-W46-3", TimeScalesFactory.getTT()));
614 Assertions.assertEquals(FieldAbsoluteDate.getJulianEpoch(field),
615 new FieldAbsoluteDate<>(field, "-4712-01-01T12:00:00.000", TimeScalesFactory.getTT()));
616 Assertions.assertEquals(FieldAbsoluteDate.getFiftiesEpoch(field),
617 new FieldAbsoluteDate<>(field, "1950-01-01", TimeScalesFactory.getTT()));
618 Assertions.assertEquals(FieldAbsoluteDate.getCCSDSEpoch(field),
619 new FieldAbsoluteDate<>(field, "1958-001", TimeScalesFactory.getTAI()));
620 }
621
622 private <T extends CalculusFieldElement<T>> void doTestLocalTimeParsing(final Field<T> field) {
623 TimeScale utc = TimeScalesFactory.getUTC();
624 Assertions.assertEquals(new FieldAbsoluteDate<>(field, "2011-12-31T23:00:00", utc),
625 new FieldAbsoluteDate<>(field, "2012-01-01T03:30:00+04:30", utc));
626 Assertions.assertEquals(new FieldAbsoluteDate<>(field, "2011-12-31T23:00:00", utc),
627 new FieldAbsoluteDate<>(field, "2012-01-01T03:30:00+0430", utc));
628 Assertions.assertEquals(new FieldAbsoluteDate<>(field, "2011-12-31T23:30:00", utc),
629 new FieldAbsoluteDate<>(field, "2012-01-01T03:30:00+04", utc));
630 Assertions.assertEquals(new FieldAbsoluteDate<>(field, "2012-01-01T05:17:00", utc),
631 new FieldAbsoluteDate<>(field, "2011-12-31T22:17:00-07:00", utc));
632 Assertions.assertEquals(new FieldAbsoluteDate<>(field, "2012-01-01T05:17:00", utc),
633 new FieldAbsoluteDate<>(field, "2011-12-31T22:17:00-0700", utc));
634 Assertions.assertEquals(new FieldAbsoluteDate<>(field, "2012-01-01T05:17:00", utc),
635 new FieldAbsoluteDate<>(field, "2011-12-31T22:17:00-07", utc));
636 }
637
638 private <T extends CalculusFieldElement<T>> void doTestTimeZoneDisplay(final Field<T> field) {
639 final TimeScale utc = TimeScalesFactory.getUTC();
640 final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, "2000-01-01T01:01:01.000", utc);
641 Assertions.assertEquals("2000-01-01T01:01:01.000Z", date.toString());
642 Assertions.assertEquals("2000-01-01T11:01:01.000+10:00", date.toString( 600));
643 Assertions.assertEquals("1999-12-31T23:01:01.000-02:00", date.toString(-120));
644
645
646 final TimeZone tz = TimeZone.getTimeZone("Europe/Paris");
647 Assertions.assertEquals("2001-01-22T11:30:00.000+01:00",
648 new FieldAbsoluteDate<>(field, "2001-01-22T10:30:00", utc).toString(tz));
649
650
651 Assertions.assertEquals("2001-06-23T11:30:00.000+02:00",
652 new FieldAbsoluteDate<>(field, "2001-06-23T09:30:00", utc).toString(tz));
653
654 }
655
656 private <T extends CalculusFieldElement<T>> void doTestLocalTimeLeapSecond(final Field<T> field) {
657
658 TimeScale utc = TimeScalesFactory.getUTC();
659 FieldAbsoluteDate<T> beforeLeap = new FieldAbsoluteDate<>(field, "2012-06-30T23:59:59.8", utc);
660 FieldAbsoluteDate<T> inLeap = new FieldAbsoluteDate<>(field, "2012-06-30T23:59:60.5", utc);
661 Assertions.assertEquals(0.7, inLeap.durationFrom(beforeLeap).getReal(), 1.0e-12);
662 for (int minutesFromUTC = -1500; minutesFromUTC < -1499; ++minutesFromUTC) {
663 DateTimeComponents dtcBeforeLeap = beforeLeap.getComponents(minutesFromUTC);
664 DateTimeComponents dtcInsideLeap = inLeap.getComponents(minutesFromUTC);
665
666
667 Assertions.assertEquals(dtcBeforeLeap.getDate(), dtcInsideLeap.getDate());
668
669 Assertions.assertEquals(dtcBeforeLeap.getTime().getHour(), dtcInsideLeap.getTime().getHour());
670 Assertions.assertEquals(dtcBeforeLeap.getTime().getMinute(), dtcInsideLeap.getTime().getMinute());
671 Assertions.assertEquals(minutesFromUTC, dtcBeforeLeap.getTime().getMinutesFromUTC());
672 Assertions.assertEquals(minutesFromUTC, dtcInsideLeap.getTime().getMinutesFromUTC());
673 Assertions.assertEquals(59.8, dtcBeforeLeap.getTime().getSecond(), 1.0e-10);
674 Assertions.assertEquals(60.5, dtcInsideLeap.getTime().getSecond(), 1.0e-10);
675 }
676
677 }
678
679 private <T extends CalculusFieldElement<T>> void doTestTimeZoneLeapSecond(final Field<T> field) {
680
681 TimeScale utc = TimeScalesFactory.getUTC();
682 final TimeZone tz = TimeZone.getTimeZone("Europe/Paris");
683 FieldAbsoluteDate<T> localBeforeMidnight = new FieldAbsoluteDate<>(field, "2012-06-30T21:59:59.800", utc);
684 Assertions.assertEquals("2012-06-30T23:59:59.800+02:00",
685 localBeforeMidnight.toString(tz));
686 Assertions.assertEquals("2012-07-01T00:00:00.800+02:00",
687 localBeforeMidnight.shiftedBy(1.0).toString(tz));
688
689 FieldAbsoluteDate<T> beforeLeap = new FieldAbsoluteDate<>(field, "2012-06-30T23:59:59.8", utc);
690 FieldAbsoluteDate<T> inLeap = new FieldAbsoluteDate<>(field, "2012-06-30T23:59:60.5", utc);
691 Assertions.assertEquals(0.7, inLeap.durationFrom(beforeLeap).getReal(), 1.0e-12);
692 Assertions.assertEquals("2012-07-01T01:59:59.800+02:00", beforeLeap.toString(tz));
693 Assertions.assertEquals("2012-07-01T01:59:60.500+02:00", inLeap.toString(tz));
694
695 }
696
697 private <T extends CalculusFieldElement<T>> void doTestParseLeap(final Field<T> field) {
698 TimeScale utc = TimeScalesFactory.getUTC();
699 FieldAbsoluteDate<T> beforeLeap = new FieldAbsoluteDate<>(field, "2012-06-30T23:59:59.8", utc);
700 FieldAbsoluteDate<T> inLeap = new FieldAbsoluteDate<>(field, "2012-06-30T23:59:60.5", utc);
701 Assertions.assertEquals(0.7, inLeap.durationFrom(beforeLeap).getReal(), 1.0e-12);
702 Assertions.assertEquals("2012-06-30T23:59:60.500", inLeap.toString(utc));
703 }
704
705 private <T extends CalculusFieldElement<T>> void doTestOutput(final Field<T> field) {
706 TimeScale tt = TimeScalesFactory.getTT();
707 Assertions.assertEquals("1950-01-01T01:01:01.000",
708 FieldAbsoluteDate.getFiftiesEpoch(field).shiftedBy(3661.0).toString(tt));
709 Assertions.assertEquals("2000-01-01T13:01:01.000",
710 FieldAbsoluteDate.getJ2000Epoch(field).shiftedBy(3661.0).toString(tt));
711 }
712
713 private <T extends CalculusFieldElement<T>> void doTestJ2000(final Field<T> field) {
714 FieldAbsoluteDate<T> FAD = new FieldAbsoluteDate<>(field);
715 Assertions.assertEquals("2000-01-01T12:00:00.000",
716 FAD.toString(TimeScalesFactory.getTT()));
717 Assertions.assertEquals("2000-01-01T11:59:27.816",
718 FAD.toString(TimeScalesFactory.getTAI()));
719 Assertions.assertEquals("2000-01-01T11:58:55.816",
720 FAD.toString(utc));
721 Assertions.assertEquals("2000-01-01T12:00:00.000",
722 FieldAbsoluteDate.getJ2000Epoch(field).toString(TimeScalesFactory.getTT()));
723 Assertions.assertEquals("2000-01-01T11:59:27.816",
724 FieldAbsoluteDate.getJ2000Epoch(field).toString(TimeScalesFactory.getTAI()));
725 Assertions.assertEquals("2000-01-01T11:58:55.816",
726 FieldAbsoluteDate.getJ2000Epoch(field).toString(utc));
727 }
728
729 private <T extends CalculusFieldElement<T>> void doTestFraction(final Field<T> field) {
730 FieldAbsoluteDate<T> d =
731 new FieldAbsoluteDate<>(field, new DateComponents(2000, 1, 1), new TimeComponents(11, 59, 27.816),
732 TimeScalesFactory.getTAI());
733 Assertions.assertEquals(0, d.durationFrom(FieldAbsoluteDate.getJ2000Epoch(field)).getReal(), 1.0e-10);
734 }
735
736 private <T extends CalculusFieldElement<T>> void doTestScalesOffset(final Field<T> field) {
737 FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2006, 2, 24),
738 new TimeComponents(15, 38, 0),
739 utc);
740 Assertions.assertEquals(33,
741 date.timeScalesOffset(TimeScalesFactory.getTAI(), utc).getReal(),
742 1.0e-10);
743 }
744
745 private <T extends CalculusFieldElement<T>> void doTestUTC(final Field<T> field) {
746 FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2002, 1, 1),
747 new TimeComponents(0, 0, 1),
748 utc);
749 Assertions.assertEquals("2002-01-01T00:00:01.000Z", date.toString());
750 }
751
752 private <T extends CalculusFieldElement<T>> void doTest1970(final Field<T> field) {
753 FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new Date(0L), utc);
754 Assertions.assertEquals("1970-01-01T00:00:00.000Z", date.toString());
755 }
756
757 private <T extends CalculusFieldElement<T>> void doTest1970Instant(final Field<T> field) {
758 Assertions.assertEquals("1970-01-01T00:00:00.000Z", new FieldAbsoluteDate<>(field, Instant.EPOCH, utc).toString());
759 Assertions.assertEquals("1970-01-01T00:00:00.000Z", new FieldAbsoluteDate<>(field, Instant.ofEpochMilli(0L), utc).toString());
760 Assertions.assertEquals("1970-01-01T00:00:00.000Z", new FieldAbsoluteDate<>(field, Instant.EPOCH, (UTCScale) utc).toString());
761 Assertions.assertEquals("1970-01-01T00:00:00.000Z", new FieldAbsoluteDate<>(field, Instant.ofEpochMilli(0L), (UTCScale) utc).toString());
762 }
763
764 private <T extends CalculusFieldElement<T>> void doTestInstantAccuracy(final Field<T> field) {
765 Assertions.assertEquals("1970-01-02T00:16:40.123456789Z", new FieldAbsoluteDate<>(field, Instant.ofEpochSecond(87400, 123456789), utc).toString());
766 Assertions.assertEquals("1970-01-07T00:10:00.123456789Z", new FieldAbsoluteDate<>(field, Instant.ofEpochSecond(519000, 123456789), utc).toString());
767 Assertions.assertEquals("1970-01-02T00:16:40.123456789Z", new FieldAbsoluteDate<>(field, Instant.ofEpochSecond(87400, 123456789), (UTCScale) utc).toString());
768 Assertions.assertEquals("1970-01-07T00:10:00.123456789Z", new FieldAbsoluteDate<>(field, Instant.ofEpochSecond(519000, 123456789), (UTCScale) utc).toString());
769 }
770
771 public <T extends CalculusFieldElement<T>> void doTestToInstant(final Field<T> field) {
772 Assertions.assertEquals(Instant.ofEpochSecond(0), new FieldAbsoluteDate<>(field, "1970-01-01T00:00:00.000Z", utc).toInstant());
773 Assertions.assertEquals(Instant.ofEpochSecond(0), new FieldAbsoluteDate<>(field, "1970-01-01T00:00:00.000Z", utc).toInstant(TimeScalesFactory.getTimeScales()));
774
775 Instant expectedInstant = Instant.ofEpochSecond(519000, 123456789);
776 Assertions.assertEquals(expectedInstant, new FieldAbsoluteDate<>(field, "1970-01-07T00:10:00.123456789Z", utc).toInstant());
777 Assertions.assertEquals(expectedInstant, new FieldAbsoluteDate<>(field, "1970-01-07T00:10:00.123456789Z", utc).toInstant(TimeScalesFactory.getTimeScales()));
778
779 Assertions.assertEquals(OffsetDateTime.parse("2024-05-15T09:32:36.123456789Z", DateTimeFormatter.ISO_DATE_TIME).toInstant(),
780 new FieldAbsoluteDate<>(field,"2024-05-15T09:32:36.123456789Z", utc).toInstant());
781 Assertions.assertEquals(OffsetDateTime.parse("2024-05-15T09:32:36.123456789Z", DateTimeFormatter.ISO_DATE_TIME).toInstant(),
782 new FieldAbsoluteDate<>(field, "2024-05-15T09:32:36.123456789Z", utc).toInstant(TimeScalesFactory.getTimeScales()));
783
784 }
785
786 private <T extends CalculusFieldElement<T>> void doTestUtcGpsOffset(final Field<T> field) {
787 FieldAbsoluteDate<T> date1 = new FieldAbsoluteDate<>(field, new DateComponents(2005, 8, 9),
788 new TimeComponents(16, 31, 17),
789 utc);
790 FieldAbsoluteDate<T> date2 = new FieldAbsoluteDate<>(field, new DateComponents(2006, 8, 9),
791 new TimeComponents(16, 31, 17),
792 utc);
793 FieldAbsoluteDate<T> dateRef = new FieldAbsoluteDate<>(field, new DateComponents(1980, 1, 6),
794 TimeComponents.H00,
795 utc);
796
797
798 long noLeapGap = ((9347 * 24 + 16) * 60 + 31) * 60 + 17;
799 long realGap = (long) date1.durationFrom(dateRef).getReal();
800 Assertions.assertEquals(13L, realGap - noLeapGap);
801
802
803 noLeapGap = ((9712 * 24 + 16) * 60 + 31) * 60 + 17;
804 realGap = (long) date2.durationFrom(dateRef).getReal();
805 Assertions.assertEquals(14L, realGap - noLeapGap);
806
807 }
808
809 private <T extends CalculusFieldElement<T>> void doTestGpsDate(final Field<T> field) {
810 FieldAbsoluteDate<T> date = FieldAbsoluteDate.createGPSDate(1387, field.getZero().add(318677000.0));
811 FieldAbsoluteDate<T> ref = new FieldAbsoluteDate<>(field, new DateComponents(2006, 8, 9),
812 new TimeComponents(16, 31, 3),
813 utc);
814 Assertions.assertEquals(0, date.durationFrom(ref).getReal(), 1.0e-15);
815 }
816
817 private <T extends CalculusFieldElement<T>> void doTestMJDDate(final Field<T> field) {
818 FieldAbsoluteDate<T> dateA = FieldAbsoluteDate.createMJDDate(51544, field.getZero().add(0.5 * Constants.JULIAN_DAY),
819 TimeScalesFactory.getTT());
820 Assertions.assertEquals(0.0, FieldAbsoluteDate.getJ2000Epoch(field).durationFrom(dateA).getReal(), 1.0e-15);
821 FieldAbsoluteDate<T> dateB = FieldAbsoluteDate.createMJDDate(53774, field.getZero(), TimeScalesFactory.getUTC());
822 FieldAbsoluteDate<T> dateC = new FieldAbsoluteDate<>(field, "2006-02-08T00:00:00", TimeScalesFactory.getUTC());
823 Assertions.assertEquals(0.0, dateC.durationFrom(dateB).getReal(), 1.0e-15);
824 }
825
826 private <T extends CalculusFieldElement<T>> void doTestJDDate(final Field<T> field) {
827 final FieldAbsoluteDate<T> date = FieldAbsoluteDate.createJDDate(2400000, field.getZero().add(0.5 * Constants.JULIAN_DAY),
828 TimeScalesFactory.getTT());
829 Assertions.assertEquals(0.0, FieldAbsoluteDate.getModifiedJulianEpoch(field).durationFrom(date).getReal(), 1.0e-15);
830 }
831
832 private <T extends CalculusFieldElement<T>> void doTestOffsets(final Field<T> field) {
833 final TimeScale tai = TimeScalesFactory.getTAI();
834 FieldAbsoluteDate<T> leapStartUTC = new FieldAbsoluteDate<>(field, 1976, 12, 31, 23, 59, 59, utc);
835 FieldAbsoluteDate<T> leapEndUTC = new FieldAbsoluteDate<>(field, 1977, 1, 1, 0, 0, 0, utc);
836 FieldAbsoluteDate<T> leapStartTAI = new FieldAbsoluteDate<>(field, 1977, 1, 1, 0, 0, 14, tai);
837 FieldAbsoluteDate<T> leapEndTAI = new FieldAbsoluteDate<>(field, 1977, 1, 1, 0, 0, 16, tai);
838 Assertions.assertEquals(leapStartUTC, leapStartTAI);
839 Assertions.assertEquals(leapEndUTC, leapEndTAI);
840 Assertions.assertEquals(1, leapEndUTC.offsetFrom(leapStartUTC, utc).getReal(), 1.0e-10);
841 Assertions.assertEquals(1, leapEndTAI.offsetFrom(leapStartTAI, utc).getReal(), 1.0e-10);
842 Assertions.assertEquals(2, leapEndUTC.offsetFrom(leapStartUTC, tai).getReal(), 1.0e-10);
843 Assertions.assertEquals(2, leapEndTAI.offsetFrom(leapStartTAI, tai).getReal(), 1.0e-10);
844 Assertions.assertEquals(2, leapEndUTC.durationFrom(leapStartUTC).getReal(), 1.0e-10);
845 Assertions.assertEquals(2, leapEndTAI.durationFrom(leapStartTAI).getReal(), 1.0e-10);
846 }
847
848 private <T extends CalculusFieldElement<T>> void doTestBeforeAndAfterLeap(final Field<T> field) {
849 final TimeScale tai = TimeScalesFactory.getTAI();
850 FieldAbsoluteDate<T> leapStart = new FieldAbsoluteDate<>(field, 1977, 1, 1, 0, 0, 14, tai);
851 FieldAbsoluteDate<T> leapEnd = new FieldAbsoluteDate<>(field, 1977, 1, 1, 0, 0, 16, tai);
852 for (int i = -10; i < 10; ++i) {
853 final double dt = 1.1 * (2 * i - 1);
854 FieldAbsoluteDate<T> d1 = leapStart.shiftedBy(dt);
855 FieldAbsoluteDate<T> d2 = new FieldAbsoluteDate<>(leapStart, dt, tai);
856 FieldAbsoluteDate<T> d3 = new FieldAbsoluteDate<>(leapStart, dt, utc);
857 FieldAbsoluteDate<T> d4 = new FieldAbsoluteDate<>(leapEnd, dt, tai);
858 FieldAbsoluteDate<T> d5 = new FieldAbsoluteDate<>(leapEnd, dt, utc);
859 Assertions.assertTrue(FastMath.abs(d1.durationFrom(d2).getReal()) < 1.0e-10);
860 if (dt < 0) {
861 Assertions.assertTrue(FastMath.abs(d2.durationFrom(d3).getReal()) < 1.0e-10);
862 Assertions.assertTrue(d4.durationFrom(d5).getReal() > (1.0 - 1.0e-10));
863 } else {
864 Assertions.assertTrue(d2.durationFrom(d3).getReal() < (-1.0 + 1.0e-10));
865 Assertions.assertTrue(FastMath.abs(d4.durationFrom(d5).getReal()) < 1.0e-10);
866 }
867 }
868 }
869
870 private <T extends CalculusFieldElement<T>> void doTestSymmetry(final Field<T> field) {
871 final TimeScale tai = TimeScalesFactory.getTAI();
872 FieldAbsoluteDate<T> leapStart = new FieldAbsoluteDate<>(field, 1977, 1, 1, 0, 0, 14, tai);
873 for (int i = -10; i < 10; ++i) {
874 final double dt = 1.1 * (2 * i - 1);
875 Assertions.assertEquals(dt, new FieldAbsoluteDate<>(leapStart, dt, utc).offsetFrom(leapStart, utc).getReal(), 1.0e-10);
876 Assertions.assertEquals(dt, new FieldAbsoluteDate<>(leapStart, dt, tai).offsetFrom(leapStart, tai).getReal(), 1.0e-10);
877 Assertions.assertEquals(dt, leapStart.shiftedBy(dt).durationFrom(leapStart).getReal(), 1.0e-10);
878 }
879 }
880
881 @SuppressWarnings("unlikely-arg-type")
882 private <T extends CalculusFieldElement<T>> void doTestEquals(final Field<T> field) {
883 FieldAbsoluteDate<T> d1 =
884 new FieldAbsoluteDate<>(field, new DateComponents(2006, 2, 25),
885 new TimeComponents(17, 10, 34),
886 utc);
887 FieldAbsoluteDate<T> d2 = new FieldAbsoluteDate<>(field, new DateComponents(2006, 2, 25),
888 new TimeComponents(17, 10, 0),
889 utc).shiftedBy(34);
890 Assertions.assertEquals(d1, d2);
891 Assertions.assertNotEquals(d1, this);
892 }
893
894 private <T extends CalculusFieldElement<T>> void doTestIsEqualTo(final Field<T> field) {
895 TestDates<T> dates = new TestDates<>(field);
896 FieldAbsoluteDate<T> present = dates.getPresentFieldAbsoluteDate();
897 Assertions.assertTrue(present.isEqualTo(dates.present));
898 Assertions.assertTrue(present.isEqualTo(dates.presentToo));
899 Assertions.assertFalse(present.isEqualTo(dates.past));
900 Assertions.assertFalse(present.isEqualTo(dates.future));
901 }
902
903 private <T extends CalculusFieldElement<T>> void doTestIsCloseTo(final Field<T> field) {
904 double tolerance = 10;
905 TestDates<T> dates = new TestDates<>(field);
906 FieldAbsoluteDate<T> present = dates.getPresentFieldAbsoluteDate();
907 FieldTimeStamped<T> closeToPresent = new AnyFieldTimeStamped<>(field, dates.presentDate.shiftedBy(5));
908 Assertions.assertTrue(present.isCloseTo(present, tolerance));
909 Assertions.assertTrue(present.isCloseTo(dates.presentToo, tolerance));
910 Assertions.assertTrue(present.isCloseTo(closeToPresent, tolerance));
911 Assertions.assertFalse(present.isCloseTo(dates.past, tolerance));
912 Assertions.assertFalse(present.isCloseTo(dates.future, tolerance));
913 }
914
915 private <T extends CalculusFieldElement<T>> void doTestIsBefore(final Field<T> field) {
916 TestDates<T> dates = new TestDates<>(field);
917 FieldAbsoluteDate<T> present = dates.getPresentFieldAbsoluteDate();
918 Assertions.assertFalse(present.isBefore(dates.past));
919 Assertions.assertFalse(present.isBefore(present));
920 Assertions.assertFalse(present.isBefore(dates.presentToo));
921 Assertions.assertTrue(present.isBefore(dates.future));
922 }
923
924 private <T extends CalculusFieldElement<T>> void doTestIsAfter(final Field<T> field) {
925 TestDates<T> dates = new TestDates<>(field);
926 FieldAbsoluteDate<T> present = dates.getPresentFieldAbsoluteDate();
927 Assertions.assertTrue(present.isAfter(dates.past));
928 Assertions.assertFalse(present.isAfter(present));
929 Assertions.assertFalse(present.isAfter(dates.presentToo));
930 Assertions.assertFalse(present.isAfter(dates.future));
931 }
932
933 private <T extends CalculusFieldElement<T>> void doTestIsBeforeOrEqualTo(final Field<T> field) {
934 TestDates<T> dates = new TestDates<>(field);
935 FieldAbsoluteDate<T> present = dates.getPresentFieldAbsoluteDate();
936 Assertions.assertFalse(present.isBeforeOrEqualTo(dates.past));
937 Assertions.assertTrue(present.isBeforeOrEqualTo(present));
938 Assertions.assertTrue(present.isBeforeOrEqualTo(dates.presentToo));
939 Assertions.assertTrue(present.isBeforeOrEqualTo(dates.future));
940 }
941
942 private <T extends CalculusFieldElement<T>> void doTestIsAfterOrEqualTo(final Field<T> field) {
943 TestDates<T> dates = new TestDates<>(field);
944 FieldAbsoluteDate<T> present = dates.getPresentFieldAbsoluteDate();
945 Assertions.assertTrue(present.isAfterOrEqualTo(dates.past));
946 Assertions.assertTrue(present.isAfterOrEqualTo(present));
947 Assertions.assertTrue(present.isAfterOrEqualTo(dates.presentToo));
948 Assertions.assertFalse(present.isAfterOrEqualTo(dates.future));
949 }
950
951 private <T extends CalculusFieldElement<T>> void doTestIsBetween(final Field<T> field) {
952 TestDates<T> dates = new TestDates<>(field);
953 FieldAbsoluteDate<T> present = dates.getPresentFieldAbsoluteDate();
954 Assertions.assertTrue(present.isBetween(dates.past, dates.future));
955 Assertions.assertTrue(present.isBetween(dates.future, dates.past));
956 Assertions.assertFalse(dates.past.getDate().isBetween(present, dates.future));
957 Assertions.assertFalse(dates.past.getDate().isBetween(dates.future, present));
958 Assertions.assertFalse(dates.future.getDate().isBetween(dates.past, present));
959 Assertions.assertFalse(dates.future.getDate().isBetween(present, dates.past));
960 Assertions.assertFalse(present.isBetween(present, dates.future));
961 Assertions.assertFalse(present.isBetween(dates.past, present));
962 Assertions.assertFalse(present.isBetween(dates.past, dates.past));
963 Assertions.assertFalse(present.isBetween(present, present));
964 Assertions.assertFalse(present.isBetween(present, dates.presentToo));
965 }
966
967 private <T extends CalculusFieldElement<T>> void doTestIsBetweenOrEqualTo(final Field<T> field) {
968 TestDates<T> dates = new TestDates<>(field);
969 FieldAbsoluteDate<T> present = dates.getPresentFieldAbsoluteDate();
970 Assertions.assertTrue(present.isBetweenOrEqualTo(dates.past, dates.future));
971 Assertions.assertTrue(present.isBetweenOrEqualTo(dates.future, dates.past));
972 Assertions.assertFalse(dates.past.getDate().isBetweenOrEqualTo(present, dates.future));
973 Assertions.assertFalse(dates.past.getDate().isBetweenOrEqualTo(dates.future, present));
974 Assertions.assertFalse(dates.future.getDate().isBetweenOrEqualTo(dates.past, present));
975 Assertions.assertFalse(dates.future.getDate().isBetweenOrEqualTo(present, dates.past));
976 Assertions.assertTrue(present.isBetweenOrEqualTo(present, dates.future));
977 Assertions.assertTrue(present.isBetweenOrEqualTo(dates.past, present));
978 Assertions.assertFalse(present.isBetweenOrEqualTo(dates.past, dates.past));
979 Assertions.assertTrue(present.isBetweenOrEqualTo(present, present));
980 Assertions.assertTrue(present.isBetweenOrEqualTo(present, dates.presentToo));
981 }
982
983 private <T extends CalculusFieldElement<T>> void doTestComponents(final Field<T> field) {
984
985
986 DateComponents date = new DateComponents(2000, 1, 1);
987 TimeComponents time = new TimeComponents(11, 59, 10);
988 TimeScale[] scales = {
989 TimeScalesFactory.getTAI(), TimeScalesFactory.getUTC(),
990 TimeScalesFactory.getTT(), TimeScalesFactory.getTCG()
991 };
992 for (int i = 0; i < scales.length; ++i) {
993 FieldAbsoluteDate<T> in = new FieldAbsoluteDate<>(field, date, time, scales[i]);
994 for (int j = 0; j < scales.length; ++j) {
995 DateTimeComponents pair = in.getComponents(scales[j]);
996 if (i == j) {
997 Assertions.assertEquals(date, pair.getDate());
998 Assertions.assertEquals(time, pair.getTime());
999 } else {
1000 Assertions.assertNotSame(date, pair.getDate());
1001 Assertions.assertNotSame(time, pair.getTime());
1002 }
1003 }
1004 }
1005 }
1006
1007 private <T extends CalculusFieldElement<T>> void doTestMonth(final Field<T> field) {
1008 TimeScale utc = TimeScalesFactory.getUTC();
1009 Assertions.assertEquals(new FieldAbsoluteDate<>(field, 2011, 2, 23, utc),
1010 new FieldAbsoluteDate<>(field, 2011, Month.FEBRUARY, 23, utc));
1011 Assertions.assertEquals(new FieldAbsoluteDate<>(field, 2011, 2, 23, 1, 2, 3.4, utc),
1012 new FieldAbsoluteDate<>(field, 2011, Month.FEBRUARY, 23, 1, 2, 3.4, utc));
1013 }
1014
1015 private <T extends CalculusFieldElement<T>> void doTestCCSDSUnsegmentedNoExtension(final Field<T> field) {
1016 FieldAbsoluteDate<T> reference = new FieldAbsoluteDate<>(field, "2002-05-23T12:34:56.789", utc);
1017 double lsb = FastMath.pow(2.0, -24);
1018
1019 byte[] timeCCSDSEpoch = new byte[] { 0x53, 0x7F, 0x40, -0x70, -0x37, -0x05, -0x19 };
1020 for (int preamble = 0x00; preamble < 0x80; ++preamble) {
1021 if (preamble == 0x1F) {
1022
1023 FieldAbsoluteDate<T> ccsds1 =
1024 FieldAbsoluteDate.parseCCSDSUnsegmentedTimeCode(field, (byte) preamble, (byte) 0x0, timeCCSDSEpoch, null);
1025 Assertions.assertEquals(0, ccsds1.durationFrom(reference).getReal(), lsb / 2);
1026 } else {
1027 try {
1028 FieldAbsoluteDate.parseCCSDSUnsegmentedTimeCode(field, (byte) preamble, (byte) 0x0, timeCCSDSEpoch, null);
1029 Assertions.fail("an exception should have been thrown");
1030 } catch (OrekitException iae) {
1031
1032 }
1033
1034 }
1035 }
1036
1037
1038 byte[] timeJ2000Epoch = new byte[] { 0x04, 0x7E, -0x0B, -0x10, -0x07, 0x16, -0x79 };
1039 try {
1040 FieldAbsoluteDate.parseCCSDSUnsegmentedTimeCode(field, (byte) 0x2F, (byte) 0x0, timeJ2000Epoch, null);
1041 Assertions.fail("an exception should have been thrown");
1042 } catch (OrekitException iae) {
1043
1044 }
1045
1046
1047 FieldAbsoluteDate<T> ccsds3 =
1048 FieldAbsoluteDate.parseCCSDSUnsegmentedTimeCode(field, (byte) 0x2F, (byte) 0x0, timeJ2000Epoch,
1049 FieldAbsoluteDate.getJ2000Epoch(field));
1050 Assertions.assertEquals(0, ccsds3.durationFrom(reference).getReal(), lsb / 2);
1051
1052 }
1053
1054 private <T extends CalculusFieldElement<T>> void doTestCCSDSUnsegmentedWithExtendedPreamble(final Field<T> field) {
1055
1056 FieldAbsoluteDate<T> reference = new FieldAbsoluteDate<>(field, "2095-03-03T22:02:45.789012345678901", utc);
1057 int leap = (int) FastMath.rint(utc.offsetFromTAI(reference.toAbsoluteDate()).toDouble());
1058
1059 byte extendedPreamble = (byte) -0x80;
1060 byte identification = (byte) 0x10;
1061 byte coarseLength1 = (byte) 0x0C;
1062 byte fineLength1 = (byte) 0x03;
1063 byte coarseLength2 = (byte) 0x20;
1064 byte fineLength2 = (byte) 0x10;
1065 byte[] timeCCSDSEpoch = new byte[] {
1066 0x01, 0x02, 0x03, 0x04, (byte)(0x05 - leap),
1067 -0x37, -0x04, -0x4A, -0x74, -0x2C, -0x3C, -0x48
1068 };
1069 byte preamble1 = (byte) (extendedPreamble | identification | coarseLength1 | fineLength1);
1070 byte preamble2 = (byte) (coarseLength2 | fineLength2);
1071 FieldAbsoluteDate<T> ccsds1 =
1072 FieldAbsoluteDate.parseCCSDSUnsegmentedTimeCode(field, preamble1, preamble2, timeCCSDSEpoch, null);
1073
1074
1075
1076 Assertions.assertEquals(-8.0e-18, ccsds1.durationFrom(reference).getReal(), 1.0e-18);
1077
1078 }
1079
1080 private <T extends CalculusFieldElement<T>> void doTestCCSDSDaySegmented(final Field<T> field) {
1081 FieldAbsoluteDate<T> reference = new FieldAbsoluteDate<>(field, "2002-05-23T12:34:56.789012345678", TimeScalesFactory.getUTC());
1082 double lsb = 1.0e-13;
1083 byte[] timeCCSDSEpoch = new byte[] { 0x3F, 0x55, 0x02, -0x4D, 0x2C, -0x6B, 0x00, -0x44, 0x61, 0x4E };
1084
1085 for (int preamble = 0x00; preamble < 0x100; ++preamble) {
1086 if (preamble == 0x42) {
1087
1088
1089 FieldAbsoluteDate<T> ccsds1 =
1090 FieldAbsoluteDate.parseCCSDSDaySegmentedTimeCode(field, (byte) preamble, timeCCSDSEpoch, null);
1091 Assertions.assertEquals(0, ccsds1.durationFrom(reference).getReal(), lsb / 2);
1092 } else {
1093 try {
1094 FieldAbsoluteDate.parseCCSDSDaySegmentedTimeCode(field, (byte) preamble, timeCCSDSEpoch, null);
1095 Assertions.fail("an exception should have been thrown");
1096 } catch (OrekitException iae) {
1097
1098 }
1099
1100 }
1101 }
1102
1103
1104 byte[] timeJ2000Epoch = new byte[] { 0x03, 0x69, 0x02, -0x4D, 0x2C, -0x6B, 0x00, -0x44, 0x61, 0x4E };
1105 try {
1106 FieldAbsoluteDate.parseCCSDSDaySegmentedTimeCode(field, (byte) 0x4A, timeJ2000Epoch, null);
1107 Assertions.fail("an exception should have been thrown");
1108 } catch (OrekitException iae) {
1109
1110 }
1111
1112
1113 FieldAbsoluteDate<T> ccsds3 =
1114 FieldAbsoluteDate.parseCCSDSDaySegmentedTimeCode(field, (byte) 0x4A, timeJ2000Epoch, DateComponents.J2000_EPOCH);
1115 Assertions.assertEquals(0, ccsds3.durationFrom(reference).getReal(), lsb / 2);
1116
1117
1118 byte[] timeMicrosecond = new byte[] { 0x03, 0x69, 0x02, -0x4D, 0x2C, -0x6B, 0x00, 0x0C };
1119 FieldAbsoluteDate<T> ccsds4 =
1120 FieldAbsoluteDate.parseCCSDSDaySegmentedTimeCode(field, (byte) 0x49, timeMicrosecond, DateComponents.J2000_EPOCH);
1121 Assertions.assertEquals(-0.345678e-6, ccsds4.durationFrom(reference).getReal(), lsb / 2);
1122
1123 }
1124
1125 private <T extends CalculusFieldElement<T>> void doTestCCSDSCalendarSegmented(final Field<T> field) {
1126
1127 FieldAbsoluteDate<T> reference = new FieldAbsoluteDate<>(field, "2002-05-23T12:34:56.789012345678", TimeScalesFactory.getUTC());
1128 double lsb = 1.0e-13;
1129 FieldAbsoluteDate<T> FAD = new FieldAbsoluteDate<>(field);
1130
1131 byte[] timeMonthDay = new byte[] { 0x07, -0x2E, 0x05, 0x17, 0x0C, 0x22, 0x38, 0x4E, 0x5A, 0x0C, 0x22, 0x38, 0x4E };
1132 for (int preamble = 0x00; preamble < 0x100; ++preamble) {
1133 if (preamble == 0x56) {
1134 FieldAbsoluteDate<T> ccsds1 =
1135 FAD.parseCCSDSCalendarSegmentedTimeCode((byte) preamble, timeMonthDay);
1136 Assertions.assertEquals(0, ccsds1.durationFrom(reference).getReal(), lsb / 2);
1137 } else {
1138 try {
1139 FAD.parseCCSDSCalendarSegmentedTimeCode((byte) preamble, timeMonthDay);
1140 Assertions.fail("an exception should have been thrown");
1141 } catch (OrekitException iae) {
1142
1143 } catch (IllegalArgumentException iae) {
1144
1145
1146 Assertions.assertEquals(preamble & 0x08, 0x08);
1147 }
1148
1149 }
1150 }
1151
1152
1153 byte[] timeDay = new byte[] { 0x07, -0x2E, 0x00, -0x71, 0x0C, 0x22, 0x38, 0x4E, 0x5A, 0x0C, 0x22, 0x38, 0x4E };
1154 for (int preamble = 0x00; preamble < 0x100; ++preamble) {
1155 if (preamble == 0x5E) {
1156 FieldAbsoluteDate<T> ccsds1 =
1157 FAD.parseCCSDSCalendarSegmentedTimeCode((byte) preamble, timeDay);
1158 Assertions.assertEquals(0, ccsds1.durationFrom(reference).getReal(), lsb / 2);
1159 } else {
1160 try {
1161 FAD.parseCCSDSCalendarSegmentedTimeCode((byte) preamble, timeDay);
1162 Assertions.fail("an exception should have been thrown");
1163 } catch (OrekitException iae) {
1164
1165 } catch (IllegalArgumentException iae) {
1166
1167
1168 Assertions.assertEquals(preamble & 0x08, 0x00);
1169 }
1170
1171 }
1172 }
1173
1174
1175 byte[] timeMicrosecond = new byte[] { 0x07, -0x2E, 0x00, -0x71, 0x0C, 0x22, 0x38, 0x4E, 0x5A, 0x0C };
1176 FieldAbsoluteDate<T> ccsds4 =
1177 FAD.parseCCSDSCalendarSegmentedTimeCode((byte) 0x5B, timeMicrosecond);
1178 Assertions.assertEquals(-0.345678e-6, ccsds4.durationFrom(reference).getReal(), lsb / 2);
1179
1180 }
1181
1182 private <T extends CalculusFieldElement<T>> void doTestExpandedConstructors(final Field<T> field) {
1183 Assertions.assertEquals(new FieldAbsoluteDate<>(field, new DateComponents(2002, 5, 28),
1184 new TimeComponents(15, 30, 0),
1185 TimeScalesFactory.getUTC()),
1186 new FieldAbsoluteDate<>(field, 2002, 5, 28, 15, 30, 0, TimeScalesFactory.getUTC()));
1187 Assertions.assertEquals(new FieldAbsoluteDate<>(field, new DateComponents(2002, 5, 28), TimeComponents.H00,
1188 TimeScalesFactory.getUTC()),
1189 new FieldAbsoluteDate<>(field, 2002, 5, 28, TimeScalesFactory.getUTC()));
1190 try {
1191 new FieldAbsoluteDate<>(field, 2002, 5, 28, 25, 30, 0, TimeScalesFactory.getUTC());
1192 } catch (OrekitIllegalArgumentException oiae) {
1193 Assertions.assertEquals(OrekitMessages.NON_EXISTENT_HMS_TIME, oiae.getSpecifier());
1194 Assertions.assertEquals(25, ((Integer) oiae.getParts()[0]).intValue());
1195 Assertions.assertEquals(30, ((Integer) oiae.getParts()[1]).intValue());
1196 Assertions.assertEquals( 0, ((Double) oiae.getParts()[2]), 1.0e-15);
1197 }
1198 }
1199
1200 private <T extends CalculusFieldElement<T>> void doTestHashcode(final Field<T> field) {
1201 FieldAbsoluteDate<T> d1 =
1202 new FieldAbsoluteDate<>(field, new DateComponents(2006, 2, 25),
1203 new TimeComponents(17, 10, 34),
1204 utc);
1205 FieldAbsoluteDate<T> d2 = new FieldAbsoluteDate<>(field, new DateComponents(2006, 2, 25),
1206 new TimeComponents(17, 10, 0),
1207 utc).shiftedBy(34);
1208 Assertions.assertEquals(d1.hashCode(), d2.hashCode());
1209 Assertions.assertTrue(d1.hashCode() != d1.shiftedBy(1.0e-3).hashCode());
1210 }
1211
1212 private <T extends CalculusFieldElement<T>> void doTestInfinity(final Field<T> field) {
1213 Assertions.assertTrue(FieldAbsoluteDate.getJulianEpoch(field).compareTo(FieldAbsoluteDate.getPastInfinity(field)) > 0);
1214 Assertions.assertTrue(FieldAbsoluteDate.getJulianEpoch(field).compareTo(FieldAbsoluteDate.getFutureInfinity(field)) < 0);
1215 Assertions.assertTrue(FieldAbsoluteDate.getJ2000Epoch(field).compareTo(FieldAbsoluteDate.getPastInfinity(field)) > 0);
1216 Assertions.assertTrue(FieldAbsoluteDate.getJ2000Epoch(field).compareTo(FieldAbsoluteDate.getFutureInfinity(field)) < 0);
1217 Assertions.assertTrue(FieldAbsoluteDate.getPastInfinity(field).compareTo(FieldAbsoluteDate.getJulianEpoch(field)) < 0);
1218 Assertions.assertTrue(FieldAbsoluteDate.getPastInfinity(field).compareTo(FieldAbsoluteDate.getJ2000Epoch(field)) < 0);
1219 Assertions.assertTrue(FieldAbsoluteDate.getPastInfinity(field).compareTo(FieldAbsoluteDate.getFutureInfinity(field)) < 0);
1220 Assertions.assertTrue(FieldAbsoluteDate.getFutureInfinity(field).compareTo(FieldAbsoluteDate.getJulianEpoch(field)) > 0);
1221 Assertions.assertTrue(FieldAbsoluteDate.getFutureInfinity(field).compareTo(FieldAbsoluteDate.getJ2000Epoch(field)) > 0);
1222 Assertions.assertTrue(FieldAbsoluteDate.getFutureInfinity(field).compareTo(FieldAbsoluteDate.getPastInfinity(field)) > 0);
1223 Assertions.assertTrue(Double.isInfinite(FieldAbsoluteDate.getFutureInfinity(field).durationFrom(FieldAbsoluteDate.getJ2000Epoch(field)).getReal()));
1224 Assertions.assertTrue(Double.isInfinite(FieldAbsoluteDate.getFutureInfinity(field).durationFrom(FieldAbsoluteDate.getPastInfinity(field)).getReal()));
1225 Assertions.assertTrue(Double.isInfinite(FieldAbsoluteDate.getPastInfinity(field).durationFrom(FieldAbsoluteDate.getJ2000Epoch(field)).getReal()));
1226 Assertions.assertEquals("5881610-07-11T23:59:59.999Z", FieldAbsoluteDate.getFutureInfinity(field).toString());
1227 Assertions.assertEquals("-5877490-03-03T00:00:00.000Z", FieldAbsoluteDate.getPastInfinity(field).toString());
1228
1229 final FieldAbsoluteDate<T> j2000 = FieldAbsoluteDate.getJ2000Epoch(field);
1230 final FieldAbsoluteDate<T> arbitrary = FieldAbsoluteDate.getArbitraryEpoch(field);
1231 Assertions.assertEquals(Double.POSITIVE_INFINITY,
1232 j2000.durationFrom(arbitrary.shiftedBy(Double.NEGATIVE_INFINITY)).getReal());
1233 Assertions.assertEquals(Double.NEGATIVE_INFINITY,
1234 j2000.durationFrom(arbitrary.shiftedBy(Double.POSITIVE_INFINITY)).getReal());
1235 Assertions.assertEquals(Double.POSITIVE_INFINITY, j2000.durationFrom(arbitrary.shiftedBy(field.getZero().add(Double.NEGATIVE_INFINITY))).getReal());
1236 Assertions.assertEquals(Double.NEGATIVE_INFINITY,
1237 j2000.durationFrom(arbitrary.shiftedBy(field.getZero().add(Double.POSITIVE_INFINITY))).getReal());
1238
1239 }
1240
1241 private <T extends CalculusFieldElement<T>> void doTestAccuracy(final Field<T> field) {
1242 TimeScale tai = TimeScalesFactory.getTAI();
1243 double sec = 0.281;
1244 FieldAbsoluteDate<T> t = new FieldAbsoluteDate<>(field, 2010, 6, 21, 18, 42, sec, tai);
1245 double recomputedSec = t.getComponents(tai).getTime().getSecond();
1246 Assertions.assertEquals(sec, recomputedSec, FastMath.ulp(sec));
1247 }
1248
1249 private <T extends CalculusFieldElement<T>> void doTestAccuracyIssue348(final Field<T> field)
1250 {
1251 FieldAbsoluteDate<T> tF = new FieldAbsoluteDate<>(field,
1252 new DateComponents(1970, 1, 1),
1253 new TimeComponents(3, 25, 45.6789),
1254 TimeScalesFactory.getUTC());
1255 AbsoluteDate tA = tF.toAbsoluteDate();
1256 double delta = -0.01;
1257 T recomputedDelta = tF.shiftedBy(delta).durationFrom(tA);
1258 Assertions.assertEquals(delta, recomputedDelta.getReal(), 1.0e-17);
1259 }
1260
1261 private <T extends CalculusFieldElement<T>> void doTestIterationAccuracy(final Field<T> field) {
1262
1263 final TimeScale tai = TimeScalesFactory.getTAI();
1264 final FieldAbsoluteDate<T> t0 = new FieldAbsoluteDate<>(field, 2010, 6, 21, 18, 42, 0.281, tai);
1265
1266
1267
1268 checkIteration(0.1, t0, 10000, 3.0, -0.3874, 1.0e-4);
1269
1270
1271
1272 checkIteration(0.125, t0, 10000, 1.0e-15, 0.0, 1.0e-15);
1273 }
1274
1275 private <T extends CalculusFieldElement<T>> void checkIteration(final double step, final FieldAbsoluteDate<T> t0, final int nMax,
1276 final double maxErrorFactor,
1277 final double expectedMean, final double meanTolerance) {
1278 final double epsilon = FastMath.ulp(step);
1279 FieldAbsoluteDate<T> iteratedDate = t0;
1280 double mean = 0;
1281 for (int i = 1; i < nMax; ++i) {
1282 iteratedDate = iteratedDate.shiftedBy(step);
1283 FieldAbsoluteDate<T> directDate = t0.shiftedBy(i * step);
1284 final T error = iteratedDate.durationFrom(directDate);
1285 mean += error.getReal() / (i * epsilon);
1286 Assertions.assertEquals(0.0, iteratedDate.durationFrom(directDate).getReal(), maxErrorFactor * i * epsilon);
1287 }
1288 mean /= nMax;
1289 Assertions.assertEquals(expectedMean, mean, meanTolerance);
1290 }
1291
1292 private <T extends CalculusFieldElement<T>> void doTestIssue142(final Field<T> field) {
1293 final FieldAbsoluteDate<T> epoch = FieldAbsoluteDate.getJavaEpoch(field);
1294 final TimeScale utc = TimeScalesFactory.getUTC();
1295
1296 Assertions.assertEquals("1970-01-01T00:00:00.000", epoch.toString(utc));
1297 Assertions.assertEquals(0.0, epoch.durationFrom(new FieldAbsoluteDate<>(field, 1970, 1, 1, utc)).getReal(), 1.0e-15);
1298 Assertions.assertEquals(8.000082,
1299 epoch.durationFrom(new FieldAbsoluteDate<>(field, DateComponents.JAVA_EPOCH, TimeScalesFactory.getTAI())).getReal(),
1300 1.0e-15);
1301
1302
1303 long msOffset = 1143849600000L;
1304 final FieldAbsoluteDate<T> ad = new FieldAbsoluteDate<>(epoch, msOffset / 1000, TimeScalesFactory.getUTC());
1305 Assertions.assertEquals("2006-04-01T00:00:00.000", ad.toString(utc));
1306 }
1307
1308 private <T extends CalculusFieldElement<T>> void doTestIssue148(final Field<T> field) {
1309 final TimeScale utc = TimeScalesFactory.getUTC();
1310 FieldAbsoluteDate<T> t0 = new FieldAbsoluteDate<>(field, 2012, 6, 30, 23, 59, 50.0, utc);
1311 DateTimeComponents components = t0.shiftedBy(11.0 - 200 * Precision.EPSILON).getComponents(utc);
1312 Assertions.assertEquals(2012, components.getDate().getYear());
1313 Assertions.assertEquals( 6, components.getDate().getMonth());
1314 Assertions.assertEquals( 30, components.getDate().getDay());
1315 Assertions.assertEquals( 23, components.getTime().getHour());
1316 Assertions.assertEquals( 59, components.getTime().getMinute());
1317 Assertions.assertEquals( 61 - 200 * Precision.EPSILON,
1318 components.getTime().getSecond(), 1.0e-15);
1319 }
1320
1321 private <T extends CalculusFieldElement<T>> void doTestIssue149(final Field<T> field) {
1322 final TimeScale utc = TimeScalesFactory.getUTC();
1323 FieldAbsoluteDate<T> t0 = new FieldAbsoluteDate<>(field, 2012, 6, 30, 23, 59, 59, utc);
1324 DateTimeComponents components = t0.shiftedBy(1.0 - Precision.EPSILON).getComponents(utc);
1325 Assertions.assertEquals(2012, components.getDate().getYear());
1326 Assertions.assertEquals( 6, components.getDate().getMonth());
1327 Assertions.assertEquals( 30, components.getDate().getDay());
1328 Assertions.assertEquals( 23, components.getTime().getHour());
1329 Assertions.assertEquals( 59, components.getTime().getMinute());
1330 Assertions.assertEquals( 60 - Precision.EPSILON,
1331 components.getTime().getSecond(), 1.0e-15);
1332 }
1333
1334 private <T extends CalculusFieldElement<T>> void doTestWrapAtMinuteEnd(final Field<T> field) {
1335 TimeScale tai = TimeScalesFactory.getTAI();
1336 TimeScale utc = TimeScalesFactory.getUTC();
1337 FieldAbsoluteDate<T> date0 = new FieldAbsoluteDate<>(field, DateComponents.J2000_EPOCH, TimeComponents.H12, tai);
1338 FieldAbsoluteDate<T> ref = date0.shiftedBy(new TimeOffset(496891466L, 732011406663332300L));
1339 FieldAbsoluteDate<T> date = ref.shiftedBy(new TimeOffset(597L, 900970042626200000L).negate().multiply(33));
1340 DateTimeComponents dtc = date.getComponents(utc);
1341 Assertions.assertEquals( 2015, dtc.getDate().getYear());
1342 Assertions.assertEquals( 9, dtc.getDate().getMonth());
1343 Assertions.assertEquals( 30, dtc.getDate().getDay());
1344 Assertions.assertEquals( 7, dtc.getTime().getHour());
1345 Assertions.assertEquals( 54, dtc.getTime().getMinute());
1346 Assertions.assertEquals( 59L, dtc.getTime().getSplitSecond().getSeconds());
1347 Assertions.assertEquals( 999999999998732300L, dtc.getTime().getSplitSecond().getAttoSeconds());
1348 Assertions.assertEquals("2015-09-30T07:54:59.9999999999987323",
1349 date.toString(utc));
1350 FieldAbsoluteDate<T> beforeMidnight = new FieldAbsoluteDate<>(field, 2008, 2, 29, 23, 59,
1351 new TimeOffset(59L, 999400000000000000L), utc);
1352 FieldAbsoluteDate<T> stillBeforeMidnight = beforeMidnight.shiftedBy(2.0e-4);
1353 Assertions.assertEquals(59.9994, beforeMidnight.getComponents(utc).getTime().getSecond(), 1.0e-15);
1354 Assertions.assertEquals(59.9996, stillBeforeMidnight.getComponents(utc).getTime().getSecond(), 1.0e-15);
1355 Assertions.assertEquals("2008-02-29T23:59:59.9994", beforeMidnight.toString(utc));
1356 Assertions.assertEquals("2008-02-29T23:59:59.9996", stillBeforeMidnight.toString(utc));
1357 }
1358
1359 private <T extends CalculusFieldElement<T>> void doTestIssue508(final Field<T> field) {
1360 AbsoluteDate date = new AbsoluteDate(2000, 2, 24, 17, 5, 30.047, TimeScalesFactory.getUTC());
1361 FieldAbsoluteDate<T> tA = new FieldAbsoluteDate<>(field, date);
1362 FieldAbsoluteDate<T> tB = new FieldAbsoluteDate<>(date, field.getZero());
1363 Assertions.assertEquals(0.0, tA.durationFrom(tB).getReal(), Precision.SAFE_MIN);
1364 }
1365
1366 public <T extends CalculusFieldElement<T>> void doTestGetComponentsIssue681and676and694(
1367 final Field<T> field) {
1368
1369
1370 FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, 2009, 1, 1, utc);
1371 double attoSecond = 1.0e-18;
1372 double zeroUlp = FastMath.nextUp(0.0);
1373 double oneUlp = FastMath.ulp(1.0);
1374 double sixtyUlp = FastMath.ulp(60.0);
1375 double one = FastMath.nextDown(1.0);
1376 double sixty = FastMath.nextDown(60.0);
1377 double sixtyOne = FastMath.nextDown(61.0);
1378
1379
1380
1381
1382 check(date, 2009, 1, 1, 0, 0, 0, 1, 0, 0);
1383 check(date.shiftedBy(attoSecond), 2009, 1, 1, 0, 0, attoSecond, 0.5, 0, 0);
1384 check(date.shiftedBy(one), 2009, 1, 1, 0, 0, one, 0.5, 0, 0);
1385
1386 check(date.shiftedBy(59).shiftedBy(one), 2009, 1, 1, 0, 0, sixty, 1, 1, 0);
1387 check(date.shiftedBy(86399).shiftedBy(one), 2009, 1, 1, 23, 59, sixty, 1, 1, 0);
1388 check(date.shiftedBy(-zeroUlp), 2009, 1, 1, 0, 0, 0, 0.5, 0, 0);
1389 check(date.shiftedBy(-oneUlp), 2008, 12, 31, 23, 59, sixtyOne, 1, 1, 0);
1390 check(date.shiftedBy(-1).shiftedBy(zeroUlp), 2008, 12, 31, 23, 59, 60.0, 0.5, 0, 0);
1391 check(date.shiftedBy(-1).shiftedBy(-zeroUlp), 2008, 12, 31, 23, 59, 60.0, 0.5, 0, 0);
1392 check(date.shiftedBy(-1).shiftedBy(-oneUlp), 2008, 12, 31, 23, 59, 60.0, 0.5, 0, 0);
1393 check(date.shiftedBy(-1).shiftedBy(-sixtyUlp), 2008, 12, 31, 23, 59, sixty, 0.5, 0, 0);
1394 check(date.shiftedBy(-61).shiftedBy(attoSecond), 2008, 12, 31, 23, 59, attoSecond, 0.5, 0, 0);
1395
1396
1397
1398
1399 FieldAbsoluteDate<T> d = new FieldAbsoluteDate<>(field, 1966, 1, 1, utc);
1400 double ratePost = 0.0025920 / Constants.JULIAN_DAY;
1401 double factorPost = ratePost / (1 + ratePost);
1402 double ratePre = 0.0012960 / Constants.JULIAN_DAY;
1403 double factorPre = ratePre / (1 + ratePre);
1404 check(d, 1966, 1, 1, 0, 0, 0, 1, 0, 0);
1405 check(d.shiftedBy(zeroUlp), 1966, 1, 1, 0, 0, 0, 0.5, 0, 0);
1406 check(d.shiftedBy(attoSecond), 1966, 1, 1, 0, 0, attoSecond, 0.5, 0, 0);
1407 check(d.shiftedBy(one), 1966, 1, 1, 0, 0, one * (1 - factorPost), 1, 3, 0);
1408 check(d.shiftedBy(59).shiftedBy(one), 1966, 1, 1, 0, 0, sixty * (1 - factorPost), 1, 2, 0);
1409 check(d.shiftedBy(86399).shiftedBy(one), 1966, 1, 1, 23, 59, sixty - 86400 * factorPost, 1, 1, 0);
1410 check(d.shiftedBy(-zeroUlp), 1966, 1, 1, 0, 0, 0, 0.5, 0, 0);
1411
1412 check(d.shiftedBy(-oneUlp), 1965, 12, 31, 23, 59, 60.0, 1, 0, 0);
1413 check(d.shiftedBy(-1).shiftedBy(zeroUlp), 1965, 12, 31, 23, 59, 59 + factorPre, 0.5, 0, 0);
1414 check(d.shiftedBy(-1).shiftedBy(-zeroUlp), 1965, 12, 31, 23, 59, 59 + factorPre, 0.5, 0, 0);
1415 check(d.shiftedBy(-1).shiftedBy(-oneUlp), 1965, 12, 31, 23, 59, 59 + factorPre, 0.5, 0, 0);
1416 check(d.shiftedBy(-1).shiftedBy(-sixtyUlp), 1965, 12, 31, 23, 59, 59 + (1 + sixtyUlp) * factorPre, 0.5, 1, 0);
1417
1418 check(d.shiftedBy(-60).shiftedBy(zeroUlp), 1965, 12, 31, 23, 59, 60 * factorPre, 0, 0, sixtyUlp);
1419 check(d.shiftedBy(-60).shiftedBy(oneUlp), 1965, 12, 31, 23, 59, (oneUlp - oneUlp * factorPre) + 60 * factorPre, 0.5, 0, sixtyUlp);
1420
1421
1422 FieldAbsoluteDate<T> d2 = new FieldAbsoluteDate<>(field, 1972, 7, 1, utc);
1423 check(d2, 1972, 7, 1, 0, 0, 0, 1, 0, 0);
1424 check(d2.shiftedBy(attoSecond), 1972, 7, 1, 0, 0, attoSecond, 0.5, 0, 0);
1425 check(d2.shiftedBy(one), 1972, 7, 1, 0, 0, one, 0.5, 0, 0);
1426 check(d2.shiftedBy(59).shiftedBy(one), 1972, 7, 1, 0, 0, sixty, 1, 1, 0);
1427 check(d2.shiftedBy(86399).shiftedBy(one), 1972, 7, 1, 23, 59, sixty, 1, 1, 0);
1428 check(d2.shiftedBy(-zeroUlp), 1972, 7, 1, 0, 0, 0, 0.5, 0, 0);
1429 check(d2.shiftedBy(-oneUlp), 1972, 6, 30, 23, 59, sixtyOne, 1, 1, 0);
1430 check(d2.shiftedBy(-1).shiftedBy(zeroUlp), 1972, 6, 30, 23, 59, 60.0, 0.5, 0, 0);
1431 check(d2.shiftedBy(-1).shiftedBy(-zeroUlp), 1972, 6, 30, 23, 59, 60.0, 0.5, 0, 0);
1432 check(d2.shiftedBy(-1).shiftedBy(-oneUlp), 1972, 6, 30, 23, 59, 60.0, 0.5, 0, 0);
1433 check(d2.shiftedBy(-1).shiftedBy(-sixtyUlp), 1972, 6, 30, 23, 59, sixty, 0.5, 0, 0);
1434 check(d2.shiftedBy(-61).shiftedBy(attoSecond), 1972, 6, 30, 23, 59, attoSecond, 0.5, 0, 0);
1435
1436
1437 FieldAbsoluteDate<T> d3 = FieldAbsoluteDate.getArbitraryEpoch(field).shiftedBy(-1230724800);
1438 check(d3, 1960, 12, 31, 23, 59, 60, 0.5, 0, 0);
1439 FieldAbsoluteDate<T> d4 = new FieldAbsoluteDate<>(field, 1961, 1, 1, utc);
1440 check(d4, 1961, 1, 1, 0, 0, 0, 0.5, 0, 0);
1441
1442
1443
1444
1445 DateTimeComponents actual = date.shiftedBy(Double.NaN).getComponents(utc);
1446 DateComponents dc = actual.getDate();
1447 TimeComponents tc = actual.getTime();
1448 MatcherAssert.assertThat(dc.getYear(), CoreMatchers.is(2000));
1449 MatcherAssert.assertThat(dc.getMonth(), CoreMatchers.is(1));
1450 MatcherAssert.assertThat(dc.getDay(), CoreMatchers.is(1));
1451 MatcherAssert.assertThat(tc.getHour(), CoreMatchers.is(0));
1452 MatcherAssert.assertThat(tc.getMinute(), CoreMatchers.is(0));
1453 MatcherAssert.assertThat("second", tc.getSecond(), CoreMatchers.is(Double.NaN));
1454 MatcherAssert.assertThat(tc.getMinutesFromUTC(), CoreMatchers.is(0));
1455 final double difference = new FieldAbsoluteDate<>(field, actual, utc).durationFrom(date).getReal();
1456 MatcherAssert.assertThat(difference, CoreMatchers.is(Double.NaN));
1457 }
1458
1459 private <T extends CalculusFieldElement<T>> void doTestNegativeOffsetConstructor(final Field<T> field) {
1460 FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field,
1461 2019, 10, 11, 20, 40,
1462 FastMath.scalb(6629298651489277.0, -55),
1463 TimeScalesFactory.getTT());
1464 FieldAbsoluteDate<T> after = date.shiftedBy(Precision.EPSILON);
1465 Assertions.assertEquals(624098367L, date.toAbsoluteDate().getSeconds());
1466 Assertions.assertEquals(FastMath.nextAfter(1.0, Double.NEGATIVE_INFINITY),
1467 1.0e-18 * date.toAbsoluteDate().getAttoSeconds(), 2.4e-15);
1468 Assertions.assertEquals(Precision.EPSILON, after.durationFrom(date).getReal(), 1.0e-18);
1469 }
1470
1471 private <T extends CalculusFieldElement<T>> void doTestNegativeOffsetShift(final Field<T> field) {
1472 FieldAbsoluteDate<T> reference = new FieldAbsoluteDate<>(field, 2019, 10, 11, 20, 40, 1.6667019180022178E-7,
1473 TimeScalesFactory.getTAI());
1474 T dt = field.getZero().newInstance(FastMath.scalb(6596520010750484.0, -39));
1475 FieldAbsoluteDate<T> shifted = reference.shiftedBy(dt);
1476 FieldAbsoluteDate<T> after = shifted.shiftedBy(Precision.EPSILON);
1477 Assertions.assertEquals(624110398L, shifted.toAbsoluteDate().getSeconds());
1478 Assertions.assertEquals((1.0 - 1.6922e-13) * 1.0e18, shifted.toAbsoluteDate().getAttoSeconds(), 1.0e-15);
1479 Assertions.assertEquals(Precision.EPSILON, after.durationFrom(shifted).getReal(), 1.0e-18);
1480 }
1481
1482 private <T extends CalculusFieldElement<T>> void doTestDurationFromWithTimeUnit(final Field<T> field) {
1483 FieldAbsoluteDate<T> reference = new FieldAbsoluteDate<>(field, 2023, 1, 1, 12, 13, 59.12334567, utc);
1484 for (TimeUnit timeUnit : TimeUnit.values()) {
1485 Assertions.assertEquals(field.getZero(), reference.durationFrom(reference, timeUnit));
1486
1487 long dayInTimeUnit = timeUnit.convert((long) Constants.JULIAN_DAY, TimeUnit.SECONDS);
1488 for (int i = 1; i <= 365; i++) {
1489 FieldAbsoluteDate<T> minusDays = reference.shiftedBy(-i * Constants.JULIAN_DAY);
1490 FieldAbsoluteDate<T> plusDays = reference.shiftedBy(i* Constants.JULIAN_DAY);
1491
1492
1493 Assertions.assertEquals(field.getZero().add(i * dayInTimeUnit), reference.durationFrom(minusDays, timeUnit));
1494
1495 Assertions.assertEquals(field.getZero().add(-i * dayInTimeUnit), reference.durationFrom(plusDays, timeUnit));
1496
1497 AbsoluteDate minusDaysA = minusDays.toAbsoluteDate();
1498 AbsoluteDate plusDaysA = plusDays.toAbsoluteDate();
1499
1500 Assertions.assertEquals(field.getZero().add(i * dayInTimeUnit), reference.durationFrom(minusDaysA, timeUnit));
1501
1502 Assertions.assertEquals(field.getZero().add(-i * dayInTimeUnit), reference.durationFrom(plusDaysA, timeUnit));
1503 }
1504
1505 for (long ns = 1; ns <= 1_000_000_000; ns += 1_000_000) {
1506 FieldAbsoluteDate<T> minus = reference.shiftedBy(-1e-9 * ns);
1507 FieldAbsoluteDate<T> plus = reference.shiftedBy(1e-9 * ns);
1508
1509 double deltaInTimeUnit = ns / (double) timeUnit.toNanos(1);
1510 Assertions.assertEquals(field.getZero().add(FastMath.round(deltaInTimeUnit)), reference.durationFrom(minus, timeUnit),
1511 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1512
1513 Assertions.assertEquals(field.getZero().add(FastMath.round(-deltaInTimeUnit)), reference.durationFrom(plus, timeUnit),
1514 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1515
1516 AbsoluteDate minusA = minus.toAbsoluteDate();
1517 AbsoluteDate plusA = plus.toAbsoluteDate();
1518
1519 Assertions.assertEquals(field.getZero().add(FastMath.round(deltaInTimeUnit)), reference.durationFrom(minusA, timeUnit),
1520 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1521
1522 Assertions.assertEquals(field.getZero().add(FastMath.round(-deltaInTimeUnit)), reference.durationFrom(plusA, timeUnit),
1523 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1524 }
1525
1526
1527 }
1528 }
1529
1530 public <T extends CalculusFieldElement<T>> void doTestConstructWithTimeUnitOffset(final Field<T> field) {
1531 FieldAbsoluteDate<T> reference = new FieldAbsoluteDate<>(field, 2023, 1, 1, 12, 13, 59.12334567, utc);
1532
1533 for (TimeUnit timeUnit : TimeUnit.values()) {
1534 Assertions.assertEquals(0,
1535 FastMath.abs(reference.durationFrom(new FieldAbsoluteDate<>(reference, 0, timeUnit)).getReal()), 1e-10);
1536
1537 long dayInTimeUnit = timeUnit.convert((long) Constants.JULIAN_DAY, TimeUnit.SECONDS);
1538 for (int i = 1; i <= 365; i++) {
1539 FieldAbsoluteDate<T> minusDays = reference.shiftedBy(-i * Constants.JULIAN_DAY);
1540 FieldAbsoluteDate<T> plusDays = reference.shiftedBy(i* Constants.JULIAN_DAY);
1541
1542 Assertions.assertEquals(0,
1543 FastMath.abs(reference.durationFrom(new FieldAbsoluteDate<>(minusDays, i * dayInTimeUnit, timeUnit)).getReal()),
1544 1e-10,
1545 String.format("TimeUnit: %s", timeUnit));
1546 Assertions.assertEquals(0,
1547 FastMath.abs(reference.durationFrom(new FieldAbsoluteDate<>(plusDays, -i * dayInTimeUnit, timeUnit)).getReal()),
1548 1e-10,
1549 String.format("TimeUnit: %s", timeUnit));
1550
1551 Assertions.assertEquals(0,
1552 FastMath.abs(reference.durationFrom(new FieldAbsoluteDate<>(minusDays.toAbsoluteDate(), i * dayInTimeUnit, timeUnit, field)).getReal()),
1553 1e-10,
1554 String.format("TimeUnit: %s", timeUnit));
1555 Assertions.assertEquals(0,
1556 FastMath.abs(reference.durationFrom(new FieldAbsoluteDate<>(plusDays.toAbsoluteDate(), -i * dayInTimeUnit, timeUnit, field)).getReal()),
1557 1e-10,
1558 String.format("TimeUnit: %s", timeUnit));
1559 }
1560
1561 for (long ns = 1; ns <= 1_000_000_000; ns += 1_000_000) {
1562 if (timeUnit.convert(1, TimeUnit.SECONDS) < 1) {
1563
1564 continue;
1565 }
1566 FieldAbsoluteDate<T> minus = reference.shiftedBy(-1e-9 * ns);
1567 FieldAbsoluteDate<T> plus = reference.shiftedBy(1e-9 * ns);
1568
1569 double deltaInTimeUnit = ns / (double) timeUnit.toNanos(1);
1570 Assertions.assertEquals(0,
1571 FastMath.abs(reference.durationFrom(new FieldAbsoluteDate<>(minus, FastMath.round(deltaInTimeUnit), timeUnit)).getReal()),
1572 1.0 / timeUnit.convert(1, TimeUnit.SECONDS),
1573 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1574 Assertions.assertEquals(0,
1575 FastMath.abs(reference.durationFrom(new FieldAbsoluteDate<>(plus, FastMath.round(-deltaInTimeUnit), timeUnit)).getReal()),
1576 1.0 / timeUnit.convert(1, TimeUnit.SECONDS),
1577 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1578
1579 Assertions.assertEquals(0,
1580 FastMath.abs(reference.durationFrom(new FieldAbsoluteDate<>(minus.toAbsoluteDate(), FastMath.round(deltaInTimeUnit), timeUnit, field)).getReal()),
1581 1.0 / timeUnit.convert(1, TimeUnit.SECONDS),
1582 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1583 Assertions.assertEquals(0,
1584 FastMath.abs(reference.durationFrom(new FieldAbsoluteDate<>(plus.toAbsoluteDate(), FastMath.round(-deltaInTimeUnit), timeUnit, field)).getReal()),
1585 1.0 / timeUnit.convert(1, TimeUnit.SECONDS),
1586 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1587 }
1588 }
1589 }
1590
1591 public <T extends CalculusFieldElement<T>> void doTestShiftedByWithTimeUnit(final Field<T> field) {
1592 FieldAbsoluteDate<T> reference = new FieldAbsoluteDate<>(field, 2023, 1, 1, 12, 13, 59.12334567, utc);
1593
1594 for (TimeUnit timeUnit : TimeUnit.values()) {
1595 Assertions.assertEquals(0,
1596 FastMath.abs(reference.durationFrom(reference.shiftedBy(0, timeUnit)).getReal()), 1e-10);
1597
1598 long dayInTimeUnit = timeUnit.convert((long) Constants.JULIAN_DAY, TimeUnit.SECONDS);
1599 for (int i = 1; i <= 365; i++) {
1600 FieldAbsoluteDate<T> minusDays = reference.shiftedBy(-i * Constants.JULIAN_DAY);
1601 FieldAbsoluteDate<T> plusDays = reference.shiftedBy(i* Constants.JULIAN_DAY);
1602
1603 Assertions.assertEquals(0,
1604 FastMath.abs(reference.durationFrom(minusDays.shiftedBy( i * dayInTimeUnit, timeUnit)).getReal()),
1605 1e-10,
1606 String.format("TimeUnit: %s", timeUnit));
1607 Assertions.assertEquals(0,
1608 FastMath.abs(reference.durationFrom(plusDays.shiftedBy( -i * dayInTimeUnit, timeUnit)).getReal()),
1609 1e-10,
1610 String.format("TimeUnit: %s", timeUnit));
1611
1612 }
1613
1614 for (long ns = 1; ns <= 1_000_000_000; ns += 1_000_000) {
1615 if (timeUnit.convert(1, TimeUnit.SECONDS) < 1) {
1616
1617 continue;
1618 }
1619 FieldAbsoluteDate<T> minus = reference.shiftedBy(-1e-9 * ns);
1620 FieldAbsoluteDate<T> plus = reference.shiftedBy(1e-9 * ns);
1621
1622 double deltaInTimeUnit = ns / (double) timeUnit.toNanos(1);
1623 Assertions.assertEquals(0,
1624 FastMath.abs(reference.durationFrom(minus.shiftedBy(FastMath.round(deltaInTimeUnit), timeUnit)).getReal()),
1625 1.0 / timeUnit.convert(1, TimeUnit.SECONDS),
1626 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1627 Assertions.assertEquals(0,
1628 FastMath.abs(reference.durationFrom(plus.shiftedBy(FastMath.round(-deltaInTimeUnit), timeUnit)).getReal()),
1629 1.0 / timeUnit.convert(1, TimeUnit.SECONDS),
1630 String.format("TimeUnit: %s, ns: %d", timeUnit, ns));
1631 }
1632 }
1633 }
1634
1635 public <T extends CalculusFieldElement<T>> void doTestToStringWithoutUtcOffset(final Field<T> field) {
1636
1637 FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field,2009, 1, 1, utc);
1638 double one = FastMath.nextDown(1.0);
1639 double zeroUlp = FastMath.nextUp(0.0);
1640 double oneUlp = FastMath.ulp(1.0);
1641
1642 double sixtyUlp = FastMath.ulp(60.0);
1643
1644
1645
1646 checkToStringNoOffset(date, "2009-01-01T00:00:00.000");
1647 checkToStringNoOffset(date.shiftedBy(1), "2009-01-01T00:00:01.000");
1648
1649 checkToStringNoOffset(date.shiftedBy(12.3456789123456789), "2009-01-01T00:00:12.346");
1650 checkToStringNoOffset(date.shiftedBy(0.0123456789123456789), "2009-01-01T00:00:00.012");
1651
1652 checkToStringNoOffset(date.shiftedBy(zeroUlp), "2009-01-01T00:00:00.000");
1653
1654 checkToStringNoOffset(date.shiftedBy(59.0).shiftedBy(one), "2009-01-01T00:01:00.000");
1655
1656 checkToStringNoOffset(date.shiftedBy(86399).shiftedBy(one), "2009-01-02T00:00:00.000");
1657 checkToStringNoOffset(date.shiftedBy(oneUlp), "2009-01-01T00:00:00.000");
1658 checkToStringNoOffset(date.shiftedBy(one), "2009-01-01T00:00:01.000");
1659 checkToStringNoOffset(date.shiftedBy(-zeroUlp), "2009-01-01T00:00:00.000");
1660
1661
1662 checkToStringNoOffset(date.shiftedBy(-oneUlp), "2009-01-01T00:00:00.000");
1663
1664 checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(one), "2009-01-01T00:00:00.000");
1665 checkToStringNoOffset(date.shiftedBy(-0.5), "2008-12-31T23:59:60.500");
1666 checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(zeroUlp), "2008-12-31T23:59:60.000");
1667 checkToStringNoOffset(date.shiftedBy(-1), "2008-12-31T23:59:60.000");
1668 checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(-zeroUlp), "2008-12-31T23:59:60.000");
1669 checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(-oneUlp), "2008-12-31T23:59:60.000");
1670 checkToStringNoOffset(date.shiftedBy(-2), "2008-12-31T23:59:59.000");
1671
1672 checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(-sixtyUlp), "2008-12-31T23:59:60.000");
1673 checkToStringNoOffset(date.shiftedBy(-61).shiftedBy(zeroUlp), "2008-12-31T23:59:00.000");
1674 checkToStringNoOffset(date.shiftedBy(-61).shiftedBy(oneUlp), "2008-12-31T23:59:00.000");
1675 }
1676
1677
1678 private <T extends CalculusFieldElement<T>> void checkToStringNoOffset(final FieldAbsoluteDate<T> d, final String s) {
1679 MatcherAssert.assertThat(d.toStringWithoutUtcOffset(utc, 3), CoreMatchers.is(s));
1680 MatcherAssert.assertThat(
1681 d.getComponents(utc).toStringWithoutUtcOffset(utc.minuteDuration(d), 3),
1682 CoreMatchers.is(s));
1683 }
1684
1685 private <T extends CalculusFieldElement<T>> void check(FieldAbsoluteDate<T> date,
1686 int year, int month, int day, int hour, int minute, double second,
1687 double roundTripUlps, final int secondUlps, final double absTol) {
1688 DateTimeComponents actual = date.getComponents(utc);
1689 DateComponents d = actual.getDate();
1690 TimeComponents t = actual.getTime();
1691 MatcherAssert.assertThat(d.getYear(), CoreMatchers.is(year));
1692 MatcherAssert.assertThat(d.getMonth(), CoreMatchers.is(month));
1693 MatcherAssert.assertThat(d.getDay(), CoreMatchers.is(day));
1694 MatcherAssert.assertThat(t.getHour(), CoreMatchers.is(hour));
1695 MatcherAssert.assertThat(t.getMinute(), CoreMatchers.is(minute));
1696 MatcherAssert.assertThat("second", t.getSecond(),
1697 OrekitMatchers.numberCloseTo(second, absTol, secondUlps));
1698 MatcherAssert.assertThat(t.getMinutesFromUTC(), CoreMatchers.is(0));
1699 final double tol = FastMath.ulp(second) * roundTripUlps;
1700 final double difference = new FieldAbsoluteDate<>(date.getField(), actual, utc)
1701 .durationFrom(date).getReal();
1702 MatcherAssert.assertThat(difference,
1703 OrekitMatchers.closeTo(0, FastMath.max(absTol, tol)));
1704 }
1705
1706 static class AnyFieldTimeStamped<T extends CalculusFieldElement<T>> implements FieldTimeStamped<T> {
1707 AbsoluteDate date;
1708 Field<T> field;
1709
1710 public AnyFieldTimeStamped(Field<T> field, AbsoluteDate date) {
1711 this.date = date;
1712 this.field = field;
1713 }
1714
1715 @Override
1716 public FieldAbsoluteDate<T> getDate() {
1717 return new FieldAbsoluteDate<>(field, date);
1718 }
1719 }
1720
1721 static class TestDates<T extends CalculusFieldElement<T>> {
1722 private final AbsoluteDate presentDate;
1723 private final AnyFieldTimeStamped<T> present;
1724 private final AnyFieldTimeStamped<T> past;
1725 private final AnyFieldTimeStamped<T> presentToo;
1726 private final AnyFieldTimeStamped<T> future;
1727
1728 public TestDates(Field<T> field) {
1729 presentDate = new AbsoluteDate(new DateComponents(2000, 1, 1),
1730 new TimeComponents(12, 0, 0),
1731 TimeScalesFactory.getUTC());
1732 present = new AnyFieldTimeStamped<>(field, presentDate);
1733 presentToo = new AnyFieldTimeStamped<>(field, presentDate.shiftedBy(0));
1734 past = new AnyFieldTimeStamped<>(field, presentDate.shiftedBy(-1000));
1735 future = new AnyFieldTimeStamped<>(field, presentDate.shiftedBy(1000));
1736 }
1737
1738 public FieldAbsoluteDate<T> getPresentFieldAbsoluteDate() {
1739 return present.getDate();
1740 }
1741 }
1742
1743 @Test
1744 public void doTestGetJulianDatesWithBinar64() {
1745
1746 final Field<Binary64> field = Binary64Field.getInstance();
1747
1748
1749 doTestGetJulianDates(field);
1750 }
1751
1752 public <T extends CalculusFieldElement<T>> void doTestGetJulianDates(Field<T> field) {
1753
1754 final T one = field.getOne();
1755 final TimeScale utc = TimeScalesFactory.getUTC();
1756
1757 FieldAbsoluteDate<T> reference = new FieldAbsoluteDate<>(field, 2024, 7, 4, 13, 0, 0, utc);
1758 FieldAbsoluteDate<T> referenceFromJDMethod =
1759 FieldAbsoluteDate.createJDDate(2460496, one.multiply(0.0416667 * Constants.JULIAN_DAY), utc);
1760 FieldAbsoluteDate<T> referenceFromMJDMethod =
1761 FieldAbsoluteDate.createMJDDate(60495, one.multiply(0.54166670 * Constants.JULIAN_DAY), utc);
1762
1763
1764 T mjdDateDefaultData = reference.getMJD();
1765 T jdDateDefaultData = reference.getJD();
1766 T mjdDate = reference.getMJD(utc);
1767 T jdDate = reference.getJD(utc);
1768
1769
1770
1771 Assertions.assertEquals(2460496.0416667, jdDateDefaultData.getReal(), 1.0e-6);
1772 Assertions.assertEquals(60495.54166670, mjdDateDefaultData.getReal(), 1.0e-6);
1773 Assertions.assertEquals(jdDate, jdDateDefaultData);
1774 Assertions.assertEquals(mjdDate, mjdDateDefaultData);
1775
1776
1777 Assertions.assertTrue(reference.isCloseTo(referenceFromJDMethod, 1e-2));
1778 Assertions.assertTrue(reference.isCloseTo(referenceFromMJDMethod, 1e-2));
1779 }
1780
1781 @Test
1782 void testGetJD() {
1783
1784 final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
1785 final FieldAbsoluteDate<UnivariateDerivative1> fieldDate = new FieldAbsoluteDate<>(UnivariateDerivative1Field.getInstance(),
1786 date).shiftedBy(new UnivariateDerivative1(0., 1));
1787
1788 final UnivariateDerivative1 jdField = fieldDate.getJD();
1789
1790 final double shift = 10.;
1791 final FieldAbsoluteDate<UnivariateDerivative1> shiftedDate = fieldDate.shiftedBy(shift);
1792 final double expectedJdDerivative = (shiftedDate.getJD().getReal() - jdField.getReal()) / shift;
1793 Assertions.assertEquals(expectedJdDerivative, jdField.getFirstDerivative(), 1e-10);
1794 }
1795
1796 @Test
1797 void testGetMJD() {
1798
1799 final AbsoluteDate date = AbsoluteDate.ARBITRARY_EPOCH;
1800 final FieldAbsoluteDate<UnivariateDerivative1> fieldDate = new FieldAbsoluteDate<>(UnivariateDerivative1Field.getInstance(),
1801 date).shiftedBy(new UnivariateDerivative1(0., 1));
1802
1803 final UnivariateDerivative1 mjdField = fieldDate.getMJD();
1804
1805 final double shift = 10.;
1806 final FieldAbsoluteDate<UnivariateDerivative1> shiftedDate = fieldDate.shiftedBy(shift);
1807 final double expectedMjdDerivative = (shiftedDate.getMJD().getReal() - mjdField.getReal()) / shift;
1808 Assertions.assertEquals(expectedMjdDerivative, mjdField.getFirstDerivative(), 1e-10);
1809 }
1810
1811 @Test
1812 void testMedian() {
1813 final AbsoluteDate date1 = new AbsoluteDate(2003, 6, 13, 14, 15,
1814 new TimeOffset(53, TimeOffset.SECOND, 12, TimeOffset.ATTOSECOND),
1815 TimeScalesFactory.getTT());
1816 final FieldAbsoluteDate<UnivariateDerivative1> fieldDate1 =
1817 new FieldAbsoluteDate<>(UnivariateDerivative1Field.getInstance(), date1).
1818 shiftedBy(new UnivariateDerivative1(0.0, 1.0));
1819 final AbsoluteDate date2 = new AbsoluteDate(2003, 6, 13, 14, 17,
1820 new TimeOffset(25, TimeOffset.SECOND, 120, TimeOffset.ATTOSECOND),
1821 TimeScalesFactory.getTT());
1822 final FieldAbsoluteDate<UnivariateDerivative1> fieldDate2 =
1823 new FieldAbsoluteDate<>(UnivariateDerivative1Field.getInstance(), date2).
1824 shiftedBy(new UnivariateDerivative1(0.0, 2.0));
1825 final AbsoluteDate dateM = new AbsoluteDate(2003, 6, 13, 14, 16,
1826 new TimeOffset(39, TimeOffset.SECOND, 66, TimeOffset.ATTOSECOND),
1827 TimeScalesFactory.getTT());
1828 final FieldAbsoluteDate<UnivariateDerivative1> fieldDateM =
1829 new FieldAbsoluteDate<>(UnivariateDerivative1Field.getInstance(), dateM).
1830 shiftedBy(new UnivariateDerivative1(0.0, 1.5));
1831 Assertions.assertEquals(fieldDateM, FieldAbsoluteDate.createMedian(fieldDate1, fieldDate2));
1832 Assertions.assertEquals(fieldDateM, FieldAbsoluteDate.createMedian(fieldDate2, fieldDate1));
1833 }
1834
1835 @Test
1836 void testMedianInfinite() {
1837 final FieldAbsoluteDate<Binary64> future = FieldAbsoluteDate.getFutureInfinity(Binary64Field.getInstance());
1838 final FieldAbsoluteDate<Binary64> past = FieldAbsoluteDate.getPastInfinity(Binary64Field.getInstance());
1839 final FieldAbsoluteDate<Binary64> arbitrary = FieldAbsoluteDate.getArbitraryEpoch(Binary64Field.getInstance());
1840 Assertions.assertEquals(future, FieldAbsoluteDate.createMedian(future, arbitrary));
1841 Assertions.assertEquals(past, FieldAbsoluteDate.createMedian(past, arbitrary));
1842 }
1843
1844 @Test
1845 void testToFUD2Field() {
1846
1847 final Field<Binary64> field = Binary64Field.getInstance();
1848 final FieldAbsoluteDate<Binary64> date = FieldAbsoluteDate.getArbitraryEpoch(field);
1849
1850 final FieldAbsoluteDate<FieldUnivariateDerivative2<Binary64>> ud2Date = date.toFUD2Field();
1851
1852 Assertions.assertEquals(date.toAbsoluteDate(), ud2Date.toAbsoluteDate());
1853 final FieldUnivariateDerivative2<Binary64> shift = ud2Date.durationFrom(date.toAbsoluteDate());
1854 Assertions.assertEquals(field.getOne(), shift.getFirstDerivative());
1855 Assertions.assertEquals(field.getZero(), shift.getSecondDerivative());
1856 }
1857
1858 private <T extends CalculusFieldElement<T>> void doTestGetDayOfYear(final Field<T> field) {
1859 Assertions.assertEquals(0.501,
1860 new FieldAbsoluteDate<>(field,
1861 new AbsoluteDate(2004, 1, 1, 0, 0, 0.001, utc)).
1862 getDayOfYear(utc).getReal(),
1863 1.0e-3);
1864 Assertions.assertEquals(1.000,
1865 new FieldAbsoluteDate<>(field,
1866 new AbsoluteDate(2004, 1, 1, 12, 0, 0.000, utc)).
1867 getDayOfYear(utc).getReal(),
1868 1.0e-3);
1869 Assertions.assertEquals(366.0,
1870 new FieldAbsoluteDate<>(field,
1871 new AbsoluteDate(2004, 12, 31, 12, 0, 0.000, utc)).
1872 getDayOfYear(utc).getReal(),
1873 1.0e-3);
1874 Assertions.assertEquals(366.499999988426,
1875 new FieldAbsoluteDate<>(field,
1876 new AbsoluteDate(2004, 12, 31, 23, 59, 59.999, utc)).
1877 getDayOfYear(utc).getReal(),
1878 1.0e-12);
1879 Assertions.assertEquals(0.500000011574,
1880 new FieldAbsoluteDate<>(field,
1881 new AbsoluteDate(2004, 12, 31, 23, 59, 59.999, utc).shiftedBy(0.002)).
1882 getDayOfYear(utc).getReal(),
1883 1.0e-12);
1884 }
1885
1886 }