org.yamcs.utils.TimeEncoding Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yamcs-api Show documentation
Show all versions of yamcs-api Show documentation
Used by external clients to communicate with Yamcs
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;
}
}