Class DisTime
This common shared class provides static code for timestamp configuration and conversion utilities, consistently supporting all active open-dis7-java simulations running together on a localhost. Multiple timestamp configurations are available, but dissimilar forms within a single simulation are considered counterproductive and impractical to manage coherently.
DIS time units are a pain to work with. As specified by the IEEE DIS Protocol specification, DIS time units are defined in a custom manner 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. Rollover problems can easily occur.] The timestamp field in the PDU header is four bytes long and is specified to be an unsigned integer value. Within a PDU encoding, the timestamp value is int representing number of 1.675 microseconds as interval past hour. IEEE DIS 1278.1, 6.2.88 Timestamp, 6.2.88.2.3 Scale states "The scale of the time value contained in the most significant 31 bits of the timestamp shall be determined by letting zero represent the start of the hour and letting 231 – 1 represent one time unit before the start of the next hour. The next hour then starts back at zero. This results in each time unit representing exactly 3600/(231) s (approximately 1.67638063 μs)."
Thus simulation applications can use float or double representations for simulation time, but proper encoding of timestamp values must be performed by the opendis library when reading or writing values. TODO: confirm correct exposure of methods properly performs conversions.
Multiple timestamp styles and settings are available.
Absolute time and Relative time are two variations for the official timestamp value in the PDU header. Absolute time indicates that the localhost is synchronized to Coordinated Universal Time (UTC), typically meaning that the local computer system is accurately synchronized with UTC via Network Time Protocol (NTP). Synchronization might also be achieved when a computer has a highly accurate reference clock (such as GPS). The packet timestamps originating from such hosts can be legitimately compared to the timestamp of packets received from other hosts, since they all are referenced to the same universal time. Relative timestamps may require further processing in order to achieve synchronization
Absolute timestamps have their least significant bit (LSB) set to 1, and relative timestamps have their LSB set to 0. The idea in the DIS specification 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.
Relative timestamps are indicated 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 correlate baseline time references before ordering packets, and that the PDU timestamp fields from one host is not directly comparable to the PDU timestamp field from another host. (TODO: such support for correlating unsynchronized clocks is not yet implemented by this library.)
Another difficulty with the DIS standard has serious effects. The nature of shared DIS data is such that the timestamp values roll over once an hour, and simulations must be prepared for that eventuality. In other words, at the top of the hour outgoing PDUs will have a timestamp of 1, then 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 a value of 1. Receiving applications should expect this behavior, and not simply expect a monotonically increasing timestamp field. Two nonstandard timestamp alternatives follow.
Unix time. Note that many applications in the wild have been known to completely ignore the DIS standard and to simply put commonly used Unix time (seconds since 1 January 1970) into the timestamp field.
Year time. The rollover associated with official DIS timestamps don't work all that well in numerous applications, which often expect a monotonically increasing timestamp field. Such unpredictable rollover variations are also incompatible with archival recording or streaming playback of Live-Virtual-Constructive (LVC) behavior streams. To avoid such problems, NPS created a "yearly" timestamp which measures hundredths of a second since the start of the current year. The maximum value for such measurements is 3,153,600,000, which can fit into an unsigned int. One hundredth of a second resolution is accurate enough for most applications, and you typically don't have to worry about rollover, instead getting only a monotonically increasing timestamp value.
TODO we are currently investigating whether IEEE_ABSOLUTE
together with
epochLvc
normalization of time reference is sufficient for LVC simulation.
Further work is upgrading DisTime support to use the java.time
library.
Of note is that DISv8 intends to use a 64-bit timestamp.
TODO: timestamp normalization to an initial reference time. Functionality is needed to define a shared common time origin (epochLvc) and also to precisely adjust stream timestamps when coordinating recorded PDU playback within LVC applications. We think the ability to "start at time 0.0", or normalizing initial time to zero for a recorded PDU stream, is actually a pretty common use case. Implementing such a capability is under active development.
Support for java.time
package: see
Java Tutorials: Date Time
and
Java Package java.time.
Don McGregor, Mike Bailey, and Don Brutzman
- Author:
- DMcG
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enum
Enumerations for prepared time formattersstatic enum
Supported timestamp styles and utility methods, default isIEEE_ABSOLUTE
indicating local clock is synchronized to UTC time standard. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final int
mask for absolute timestampsstatic final int
mask for relative timestampsstatic final String
prefix for trace statementsstatic final DateTimeFormatter
Format timeHH:mm:ss.SS
static final DateTimeFormatter
Format timeHH:mm:ss.SSSSSS
static final DateTimeFormatter
Format timeHH:mm:ss.SSS
static final DateTimeFormatter
Format timeHH:mm:ss.SSSSSSSSS
static final DateTimeFormatter
Format timeHH:mm:ss
static final DateTimeFormatter
Format timeHH:mm:ss.S
, defaultstatic final DisTime.TimestampStyle
Default value is TimestampStyle.IEEE_ABSOLUTE. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic CommentPdu
Provide parse able time metadata encapsulated in CommentPdu for sharing.static void
Reset epochLvc so it is no longer activestatic boolean
configureTimeMetadata
(CommentPdu timeMetadataCommentPdu) Provide corresponding utility method to parse time metadata from CommentPdustatic Instant
convertToInstant
(long timestamp) Convert timestamp value to Instant for time operations.static LocalDateTime
convertToLocalDateTime
(long timestamp) Convert timestamp value to LocalDateTime for time operations.static LocalTime
convertToLocalTime
(long timestamp) Convert timestamp value to LocalTime for time operations.static String
convertToString
(int timestamp) Convert timestamp value to string for logging and diagnostics, taking into account epochLvc and TimeStampStyle (DIS absolute/relative, Unix or Year).static int
Recommended form, checks local system clock and returns the current DIS standard relative timestamp based on current timestampStyle.static Instant
Get initial timestamp for zero-based clock, meaning all timestamps are measured with respect to given starting timestatic PduFactory
Return the static instance of the PduFactorystatic DateTimeFormatter
Get time format used for text loggingstatic DisTime.TimestampStyle
Retrieve the current timestampStyle.static boolean
Whether epochLvc is currently appliedstatic boolean
Determine whether host computer clock is accurately synchronized with UTC to a time standardstatic void
Main method for testing.static void
setEpochLvc
(Instant newEpochLvc) Set Instant value as epochLvc for zero-based clock, meaning timestamps normalized to 0 at that initial starting timestatic void
Reset epochLvc using current time for zero-based clock, meaning timestamps are normalized to "time zero" of simulation as initial starting timestatic void
setHostClockSynchronized
(boolean newhostClockSynchronized) Declare whether host computer clock is accurately synchronized with UTC using a time standard, such as NTP.static void
setTimeFormatter
(DisTime.TimeFormatterType timeFormatterChoice) Set time format for text loggingstatic void
setTimestampStyle
(DisTime.TimestampStyle newTimestampStyle) Set which time reference is employed throughout this simulation as timestampStyle: IEEE_ABSOLUTE, IEEE_RELATIVE, UNIX, or YEAR.
-
Field Details
-
TIMESTAMP_STYLE_DEFAULT
Default value is TimestampStyle.IEEE_ABSOLUTE. -
ABSOLUTE_TIMESTAMP_MASK
public static final int ABSOLUTE_TIMESTAMP_MASKmask for absolute timestamps- See Also:
-
RELATIVE_TIMESTAMP_MASK
public static final int RELATIVE_TIMESTAMP_MASKmask for relative timestamps- See Also:
-
TIME_COMMENT_PDU_PREFIX
-
timeFormatterSeconds
-
timeFormatterTenthSeconds
Format timeHH:mm:ss.S
, default- See Also:
-
timeFormatterHundredthSeconds
Format timeHH:mm:ss.SS
- See Also:
-
timeFormatterMilliSeconds
-
timeFormatterMicroSeconds
Format timeHH:mm:ss.SSSSSS
- See Also:
-
timeFormatterNanoSeconds
Format timeHH:mm:ss.SSSSSSSSS
- See Also:
-
-
Constructor Details
-
DisTime
public DisTime()Shared instance. This method 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
-
getTimeFormatter
Get time format used for text logging- Returns:
- current timeFormatter
-
setTimeFormatter
Set time format for text logging- Parameters:
timeFormatterChoice
- enumeration for the new timeFormatter to set
-
buildTimeMetadataCommentPdu
Provide parse able time metadata encapsulated in CommentPdu for sharing. TODO: move this to PduFactory- Returns:
- PDU of interest
-
configureTimeMetadata
Provide corresponding utility method to parse time metadata from CommentPdu- Parameters:
timeMetadataCommentPdu
- CommentPdu to parse- Returns:
- whether parsing and configuration successful
-
getCurrentDisTimestamp
public static int getCurrentDisTimestamp()Recommended form, checks local system clock and returns the current DIS standard relative timestamp based on current timestampStyle.- Returns:
- DIS time units, relative
- See Also:
-
convertToInstant
Convert timestamp value to Instant for time operations. TODO take into account epochLvc and TimeStampStyle (DIS absolute/relative, Unix or Year). TODO consider different formats for different timestampStyle values.- Parameters:
timestamp
- value in seconds- Returns:
- corresponding Instant value (with 31-bit fidelity)
-
convertToLocalTime
Convert timestamp value to LocalTime for time operations. TODO take into account epochLvc and TimeStampStyle (DIS absolute/relative, Unix or Year). TODO consider different formats for different timestampStyle values.- Parameters:
timestamp
- value in seconds- Returns:
- corresponding Instant value (with 31-bit fidelity)
-
convertToLocalDateTime
Convert timestamp value to LocalDateTime for time operations. TODO take into account epochLvc and TimeStampStyle (DIS absolute/relative, Unix or Year). TODO consider different formats for different timestampStyle values.- Parameters:
timestamp
- value in seconds- Returns:
- corresponding LocalDateTime value (with 31-bit fidelity)
-
convertToString
Convert timestamp value to string for logging and diagnostics, taking into account epochLvc and TimeStampStyle (DIS absolute/relative, Unix or Year). TODO consider different formats for different timestampStyle values.- Parameters:
timestamp
- value in milliseconds- Returns:
- string value provided by GregorianCalendar
- See Also:
-
setTimestampStyle
Set which time reference is employed throughout this simulation as timestampStyle: IEEE_ABSOLUTE, IEEE_RELATIVE, UNIX, or YEAR.- Parameters:
newTimestampStyle
- the timestamp style to set for this PDU
-
getTimestampStyle
Retrieve the current timestampStyle.- Returns:
- the current timestampStyle
-
setHostClockSynchronized
public static void setHostClockSynchronized(boolean newhostClockSynchronized) Declare whether host computer clock is accurately synchronized with UTC using a time standard, such as NTP.- Parameters:
newhostClockSynchronized
- whether localhost is synchronized to time reference
-
isHostClockSynchronized
public static boolean isHostClockSynchronized()Determine whether host computer clock is accurately synchronized with UTC to a time standard- Returns:
- whether localhost is synchronized to time reference
-
setEpochLvcNow
public static void setEpochLvcNow()Reset epochLvc using current time for zero-based clock, meaning timestamps are normalized to "time zero" of simulation as initial starting time -
setEpochLvc
Set Instant value as epochLvc for zero-based clock, meaning timestamps normalized to 0 at that initial starting time- Parameters:
newEpochLvc
- Instant corresponding to first PDU in series, considered time zero
-
getEpochLvc
Get initial timestamp for zero-based clock, meaning all timestamps are measured with respect to given starting time- Returns:
- whether localhost is synchronized to time reference
-
hasEpochLvc
public static boolean hasEpochLvc()Whether epochLvc is currently applied- Returns:
- whether epochLvc is active
-
clearEpochLvc
public static void clearEpochLvc()Reset epochLvc so it is no longer active -
getPduFactory
Return the static instance of the PduFactory- Returns:
- the static instance of the PduFactory
-
main
Main method for testing.- Parameters:
args
- [unused] command-line arguments are an array of optional String parameters that are passed from execution environment during invocation- See Also:
-