The "Time" package is an independent package providing classes to handle epochs, time scales, and to compare instants between them.
The principal class is AbsoluteDate which represents a unique instant in time, and to be able to locate it with respect to the many different times scales in use in the space dynamics and astronomy fields.
This greatly simplifies development as it hides some models internals. For example when using JPL-based ephemerides, time must be in Terrestrial Time (formerly known as Ephemeris Time). However, this is a implementation detail and someone calling Orekit from an high level application should not deal with it. The AbsoluteDate class allows users to pass a date regardless of the time scale it was defined in, conversions will be added as required transparently.
Dates are commonly defined by specifying a location in a specific time scale . For example, the J2000.0 epoch is defined from its calendar components as 2000-01-01T12:00:00 in Terrestrial Time. It is of prime importance to understand the various available time scales definitions to avoid mistakes. Orekit provides 5 of the most important ones:
There are three main ways to define a date:
The first option is the more straightforward one, but is not sufficient for some needs. The two last options are confusingly similar, because of the complexity of time scales. Understanding the differences between the two is a key point to avoid large errors.
An apparent seconds offset is the difference between two readings on a clock synchronized with a time scale. If for example the first reading is 23:59:59 and the second reading is 00:00:00, the the apparent seconds offset is 1 second. An elapsed duration is the count of seconds that could be measured by a stop watch started at the first instant and stopped at the second instant. Most of the time, both times are identical. However, if the time scale is UTC and if the readings are made when a leap second is introduced, then the duration elapsed between the two events is 2 seconds and not 1 second!
The method offsetFrom method which takes both a date and a time scale as parameters computes the apparent offset. The durationFrom method which takes only a date as parameter computes the elapsed duration. In the exemple above, the first method would return 1 second while the second method would return 2 seconds:
TimeScale utc = UTCScale.getInstance(); AbsoluteDate start = new AbsoluteDate(2005, 12, 31, 23, 59, 59, utc); AbsoluteDate stop = new AbsoluteDate(2006, 1, 1, 0, 0, 0, utc); System.out.println(stop.offsetFrom(start, utc)); // prints 1.0 System.out.println(stop.durationFrom(start)); // prints 2.0
This property is used in reverse to define dates. We can define the second instant either as the instance which will occur when the reading of the clock is one second away for the reading if the first date. We can also define it as the instant occurring when two seconds have elapsed since the first instant, without any reference to an external clock. Both approaches are possible, it depends on the available data and its meaning. The following code shows both approaches:
TimeScale utc = UTCScale.getInstance(); AbsoluteDate referenceDate = new AbsoluteDate(2005, 12, 31, 23, 59, 59, utc); AbsoluteDate date1 = new AbsoluteDate(referenceDate, 1.0, utc); AbsoluteDate date2 = new AbsoluteDate(referenceDate, 2.0);
The two variables date1 and date2 represent the same instant. The first one has been defined relatively to a time scale, the second one has been defined independently of any time scale.
Orekit defines 6 reference epochs. The first 5 are commonly used in the space community and the last one is commonly used in the computer science field.
Once it is built, an AbsoluteDate can be compared to other ones, and converted and expressed in other time scales. It is used to define states, orbits, frames...
Classes that include a date implement the TimeStamped interface. The ChronologicalComparator singleton can sort objects implementing this interface chronologically. This is particularly interesting for ephemerides. One trick that can be used for such collections is too really define them using generic TimeStamped instances as in the following example. The trick is that we want to be allowed to use AbsoluteDate instances in methods like headSet , tailSet or subSet .
public class MyClass implements TimeStamped {
...
}
public class Ephemeris {
// we declare the ephemeris as containing general TimeStamped instances
private TreeSet<TimeStamped> ephemeris;
public Ephemeris(MyClass[] array) {
ephemeris = new TreeSet<TimeStamped>(ChronologicalComparator.getInstance());
for (int i = 0; i < n; ++i) {
ephemeris.add(new MyClass(...));
}
}
public MyClass getBefore(AbsoluteDate date) {
// since AbsoluteDate implements TimeStamped, we can do the following
return (MyClass) ephemeris.headSet(date).last();
}
public MyClass getAfter(AbsoluteDate date) {
// since AbsoluteDate implements TimeStamped, we can do the following
return (MyClass) ephemeris.tailSet(date).first();
}
}