All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yamcs.utils.TimeEncoding Maven / Gradle / Ivy

There is a newer version: 5.10.1
Show newest version
package org.yamcs.utils;

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * This class provides times in terms of milliseconds since 1970TAI
 * 
 * @author nm
 *
 */
public class TimeEncoding {
    public static final long INVALID_INSTANT = Long.MIN_VALUE;
    // these two are used for open intervals
    public static final long MIN_INSTANT = Long.MIN_VALUE;
    public static long MAX_INSTANT = 185539080470435999L;

    static final long GPS_EPOCH_YAMCS_EPOCH_DELTA = 315964819000L;
    static final long TAI_EPOCH_YAMCS_EPOCH_DELTA = -378691191000L;
    static final long J2000_EPOCH_YAMCS_EPOCH_DELTA = 946727967816L;
    
    static final long GPS_TAI_DELTA = 19000;

    static TaiUtcConverter taiUtcConverter;
    static Pattern iso8601Pattern = Pattern
            .compile("(\\d+)\\-(\\d{2})\\-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(\\.(\\d{3}))?Z?");
    static Pattern doyPattern = Pattern.compile("(\\d+)\\/(\\d+)T(\\d{2}):(\\d{2}):(\\d{2})(\\.(\\d{3}))?");

    public static void setUp() throws RuntimeException {
        try {
            taiUtcConverter = new TaiUtcConverter();
            MAX_INSTANT = 185539080470399999L + taiUtcConverter.diffTaiUtc * 1000;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns the current wall clock time. Is the same with getWallclockTime
     *
     * Should use instead timeService.getMissionTime()
     *
     * @return
     */
    @Deprecated
    public static long currentInstant() {
        return taiUtcConverter.unixToInstant(System.currentTimeMillis());
    }

    public static long getWallclockTime() {
        return taiUtcConverter.unixToInstant(System.currentTimeMillis());
    }

    private static void formatOn2Digits(int x, StringBuilder sb) {
        if (x < 10)
            sb.append("0").append(x);
        else
            sb.append(x);
    }

    private static void formatOn3Digits(int x, StringBuilder sb) {
        if (x < 10)
            sb.append("00").append(x);
        else if (x < 100)
            sb.append("0").append(x);
        else
            sb.append(x);
    }

    private static void formatOn4Digits(int x, StringBuilder sb) {
        if (x < 10)
            sb.append("000").append(x);
        else if (x < 100)
            sb.append("00").append(x);
        else if (x < 1000)
            sb.append("0").append(x);
        else
            sb.append(x);
    }

    /**
     * Returns the instant formatted as UTC yyyy-MM-DDTHH:mm:ss.SSSZ
     * 
     * @param instant
     * @return
     */
    public static String toString(long instant) {
        TaiUtcConverter.DateTimeComponents dtc = taiUtcConverter.instantToUtc(instant);
        StringBuilder sb = new StringBuilder();
        formatOn4Digits(dtc.year, sb);
        sb.append("-");
        formatOn2Digits(dtc.month, sb);
        sb.append("-");
        formatOn2Digits(dtc.day, sb);
        sb.append("T");
        formatOn2Digits(dtc.hour, sb);
        sb.append(":");
        formatOn2Digits(dtc.minute, sb);
        sb.append(":");
        formatOn2Digits(dtc.second, sb);
        sb.append(".");
        formatOn3Digits(dtc.millisec, sb);
        return sb.append("Z").toString();
    }

    /**
     * Returns the instant formatted as UTC yyyy-DDDTHH:mm:ss.SSS
     * 
     * @param instant
     * @return
     */
    public static String toOrdinalDateTime(long instant) {
        TaiUtcConverter.DateTimeComponents dtc = taiUtcConverter.instantToUtc(instant);
        StringBuilder sb = new StringBuilder();
        formatOn4Digits(dtc.year, sb);
        sb.append("-");
        formatOn3Digits(dtc.doy, sb);
        sb.append("T");
        formatOn2Digits(dtc.hour, sb);
        sb.append(":");
        formatOn2Digits(dtc.minute, sb);
        sb.append(":");
        formatOn2Digits(dtc.second, sb);
        sb.append(".");
        formatOn3Digits(dtc.millisec, sb);
        return sb.toString();
    }

    /**
     * Returns the instant in UTC time scale formatted as YYYY-DDDTHHhMMmSSsSSS so that is leads to an MS Windows
     * compatible filename
     * 
     * @param instant
     * @return
     */
    public static String toWinCompatibleDateTime(long instant) {
        TaiUtcConverter.DateTimeComponents dtc = taiUtcConverter.instantToUtc(instant);
        StringBuilder sb = new StringBuilder();
        formatOn4Digits(dtc.year, sb);
        sb.append("-");
        formatOn3Digits(dtc.doy, sb);
        sb.append("T");
        formatOn2Digits(dtc.hour, sb);
        sb.append("h");
        formatOn2Digits(dtc.minute, sb);
        sb.append("m");
        formatOn2Digits(dtc.second, sb);
        sb.append("s");
        formatOn3Digits(dtc.millisec, sb);
        return sb.toString();
    }

    public static String toCombinedFormat(long instant) {
        TaiUtcConverter.DateTimeComponents dtc = taiUtcConverter.instantToUtc(instant);
        StringBuilder sb = new StringBuilder();
        formatOn4Digits(dtc.year, sb);
        sb.append("-");
        formatOn2Digits(dtc.month, sb);
        sb.append("-");
        formatOn2Digits(dtc.day, sb);
        sb.append("/");
        formatOn3Digits(dtc.doy, sb);
        sb.append("T");
        formatOn2Digits(dtc.hour, sb);
        sb.append(":");
        formatOn2Digits(dtc.minute, sb);
        sb.append(":");
        formatOn2Digits(dtc.second, sb);
        sb.append(".");
        formatOn3Digits(dtc.millisec, sb);
        return sb.toString();
    }

    /**
     * we assume coarseTime to be always positive (corresponding to uint32_t in C)
     * 
     * @param coarseTime
     *            number of seconds from GPS epoch
     * @param fineTime
     *            number of 1/256 seconds
     * @return
     */
    public static long fromGpsCcsdsTime(int coarseTime, byte fineTime) {
        long c = ((long) coarseTime) & 0xFFFFFFFFL;
        return GPS_EPOCH_YAMCS_EPOCH_DELTA + c * 1000 + 1000 * (0xFF & fineTime) / 256;
    }

    /**
     * Conversion from instant to GPS time.
     * 
     * @param instant
     *            yamcs time
     * @return GPS time
     */
    public static GpsCcsdsTime toGpsTime(final long instant) {
        GpsCcsdsTime gpsTime = new GpsCcsdsTime();
        long shiftedMillis = instant - GPS_EPOCH_YAMCS_EPOCH_DELTA;
        gpsTime.coarseTime = (int) (shiftedMillis / 1000);
        gpsTime.fineTime = (byte) (((shiftedMillis % 1000) * 256 / 1000));
        return gpsTime;
    }

    /**
     * Conversion from current instant to GPS time. Current time is the *nix time this function is called.
     * 
     * @return GPS time
     */
    public static GpsCcsdsTime getCurrentGpsTime() {
        return toGpsTime(TimeEncoding.currentInstant());
    }

    /**
     * Conversion from instant to GPS time (milliseconds since the GPS epoch).
     * 
     * @param instant
     *            TimeEncoding instant
     *
     * @return GPS time
     */
    public static long toGpsTimeMillisec(final long instant) {
        return instant - GPS_EPOCH_YAMCS_EPOCH_DELTA;
    }

    public static long fromGpsYearSecMillis(int year, int secOfYear, int millis) {
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        cal.clear();
        cal.set(Calendar.YEAR, year);
        cal.add(Calendar.SECOND, secOfYear);
        cal.add(Calendar.MILLISECOND, millis);

        return GPS_TAI_DELTA + cal.getTimeInMillis();
    }

    public static TaiUtcConverter.DateTimeComponents toUtc(long instant) {
        return taiUtcConverter.instantToUtc(instant);
    }

    /**
     * parses an ISO 8601 UTC date into an instant
     * 
     * @param s
     * @return
     */
    public static long parse(String s) {
        TaiUtcConverter.DateTimeComponents dtc;
        Matcher m = iso8601Pattern.matcher(s);

        if (m.matches()) {

            int year = Integer.parseInt(m.group(1));
            int month = Integer.parseInt(m.group(2));
            int day = Integer.parseInt(m.group(3));
            int hour = Integer.parseInt(m.group(4));
            int minute = Integer.parseInt(m.group(5));
            int second = Integer.parseInt(m.group(6));
            int millisec = 0;
            if (m.group(7) != null) {
                millisec = Integer.parseInt(m.group(8));
            }
            dtc = new TaiUtcConverter.DateTimeComponents(year, month, day, hour, minute, second, millisec);
        } else {
            m = doyPattern.matcher(s);
            if (m.matches()) {
                int year = Integer.parseInt(m.group(1));
                int doy = Integer.parseInt(m.group(2));
                int hour = Integer.parseInt(m.group(3));
                int minute = Integer.parseInt(m.group(4));
                int second = Integer.parseInt(m.group(5));
                int millisec = 0;
                if (m.group(6) != null) {
                    millisec = Integer.parseInt(m.group(7));
                }

                dtc = new TaiUtcConverter.DateTimeComponents(year, doy, hour, minute, second, millisec);

            } else {
                throw new IllegalArgumentException(
                        "Cannot parse '" + s + "' with the pattern '" + iso8601Pattern + " or " + doyPattern);
            }
        }
        return taiUtcConverter.utcToInstant(dtc);
    }

    /**
     * Transforms UNIX time (milliseconds since 1970) to instant
     * 
     * @param milliseconds
     * @return
     * @deprecated use {@link fromUnixMillisec}
     */
    @Deprecated
    public static long fromUnixTime(long milliseconds) {
        return fromUnixMillisec(milliseconds);
    }
    
    /**
     * Transforms UNIX time (milliseconds since 1970) to instant
     * 
     * @param milliseconds
     * @return
     */
    public static long fromUnixMillisec(long milliseconds) {
        return taiUtcConverter.unixToInstant(milliseconds);
    }
    /**
     * Transforms UNIX time expressed in seconds and microseconds since 1970 to instant WARNING: this conversion will
     * loose precision (microsecond to millisecond)
     *
     * @param seconds
     * @param microseconds
     * @return
     */
    public static long fromUnixTime(long seconds, int microseconds) {
        long millisec = seconds * 1000 + microseconds / 1000;
        return taiUtcConverter.unixToInstant(millisec);
    }

    /**
     * Transforms instant to UNIX time expressed in milliseconds since 1970
     * 
     * @param instant
     * @return
     */
    public static long toUnixTime(long instant) {
        return taiUtcConverter.instantToUnix(instant);
    }

    /**
     * Transforms the cal from UNIX (millisec since 1970) to instant
     * 
     * @param cal
     * @return
     */
    public static long fromCalendar(Calendar cal) {
        return fromUnixMillisec(cal.getTimeInMillis());
    }

    /**
     * Transforms a Date from UNIX (millisec since 1970) to instant
     */
    public static long fromDate(Date date) {
        return fromUnixTime(date.getTime());
    }

    /**
     * transforms instant into a java cal containing milliseconds since 1970
     * 
     * @param instant
     * @return
     */
    public static Calendar toCalendar(long instant) {
        if (instant == TimeEncoding.INVALID_INSTANT)
            return null;
        long t = taiUtcConverter.instantToUnix(instant);
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(t);
        return cal;
    }

    /**
     * JavaGps is number of milliseconds since 1970 that assumes no leap seconds from 1970 to GPS Epoch, and then
     * continues with the leap seconds.
     * 
     * @param instant
     * @return
     */
    public static long getJavaGpsFromInstant(long instant) {
        return instant - 19000;
    }

    public static long getInstantfromJavaGps(long javagps) {
        return javagps + 19000;
    }

    /**
     *
     * @param gpstime
     *            number of millisec from GPS epoch
     * @return
     */
    public static long fromGpsMillisec(long gpstime) {
        return gpstime + GPS_EPOCH_YAMCS_EPOCH_DELTA;
    }

    public static long fromTaiMillisec(long taitime) {
        return taitime + TAI_EPOCH_YAMCS_EPOCH_DELTA;
    }
    
    public static long fromJ2000Millisec(long j2000time) {
        return j2000time + J2000_EPOCH_YAMCS_EPOCH_DELTA;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy