CcsdsSegmentedTimeCode.java
- /* Copyright 2002-2025 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.time;
- import org.orekit.errors.OrekitException;
- import org.orekit.errors.OrekitMessages;
- /** This class represents a CCSDS segmented time code.
- * @author Luc Maisonobe
- * @since 12.1
- * @see AbsoluteDate
- * @see FieldAbsoluteDate
- */
- class CcsdsSegmentedTimeCode extends AbstractCcsdsTimeCode {
- /** Date part. */
- private final DateComponents date;
- /** Time part. */
- private final TimeComponents time;
- /** Create an instance CCSDS Day Segmented Time Code (CDS).
- * <p>
- * CCSDS Day Segmented Time Code is defined in the blue book:
- * CCSDS Time Code Format (CCSDS 301.0-B-4) published in November 2010
- * </p>
- * @param preambleField field specifying the format, often not transmitted in
- * data interfaces, as it is constant for a given data interface
- * @param timeField byte array containing the time code
- * @param agencyDefinedEpoch reference epoch, ignored if the preamble field
- * specifies the {@link DateComponents#CCSDS_EPOCH CCSDS reference epoch} is used
- * (and hence may be null in this case)
- */
- CcsdsSegmentedTimeCode(final byte preambleField, final byte[] timeField,
- final DateComponents agencyDefinedEpoch) {
- // time code identification
- if ((preambleField & 0xF0) != 0x40) {
- throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_PREAMBLE_FIELD,
- formatByte(preambleField));
- }
- // reference epoch
- final DateComponents epoch;
- if ((preambleField & 0x08) == 0x00) {
- // the reference epoch is CCSDS epoch 1958-01-01T00:00:00 TAI
- epoch = DateComponents.CCSDS_EPOCH;
- } else {
- // the reference epoch is agency defined
- if (agencyDefinedEpoch == null) {
- throw new OrekitException(OrekitMessages.CCSDS_DATE_MISSING_AGENCY_EPOCH);
- }
- epoch = agencyDefinedEpoch;
- }
- // time field lengths
- final int daySegmentLength = ((preambleField & 0x04) == 0x0) ? 2 : 3;
- final int subMillisecondLength = (preambleField & 0x03) << 1;
- if (subMillisecondLength == 6) {
- throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_PREAMBLE_FIELD,
- formatByte(preambleField));
- }
- if (timeField.length != daySegmentLength + 4 + subMillisecondLength) {
- throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_LENGTH_TIME_FIELD,
- timeField.length, daySegmentLength + 4 + subMillisecondLength);
- }
- int i = 0;
- int day = 0;
- while (i < daySegmentLength) {
- day = day * 256 + toUnsigned(timeField[i++]);
- }
- long milliInDay = 0L;
- while (i < daySegmentLength + 4) {
- milliInDay = milliInDay * 256 + toUnsigned(timeField[i++]);
- }
- final int milli = (int) (milliInDay % 1000L);
- final int seconds = (int) ((milliInDay - milli) / 1000L);
- long subMilli = 0;
- while (i < timeField.length) {
- subMilli = subMilli * 256 + toUnsigned(timeField[i++]);
- }
- final TimeOffset timeOffset =
- new TimeOffset(seconds, TimeOffset.SECOND,
- milli, TimeOffset.MILLISECOND,
- subMilli, subMillisecondLength == 2 ? TimeOffset.MICROSECOND : TimeOffset.PICOSECOND);
- this.date = new DateComponents(epoch, day);
- this.time = new TimeComponents(timeOffset);
- }
- /** Build an instance from a CCSDS Calendar Segmented Time Code (CCS).
- * <p>
- * CCSDS Calendar Segmented Time Code is defined in the blue book:
- * CCSDS Time Code Format (CCSDS 301.0-B-4) published in November 2010
- * </p>
- * @param preambleField field specifying the format, often not transmitted in
- * data interfaces, as it is constant for a given data interface
- * @param timeField byte array containing the time code
- */
- CcsdsSegmentedTimeCode(final byte preambleField, final byte[] timeField) {
- // time code identification
- if ((preambleField & 0xF0) != 0x50) {
- throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_PREAMBLE_FIELD,
- formatByte(preambleField));
- }
- // time field length
- final int length = 7 + (preambleField & 0x07);
- if (length == 14) {
- throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_PREAMBLE_FIELD,
- formatByte(preambleField));
- }
- if (timeField.length != length) {
- throw new OrekitException(OrekitMessages.CCSDS_DATE_INVALID_LENGTH_TIME_FIELD,
- timeField.length, length);
- }
- // date part in the first four bytes
- if ((preambleField & 0x08) == 0x00) {
- // month of year and day of month variation
- this.date = new DateComponents(toUnsigned(timeField[0]) * 256 + toUnsigned(timeField[1]),
- toUnsigned(timeField[2]),
- toUnsigned(timeField[3]));
- } else {
- // day of year variation
- this.date = new DateComponents(toUnsigned(timeField[0]) * 256 + toUnsigned(timeField[1]),
- toUnsigned(timeField[2]) * 256 + toUnsigned(timeField[3]));
- }
- // time part from bytes 5 to last (between 7 and 13 depending on precision)
- final int hour = toUnsigned(timeField[4]);
- final int minute = toUnsigned(timeField[5]);
- final int second = toUnsigned(timeField[6]);
- final int secondInDay = 3600 * hour + 60 * minute + second;
- long sub = 0;
- long attoSecondMultiplier = 1000000000000000000L;
- for (int i = 7; i < length; ++i) {
- sub = sub * 100L + toUnsigned(timeField[i]);
- attoSecondMultiplier /= 100L;
- }
- this.time = new TimeComponents(new TimeOffset(secondInDay, sub * attoSecondMultiplier));
- }
- /** Get the date part.
- * @return date part
- */
- public DateComponents getDate() {
- return date;
- }
- /** Get the time part.
- * @return time part
- */
- public TimeComponents getTime() {
- return time;
- }
- }