Class DisTime

java.lang.Object
edu.nps.moves.dis7.utilities.DisTime

public class DisTime extends Object

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.

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.

TODO: upgrade to 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 Classes
    Modifier and Type
    Class
    Description
    static enum 
    Supported timestamp styles and utility methods, default is IEEE_ABSOLUTE indicating local clock is synchronized to UTC time standard.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    mask for absolute timestamps
    static final int
    mask for relative timestamps
    static final String
    prefix for trace statements
    Default value is TimestampStyle.IEEE_ABSOLUTE.
  • Constructor Summary

    Constructors
    Constructor
    Description
    Shared instance.
  • Method Summary

    Modifier and Type
    Method
    Description
    static CommentPdu
    Provide parsable time metadata encapsulated in CommentPdu for sharing
    static void
    Reset epochLvc so it is no longer active
    static boolean
    configureTimeMetadata(CommentPdu timeMetadataCommentPdu)
    Provide corresponding utility method to parse time metadata from CommentPdu
    static Instant
    convertToInstant(int timestamp)
    Convert timestamp value to Instant for time operationss, taking into account epochLvc and TimeStampStyle (DIS absolute/relative, Unix or Year).
    convertToLocalDateTime(int timestamp)
    Convert timestamp value to Instant for time operations, taking into account epochLvc and TimeStampStyle (DIS absolute/relative, Unix or Year).
    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).
    convertToZonedDateTime(int timestamp)
    Convert timestamp value to Instant for time operations, 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 time
    Retrieve the current timestampStyle.
    static boolean
    Whether epochLvc is currently applied
    static boolean
    Determine whether host computer clock is accurately synchronized with UTC to a time standard
    static void
    main(String[] args)
    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 time
    static void
    Reset epochLvc using current time for zero-based clock, meaning timestamps are normalized to "time zero" of simulation as initial starting time
    static void
    setHostClockSynchronized(boolean newhostClockSynchronized)
    Declare whether host computer clock is accurately synchronized with UTC using a time standard, such as NTP.
    static void
    Set which time reference is employed throughout this simulation as timestampStyle: IEEE_ABSOLUTE, IEEE_RELATIVE, UNIX, or YEAR.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • TIMESTAMP_STYLE_DEFAULT

      public static final DisTime.TimestampStyle TIMESTAMP_STYLE_DEFAULT
      Default value is TimestampStyle.IEEE_ABSOLUTE.
    • ABSOLUTE_TIMESTAMP_MASK

      public static final int ABSOLUTE_TIMESTAMP_MASK
      mask for absolute timestamps
      See Also:
    • RELATIVE_TIMESTAMP_MASK

      public static final int RELATIVE_TIMESTAMP_MASK
      mask for relative timestamps
      See Also:
    • TIME_COMMENT_PDU_PREFIX

      public static final String TIME_COMMENT_PDU_PREFIX
      prefix for trace statements
      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

    • buildTimeMetadataCommentPdu

      public static CommentPdu buildTimeMetadataCommentPdu()
      Provide parsable time metadata encapsulated in CommentPdu for sharing
      Returns:
      PDU of interest
    • configureTimeMetadata

      public static boolean configureTimeMetadata(CommentPdu timeMetadataCommentPdu)
      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

      public static Instant convertToInstant(int timestamp)
      Convert timestamp value to Instant for time operationss, 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:
      corresponding Instant value (with 31-bit fidelity)
    • convertToLocalDateTime

      public static LocalDateTime convertToLocalDateTime(int timestamp)
      Convert timestamp value to Instant for time operations, 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:
      corresponding Instant value (with 31-bit fidelity)
    • convertToZonedDateTime

      public static ZonedDateTime convertToZonedDateTime(int timestamp)
      Convert timestamp value to Instant for time operations, 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:
      corresponding Instant value (with 31-bit fidelity)
    • convertToString

      public 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). TODO consider different formats for different timestampStyle values.
      Parameters:
      timestamp - value in milliseconds
      Returns:
      string value provided by GregorianCalendar
      See Also:
    • setTimestampStyle

      public static void setTimestampStyle(DisTime.TimestampStyle newTimestampStyle)
      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

      public static DisTime.TimestampStyle 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

      public static void setEpochLvc(Instant newEpochLvc)
      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

      public static Instant 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
    • main

      public static void main(String[] args)
      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: