Class DisTime
DIS time units are a pain to work with. DIS time units are arbitrary, and set equal to 2^31 - 1 time units per hour. The DIS time is set to the number of time units since the start of the hour. The timestamp field in the PDU header is four bytes long and is specified to be an unsigned integer value.
There are two types of official timestamps in the PDU header: absolute time and relative time. Absolute time is used when the host is synchronized to UTC, i.e. the host has access to UTC via Network Time Protocol (NTP). This time can be legitimately compared to the timestamp of packets received from other hosts, since they all refer to the same universal time.
Relative timestamps are used when the host does NOT have access to NTP, and hence the system time might not be coordinated with that of other hosts. This means that a host receiving DIS packets from several hosts might have to set up a per-host table to order packets, and that the PDU timestamp fields from one host is not directly comparable to the PDU timestamp field from another host.
Absolute timestamps have their LSB set to 1, and relative timestamps have their LSB set to 0. The idea is to get the current time since the top of the hour, divide by 2^31-1, shift left one bit, then set the LSB to either 0 for relative timestamps or 1 for absolute timestamps.
The nature of the data is such that the timestamp fields will roll over once an hour, and simulations must be prepared for that. Ie, at the top of the hour outgoing PDUs will have a timestamp of 1, just before the end of the hour the PDUs will have a timestamp of 2^31 - 1, and then they will roll back over to 1. Receiving applications should expect this behavior, and not simply expect a monotonically increasing timestamp field.
The official DIS timestamps don't work all that well in our (NPS's) applications, which often expect a monotonically increasing timestamp field. To get around this, we use hundreds of a second since the start of the year. The maximum value for this field is 3,153,600,000, which can fit into an unsigned int. The resolution is good enough for most applications, and you typically don't have to worry about rollover, instead getting only a monotonically increasing timestamp value.
Note that many applications in the wild have been known to completely ignore the standard and to simply put the Unix time (seconds since 1970) into the field.
You need to be careful with the shared instance of this class--I'm not at all convinced it is thread safe. If you are using multiple threads, I suggest you create a new instance of the class for each thread to prevent the values from getting stomped on.
Shared singleton removed. Mike Bailey, 14 June 2019- Author:
- DMcG
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic int
mask for absolute timestampsprotected GregorianCalendar
calendar instancestatic int
mask for relative timestamps -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionint
Returns the absolute timestamp, assuming that this host is sync'd to NTP.int
Returns the DIS standard relative timestamp, which should be used if this host is not slaved to NTP.int
Returns a useful timestamp, hundredths of a second since the start of the year.int
Another option for marshalling with the timestamp field set automatically.static String
timeStampToString(int timeStamp)
Convert timestamp value to string for logging and diagnostics
-
Field Details
-
ABSOLUTE_TIMESTAMP_MASK
public static final int ABSOLUTE_TIMESTAMP_MASKmask for absolute timestamps- See Also:
- Constant Field Values
-
RELATIVE_TIMESTAMP_MASK
public static final int RELATIVE_TIMESTAMP_MASKmask for relative timestamps- See Also:
- Constant Field Values
-
calendar
calendar instance
-
-
Constructor Details
-
DisTime
public DisTime()Shared instance. This is not thread-safe. If you are working in multiple threads, create a new instance for each thread. return singleton instance of DisTime
-
-
Method Details
-
getDisAbsoluteTimestamp
public int getDisAbsoluteTimestamp()Returns the absolute timestamp, assuming that this host is sync'd to NTP. Fix to bitshift by mvormelch.- Returns:
- DIS time units, get absolute timestamp
-
getDisRelativeTimestamp
public int getDisRelativeTimestamp()Returns the DIS standard relative timestamp, which should be used if this host is not slaved to NTP. Fix to bitshift by mvormelch- Returns:
- DIS time units, relative
-
getNpsTimestamp
public int getNpsTimestamp()Returns a useful timestamp, hundredths of a second since the start of the year. This effectively eliminates the need for receivers to handle timestamp rollover, as long as you're not working on New Year's Eve.- Returns:
- a timestamp in hundredths of a second since the start of the year
-
getUnixTimestamp
public int getUnixTimestamp()Another option for marshalling with the timestamp field set automatically. The UNIX time is conventionally seconds since January 1, 1970. UTC time is used, and leap seconds are excluded. This approach is popular in the wild, but the time resolution is not very good for high frequency updates, such as aircraft. An entity updating at 30 PDUs/second would see 30 PDUs sent out with the same timestamp, and have 29 of them discarded as duplicate packets. Note that there are other "Unix times", such milliseconds since 1/1/1970, saved in a long. This cannot be used, since the value is saved in a long. Java's System.getCurrentTimeMillis() uses this value. Unix time (in seconds) rolls over in 2038. Consult the Wikipedia page on Unix time for the gory details- Returns:
- seconds since 1970
-
timeStampToString
Convert timestamp value to string for logging and diagnostics- Parameters:
timeStamp
- value in milliseconds- Returns:
- string value provided by GregorianCalendar
- See Also:
GregorianCalendar
-