UTCTAIOffset.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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. import java.io.Serializable;

  19. import org.hipparchus.RealFieldElement;
  20. import org.orekit.utils.Constants;

  21. /** Offset between {@link UTCScale UTC} and  {@link TAIScale TAI} time scales.
  22.  * <p>The {@link UTCScale UTC} and  {@link TAIScale TAI} time scales are two
  23.  * scales offset with respect to each other. The {@link TAIScale TAI} scale is
  24.  * continuous whereas the {@link UTCScale UTC} includes some discontinuity when
  25.  * leap seconds are introduced by the <a href="http://www.iers.org/">International
  26.  * Earth Rotation Service</a> (IERS).</p>
  27.  * <p>This class represents the offset between the two scales that is
  28.  * valid between two leap seconds occurrences. It handles both the linear offsets
  29.  * used from 1961-01-01 to 1971-12-31 and the constant integer offsets used since
  30.  * 1972-01-01.</p>
  31.  * @author Luc Maisonobe
  32.  * @see UTCScale
  33.  * @see UTCTAIHistoryFilesLoader
  34.  */
  35. class UTCTAIOffset implements TimeStamped, Serializable {

  36.     /** Serializable UID. */
  37.     private static final long serialVersionUID = 4742190573136348054L;

  38.     /** Leap date. */
  39.     private final AbsoluteDate leapDate;

  40.     /** Leap date in Modified Julian Day. */
  41.     private final int leapDateMJD;

  42.     /** Offset start of validity date. */
  43.     private final AbsoluteDate validityStart;

  44.     /** Reference date for the slope multiplication as Modified Julian Day. */
  45.     private final int mjdRef;

  46.     /** Reference date for the slope multiplication. */
  47.     private final AbsoluteDate reference;

  48.     /** Value of the leap at offset validity start (in seconds). */
  49.     private final double leap;

  50.     /** Offset at validity start in seconds (TAI minus UTC). */
  51.     private final double offset;

  52.     /** Offset slope in seconds per UTC second (TAI minus UTC / dUTC). */
  53.     private final double slopeUTC;

  54.     /** Offset slope in seconds per TAI second (TAI minus UTC / dTAI). */
  55.     private final double slopeTAI;

  56.     /** Simple constructor for a constant model.
  57.      * @param leapDate leap date
  58.      * @param leapDateMJD leap date in Modified Julian Day
  59.      * @param leap value of the leap at offset validity start (in seconds)
  60.      * @param offset offset in seconds (TAI minus UTC)
  61.      */
  62.     UTCTAIOffset(final AbsoluteDate leapDate, final int leapDateMJD,
  63.                         final double leap, final double offset) {
  64.         this(leapDate, leapDateMJD, leap, offset, 0, 0);
  65.     }

  66.     /** Simple constructor for a linear model.
  67.      * @param leapDate leap date
  68.      * @param leapDateMJD leap date in Modified Julian Day
  69.      * @param leap value of the leap at offset validity start (in seconds)
  70.      * @param offset offset in seconds (TAI minus UTC)
  71.      * @param mjdRef reference date for the slope multiplication as Modified Julian Day
  72.      * @param slope offset slope in seconds per UTC second (TAI minus UTC / dUTC)
  73.      */
  74.     UTCTAIOffset(final AbsoluteDate leapDate, final int leapDateMJD,
  75.                         final double leap, final double offset,
  76.                         final int mjdRef, final double slope) {
  77.         this.leapDate      = leapDate;
  78.         this.leapDateMJD   = leapDateMJD;
  79.         this.validityStart = leapDate.shiftedBy(leap);
  80.         this.mjdRef        = mjdRef;
  81.         this.reference     = new AbsoluteDate(new DateComponents(DateComponents.MODIFIED_JULIAN_EPOCH, mjdRef),
  82.                                               TimeScalesFactory.getTAI()).shiftedBy(offset);
  83.         this.leap          = leap;
  84.         this.offset        = offset;
  85.         this.slopeUTC      = slope;
  86.         this.slopeTAI      = slope / (1 + slope);
  87.     }

  88.     /** Get the date of the start of the leap.
  89.      * @return date of the start of the leap
  90.      * @see #getValidityStart()
  91.      */
  92.     public AbsoluteDate getDate() {
  93.         return leapDate;
  94.     }

  95.     /** Get the date of the start of the leap as Modified Julian Day.
  96.      * @return date of the start of the leap as Modified Julian Day
  97.      */
  98.     public int getMJD() {
  99.         return leapDateMJD;
  100.     }

  101.     /** Get the start time of validity for this offset.
  102.      * <p>The start of the validity of the offset is {@link #getLeap()}
  103.      * seconds after the start of the leap itself.</p>
  104.      * @return start of validity date
  105.      * @see #getDate()
  106.      */
  107.     public AbsoluteDate getValidityStart() {
  108.         return validityStart;
  109.     }

  110.     /** Get the value of the leap at offset validity start (in seconds).
  111.      * @return value of the leap at offset validity start (in seconds)
  112.      */
  113.     public double getLeap() {
  114.         return leap;
  115.     }

  116.     /** Get the TAI - UTC offset in seconds.
  117.      * @param date date at which the offset is requested
  118.      * @return TAI - UTC offset in seconds.
  119.      */
  120.     public double getOffset(final AbsoluteDate date) {
  121.         if (slopeTAI == 0) {
  122.             // we use an if statement here so the offset computation returns
  123.             // a finite value when date is AbsoluteDate.FUTURE_INFINITY
  124.             // without this if statement, the multiplication between an
  125.             // infinite duration and a zero slope would induce a NaN offset
  126.             return offset;
  127.         } else {
  128.             return offset + date.durationFrom(reference) * slopeTAI;
  129.         }
  130.     }

  131.     /** Get the TAI - UTC offset in seconds.
  132.      * @param date date at which the offset is requested
  133.      * @param <T> type of the filed elements
  134.      * @return TAI - UTC offset in seconds.
  135.      * @since 9.0
  136.      */
  137.     public <T extends RealFieldElement<T>> T getOffset(final FieldAbsoluteDate<T> date) {
  138.         if (slopeTAI == 0) {
  139.             // we use an if statement here so the offset computation returns
  140.             // a finite value when date is FieldAbsoluteDate.getFutureInfinity(field)
  141.             // without this if statement, the multiplication between an
  142.             // infinite duration and a zero slope would induce a NaN offset
  143.             return date.getField().getZero().add(offset);
  144.         } else {
  145.             return date.durationFrom(reference).multiply(slopeTAI).add(offset);
  146.         }
  147.     }

  148.     /** Get the TAI - UTC offset in seconds.
  149.      * @param date date components (in UTC) at which the offset is requested
  150.      * @param time time components (in UTC) at which the offset is requested
  151.      * @return TAI - UTC offset in seconds.
  152.      */
  153.     public double getOffset(final DateComponents date, final TimeComponents time) {
  154.         final int    days     = date.getMJD() - mjdRef;
  155.         final double fraction = time.getSecondsInUTCDay();
  156.         return offset + days * (slopeUTC * Constants.JULIAN_DAY) + fraction * slopeUTC;
  157.     }

  158. }