/**
  * Returns the value of this TimeInstant object as a long type in the time unit given as a
  * parameter. If the parameter has a coarser granularity than epsilon the returned value will be
  * rounded, so lose precision.
  *
  * @param unit the TimeUnit
  * @return long: the time value of the TimeInstant object as a long type in the time unit given as
  *     a parameter or Long.MIN_VALUE if conversion would negatively overflow, or Long.MAX_VALUE if
  *     it would positively overflow.
  */
 public long getTimeRounded(TimeUnit unit) {
   if (unit.compareTo(TimeOperations.getEpsilon()) > 0) {
     // unit has a coarser granularity than epsilon
     long halfAUnitInEpsilon = TimeOperations.getEpsilon().convert(1, unit) / 2;
     long durationInUnitTruncated = getTimeTruncated(unit);
     long difference =
         _timeInEpsilon - TimeOperations.getEpsilon().convert(durationInUnitTruncated, unit);
     // if the time value in the unit Epsilon is bigger than
     if (difference >= halfAUnitInEpsilon) {
       return durationInUnitTruncated + 1;
     }
     return durationInUnitTruncated;
   } else {
     // unit has a finer granularity or is equal than epsilon
     return getTimeTruncated(unit);
   }
 }
  /**
   * Returns the String Representation of this TimeInstant according to the TimeFormatter,
   * truncating digits after the decimal point if necessary.
   *
   * @param digits Maximum number of digits after decimal point
   * @see java.lang.Object#toString()
   * @see desmoj.core.simulator.TimeFormatter
   */
  public String toString(int digits) {

    String result = TimeOperations.formatTimeInstant(this);

    if (result.lastIndexOf(".") >= 0) {
      result = result.substring(0, Math.max(result.length() - 1, result.lastIndexOf(".") + digits));
    }
    return result;
  }
  /**
   * Constructs a TimeInstant object with the given time value in the time unit of the given
   * parameter. It represents a time instant in simulation time. Note that trying to create a
   * TimeInstant object The simulation will also stop immediately if the TimeSpan is larger than
   * Long.MAX_VALUE-1 (in the unit of epsilon).
   *
   * @param time long : The time value of this TimeInstant in the time unit of unit.
   * @param unit TimeUnit: the TimeUnit
   */
  public TimeInstant(long time, TimeUnit unit) {
    if (unit == null) { // no time unit given
      throw (new desmoj.core.exception.SimAbortedException(
          new desmoj.core.report.ErrorMessage(
              null,
              "Can't create TimeInstant object! Simulation aborted.",
              "Class : TimeInstant  Constructor : TimeInstant(long, TimeUnit)",
              "Time unit passed is null",
              "Make sure to pass a non-null time unit. \nNote that before "
                  + "connecting model and experiment, TimeInstants must explicitly\n"
                  + "refer to a time unit as the reference unit is not yet defined,"
                  + "e.g. use \nTimeInstant(long time, TimeUnit unit) instead of"
                  + "TimeInstant(long time).",
              null)));
    }
    // System.out.println(time + " " + unit);
    // System.out.println("Format: "
    // + new SimpleDateFormat().format(new Date(time)));
    if (unit.compareTo(TimeOperations.getEpsilon()) < 0) {
      // unit is a finer granularity than epsilon
      if (TimeOperations.getStartTime() != null) { // Start time has been
        // set
        System.out.println("Starttime: " + TimeOperations.getStartTime());
        long timeSinceStart =
            time // time since start...?
                - unit.convert(
                    TimeOperations.getStartTime() // Achtung-negative
                        // werden
                        // positiv
                        .getTimeInEpsilon(),
                    TimeOperations.getEpsilon());
        System.out.println("TimeSinceStart: " + timeSinceStart);
        if (timeSinceStart != 0) {
          time = time - (timeSinceStart % unit.convert(1, TimeOperations.getEpsilon()));
        }
      }
    }
    this._timeInEpsilon = TimeOperations.getEpsilon().convert(time, unit);
    if (_timeInEpsilon == Long.MAX_VALUE) {
      /*The timeInstant is too big.
      (The method TimeUnit.convert(duration,unit)returns Long.MAX_VALUE if
      the result of the conversion is to big*/

      throw (new desmoj.core.exception.SimAbortedException(
          new desmoj.core.report.ErrorMessage(
              null,
              "Can't create TimeInstant object! Simulation aborted.",
              "Class : TimeInstant  Constructor : TimeInstant(long,TimeUnit)",
              "the TimeInstant is too big. ",
              "Can only create TimeInstant objects which are smaller than Long.MAX_VALUE (in the TimeUnit of epsilon).",
              null)));
    }

    this._preferredTimeZone = DEFAULT_PREFERRED_TIMEZONE;
  }
 /**
  * Returns the String Representation of this TimeInstant according to the TimeFormatter.
  *
  * @see java.lang.Object#toString()
  * @see desmoj.core.simulator.TimeFormatter
  */
 public String toString() {
   return TimeOperations.formatTimeInstant(this);
 }
 /**
  * Returns the value of this TimeInstant object as a double type in the time unit of the reference
  * time.
  *
  * @return double: the time value of the TimeInstant object as a double type in the time unit
  *     given as a parameter
  */
 public double getTimeAsDouble() {
   return getTimeAsDouble(TimeOperations.getReferenceUnit());
 }
 /**
  * Returns the value of this TimeInstant object as a double type in the time unit given as a
  * parameter.
  *
  * @return double: the time value of the TimeInstant object as a double type in the time unit
  *     given as a parameter
  */
 public double getTimeAsDouble(TimeUnit unit) {
   return _timeInEpsilon / (double) TimeOperations.getEpsilon().convert(1, unit);
 }
 /**
  * Returns the value of this TimeInstant object as a long type in the time unit of the reference
  * time. If the parameter has a coarser granularity than epsilon the returned value will be
  * rounded, so lose precision.
  *
  * @return long: the time value of the TimeInstant object as a long type in the time unit given as
  *     a parameter or Long.MIN_VALUE if conversion would negatively overflow, or Long.MAX_VALUE if
  *     it would positively overflow.
  */
 public long getTimeRounded() {
   return getTimeRounded(TimeOperations.getReferenceUnit());
 }
 /**
  * Returns the value of this TimeInstant object as a long type in the time unit of the reference
  * time. If the parameter has a coarser granularity than epsilon the returned value will be
  * truncated, so lose precision.
  *
  * @return long: the time value of the TimeInstant object as a long type in the time unit given as
  *     a parameter or Long.MIN_VALUE if conversion would negatively overflow, or Long.MAX_VALUE if
  *     it would positively overflow.
  */
 public long getTimeTruncated() {
   return getTimeTruncated(TimeOperations.getReferenceUnit());
 }
 /**
  * Returns the value of this TimeInstant object as a long type in the time unit given as a
  * parameter. If the parameter has a coarser granularity than epsilon the returned value will be
  * truncated, so lose precision.
  *
  * @return long: the time value of the TimeInstant object as a long type in the time unit given as
  *     a parameter or Long.MIN_VALUE if conversion would negatively overflow, or Long.MAX_VALUE if
  *     it would positively overflow.
  */
 public long getTimeTruncated(TimeUnit unit) {
   return unit.convert(_timeInEpsilon, TimeOperations.getEpsilon());
 }
 /**
  * Constructs a TimeInstant object with the given time value in the time unit of the reference
  * time. It represents a time Instant in simulation time.
  *
  * @param timeInReferenceUnit double : The time value of this TimeInstant in the time unit of the
  *     reference time.
  */
 public TimeInstant(double timeInReferenceUnit) {
   this(timeInReferenceUnit, TimeOperations.getReferenceUnit());
 }