diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 01ebb03301f6ec28cf91f58d358b55f28829ee78..168c7591d504149772a78ecd64e294cd611e939c 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -56,6 +56,33 @@
       <action dev="bryan" type="fix" issue="820">
         TLE Jacobians are now calculated in cartesian elements.
       </action>
+      <action dev="evan" type="update" issue="825">
+        Improve exception messages with two AbsoluteDates by including duration between
+        them.
+      </action>
+      <action dev="evan" type="update" issue="637" due-to="Piotr">
+        Add trailing "Z" to AbsoluteDate.toString() to indicate UTC.
+        Backwards incompatible.
+      </action>
+      <action dev="evan" type="update" issue="825">
+        In AbsoluteDate.toString() fallback to TAI when no leap seconds are loaded.
+      </action>
+      <action dev="evan" type="update" issue="591">
+        Fix TimeComponents.toString(): correct ISO 8601 with UTC offset, rounding issues.
+        Backwards incompatible.
+      </action>
+      <action dev="evan" type="update" issue="590">
+        Fix DateTimeComponents.toString(): correct ISO 8601, leap second, rounding issues.
+        Backwards incompatible.
+      </action>
+      <action dev="evan" type="update" issue="637" due-to="Piotr">
+        Fix AbsoluteDate.toString(timeZone) and toString(minutesFromUtc) to include the
+        UTC offset when it is zero.
+      </action>
+      <action dev="evan" type="add">
+        Add DateTimeComponents.toString(...) method with correct rounding for user
+        specified precision.
+      </action>
       <action dev="bryan" type="update" issue="626">
         Used a separate Comparator for sorting integer least square solutions.
       </action>
diff --git a/src/main/java/org/orekit/bodies/JPLEphemeridesLoader.java b/src/main/java/org/orekit/bodies/JPLEphemeridesLoader.java
index 58db665d2489c0ce724a166f027fa4b2e7fe2851..4b93d70f107b035ee2c7f8bdffa95915af797691 100644
--- a/src/main/java/org/orekit/bodies/JPLEphemeridesLoader.java
+++ b/src/main/java/org/orekit/bodies/JPLEphemeridesLoader.java
@@ -990,12 +990,14 @@ public class JPLEphemeridesLoader extends AbstractSelfFeedingLoader
             // extract time range covered by the record
             final AbsoluteDate rangeStart = extractDate(record, DATA_START_RANGE_OFFSET);
             if (rangeStart.compareTo(startEpoch) < 0) {
-                throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, rangeStart, startEpoch, finalEpoch);
+                throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE,
+                        rangeStart, startEpoch, finalEpoch, startEpoch.durationFrom(rangeStart));
             }
 
             final AbsoluteDate rangeEnd   = extractDate(record, DATE_END_RANGE_OFFSET);
             if (rangeEnd.compareTo(finalEpoch) > 0) {
-                throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, rangeEnd, startEpoch, finalEpoch);
+                throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER,
+                        rangeEnd, startEpoch, finalEpoch, rangeEnd.durationFrom(finalEpoch));
             }
 
             if (rangeStart.compareTo(end) > 0 || rangeEnd.compareTo(start) < 0) {
diff --git a/src/main/java/org/orekit/errors/OrekitMessages.java b/src/main/java/org/orekit/errors/OrekitMessages.java
index fe5d3e19f7a4e3a98d439a0865e36e49411764da..4067cd55c402663f5aea3fd072cd2bcedb7a2831 100644
--- a/src/main/java/org/orekit/errors/OrekitMessages.java
+++ b/src/main/java/org/orekit/errors/OrekitMessages.java
@@ -72,6 +72,7 @@ public enum OrekitMessages implements Localizable {
     UNABLE_TO_FIND_RESOURCE("unable to find resource {0} in classpath"),
     NO_EARTH_ORIENTATION_PARAMETERS_LOADED("no Earth Orientation Parameters loaded"),
     MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES("missing Earth Orientation Parameters between {0} and {1}"),
+    MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP("missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s"),
     NO_EARTH_ORIENTATION_PARAMETERS("missing Earth Orientation Parameters"),
     NOT_A_SUPPORTED_IERS_DATA_FILE("file {0} is not a supported IERS data file"),
     INCONSISTENT_DATES_IN_IERS_FILE("inconsistent dates in IERS file {0}: {1}-{2}-{3} and MJD {4}"),
@@ -100,7 +101,7 @@ public enum OrekitMessages implements Localizable {
     MISSING_GRAVITY_FIELD_COEFFICIENT_IN_FILE("missing gravity field coefficient {0}({1}, {2}) in file {3}"),
     TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD("too large degree (n = {0}, potential maximal degree is {1})"),
     TOO_LARGE_ORDER_FOR_GRAVITY_FIELD("too large order (m = {0}, potential maximal order is {1})"),
-    SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD("several reference dates ({0} and {1}) found in gravity field file {2}"),
+    SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD("several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}"),
     NO_TLE_FOR_OBJECT("no TLE data available for object {0}"),
     NO_TLE_FOR_LAUNCH_YEAR_NUMBER_PIECE(
             "no TLE data available for launch year {0}, launch number {1}, launch piece {2}"),
@@ -131,7 +132,7 @@ public enum OrekitMessages implements Localizable {
     FRAMES_MISMATCH("frame {0} does not match frame {1}"),
     INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION("initial state not specified for orbit propagation"),
     EVENT_DATE_TOO_CLOSE(
-            "event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added"),
+            "target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added"),
     UNABLE_TO_READ_JPL_HEADER("unable to read header record from JPL ephemerides binary file {0}"),
     INCONSISTENT_ASTRONOMICAL_UNIT_IN_FILES(
             "inconsistent values of astronomical unit in JPL ephemerides files: ({0} and {1})"),
@@ -144,6 +145,8 @@ public enum OrekitMessages implements Localizable {
     NO_JPL_EPHEMERIDES_BINARY_FILES_FOUND("no JPL ephemerides binary files found"),
     OUT_OF_RANGE_BODY_EPHEMERIDES_DATE("out of range date for {0} ephemerides: {1}"),
     OUT_OF_RANGE_EPHEMERIDES_DATE("out of range date for ephemerides: {0}, [{1}, {2}]"),
+    OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE("out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]"),
+    OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER("out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]"),
     UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH(
             "unexpected two elevation values: {0} and {1}, for one azimuth: {2}"),
     UNSUPPORTED_PARAMETER_NAME("unsupported parameter name {0}, supported names: {1}"),
@@ -204,10 +207,10 @@ public enum OrekitMessages implements Localizable {
     NOT_ENOUGH_DATA_FOR_INTERPOLATION("not enough data for interpolation (sample size = {0})"),
     NOT_ENOUGH_CACHED_NEIGHBORS("too small number of cached neighbors: {0} (must be at least {1})"),
     NO_CACHED_ENTRIES("no cached entries"),
-    NON_CHRONOLOGICALLY_SORTED_ENTRIES("generated entries not sorted: {0} > {1}"),
+    NON_CHRONOLOGICALLY_SORTED_ENTRIES("generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s"),
     NO_DATA_GENERATED("no data generated around date: {0}"),
-    UNABLE_TO_GENERATE_NEW_DATA_BEFORE("unable to generate new data before {0}, data requested for {1}"),
-    UNABLE_TO_GENERATE_NEW_DATA_AFTER("unable to generate new data after {0}, data requested for {1}"),
+    UNABLE_TO_GENERATE_NEW_DATA_BEFORE("unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before"),
+    UNABLE_TO_GENERATE_NEW_DATA_AFTER("unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after"),
     UNABLE_TO_COMPUTE_HYPERBOLIC_ECCENTRIC_ANOMALY(
             "unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations"),
     UNABLE_TO_COMPUTE_DSST_MEAN_PARAMETERS("unable to compute mean orbit from osculating orbit after {0} iterations"),
@@ -286,10 +289,11 @@ public enum OrekitMessages implements Localizable {
             "invalid measurement types {0} and {1} for the combination of measurements {2}"),
     INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS(
             "frequencies {0} and {1} are incompatibles for the {2} combination"),
-    NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS("observations {0} and {1} are not in chronological dates"),
+    NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS("observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}"),
     EXCEPTIONAL_DATA_CONTEXT(
             "Use of the ExceptionalDataContext detected. This is typically used to detect developer errors."),
-    NON_DIFFERENT_DATES_FOR_OBSERVATIONS("observations {0}, {1} and {2} must have different dates"),
+    NON_DIFFERENT_DATES_FOR_OBSERVATIONS(
+            "Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)"),
     NON_COPLANAR_POINTS("observations are not in the same plane"),
     INVALID_PARAMETER_RANGE("invalid parameter {0}: {1} not in range [{2}, {3}]"),
     PARAMETER_NOT_SET("The parameter {0} should not be null in {1}"),
diff --git a/src/main/java/org/orekit/estimation/iod/IodGibbs.java b/src/main/java/org/orekit/estimation/iod/IodGibbs.java
index 6ca18e49b37e5ef8ced332d692372f5ac155ff93..05bc080cc7aa8f49a80f3aed20dabd6ada4f0b28 100644
--- a/src/main/java/org/orekit/estimation/iod/IodGibbs.java
+++ b/src/main/java/org/orekit/estimation/iod/IodGibbs.java
@@ -105,7 +105,8 @@ public class IodGibbs {
                                    final Vector3D r3, final AbsoluteDate date3) {
         // Checks measures are not at the same date
         if (date1.equals(date2) || date1.equals(date3) || date2.equals(date3)) {
-            throw new OrekitException(OrekitMessages.NON_DIFFERENT_DATES_FOR_OBSERVATIONS, date1, date2, date3);
+            throw new OrekitException(OrekitMessages.NON_DIFFERENT_DATES_FOR_OBSERVATIONS, date1, date2, date3,
+                    date2.durationFrom(date1), date3.durationFrom(date1), date3.durationFrom(date2));
         }
 
         // Checks measures are in the same plane
diff --git a/src/main/java/org/orekit/estimation/iod/IodLambert.java b/src/main/java/org/orekit/estimation/iod/IodLambert.java
index cd3f31561ea2b88f8996ca9c5876233b95215db7..9a4f85f383f397a50d2e39ee9acd159f0e61d99e 100644
--- a/src/main/java/org/orekit/estimation/iod/IodLambert.java
+++ b/src/main/java/org/orekit/estimation/iod/IodLambert.java
@@ -130,7 +130,7 @@ public class IodLambert {
 
         // Exception if t2 < t1
         if (tau < 0.0) {
-            throw new OrekitException(OrekitMessages.NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS, t1, t2);
+            throw new OrekitException(OrekitMessages.NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS, t1, t2, -tau);
         }
 
         // normalizing constants
diff --git a/src/main/java/org/orekit/files/ccsds/ndm/adm/aem/StreamingAemWriter.java b/src/main/java/org/orekit/files/ccsds/ndm/adm/aem/StreamingAemWriter.java
index fcd62359a839a038e1c28789b902460492f69d76..3ce24a235b13152f231348e131c05aceccfc2e77 100644
--- a/src/main/java/org/orekit/files/ccsds/ndm/adm/aem/StreamingAemWriter.java
+++ b/src/main/java/org/orekit/files/ccsds/ndm/adm/aem/StreamingAemWriter.java
@@ -123,8 +123,10 @@ public class StreamingAemWriter implements AutoCloseable {
         @Override
         public void init(final SpacecraftState s0, final AbsoluteDate t, final double step) {
             try {
-                if (t.isBefore(s0)) {
-                    throw new OrekitException(OrekitMessages.NON_CHRONOLOGICALLY_SORTED_ENTRIES, s0.getDate(), t);
+                final AbsoluteDate date = s0.getDate();
+                if (t.isBefore(date)) {
+                    throw new OrekitException(OrekitMessages.NON_CHRONOLOGICALLY_SORTED_ENTRIES,
+                            date, t, date.durationFrom(t));
                 }
 
                 if (headerWritePending) {
@@ -133,7 +135,7 @@ public class StreamingAemWriter implements AutoCloseable {
                     headerWritePending = false;
                 }
 
-                metadata.setStartTime(s0.getDate());
+                metadata.setStartTime(date);
                 metadata.setUseableStartTime(null);
                 metadata.setUseableStopTime(null);
                 metadata.setStopTime(t);
diff --git a/src/main/java/org/orekit/files/ccsds/ndm/odm/oem/StreamingOemWriter.java b/src/main/java/org/orekit/files/ccsds/ndm/odm/oem/StreamingOemWriter.java
index b7aab36626540f05fe9f0b5b691256a2b148ab5a..bfe8c40c93f81b0966f9cb0dff0f3cbb83abdf42 100644
--- a/src/main/java/org/orekit/files/ccsds/ndm/odm/oem/StreamingOemWriter.java
+++ b/src/main/java/org/orekit/files/ccsds/ndm/odm/oem/StreamingOemWriter.java
@@ -128,8 +128,10 @@ public class StreamingOemWriter implements AutoCloseable {
         @Override
         public void init(final SpacecraftState s0, final AbsoluteDate t, final double step) {
             try {
-                if (t.isBefore(s0)) {
-                    throw new OrekitException(OrekitMessages.NON_CHRONOLOGICALLY_SORTED_ENTRIES, s0.getDate(), t);
+                final AbsoluteDate date = s0.getDate();
+                if (t.isBefore(date)) {
+                    throw new OrekitException(OrekitMessages.NON_CHRONOLOGICALLY_SORTED_ENTRIES,
+                            date, t, date.durationFrom(t));
                 }
 
                 if (headerWritePending) {
@@ -138,7 +140,7 @@ public class StreamingOemWriter implements AutoCloseable {
                     headerWritePending = false;
                 }
 
-                metadata.setStartTime(s0.getDate());
+                metadata.setStartTime(date);
                 metadata.setUseableStartTime(null);
                 metadata.setUseableStopTime(null);
                 metadata.setStopTime(t);
diff --git a/src/main/java/org/orekit/forces/gravity/potential/ICGEMFormatReader.java b/src/main/java/org/orekit/forces/gravity/potential/ICGEMFormatReader.java
index bf0f05626924d747b2b58538e757222d033e52b2..76089a275f932017ce239a3c2030b2c85548cc53 100644
--- a/src/main/java/org/orekit/forces/gravity/potential/ICGEMFormatReader.java
+++ b/src/main/java/org/orekit/forces/gravity/potential/ICGEMFormatReader.java
@@ -303,8 +303,10 @@ public class ICGEMFormatReader extends PotentialCoefficientsReader {
                                     // first reference found, store it
                                     referenceDate = toDate(localRef);
                                 } else if (!referenceDate.equals(toDate(localRef))) {
+                                    final AbsoluteDate localDate = toDate(localRef);
                                     throw new OrekitException(OrekitMessages.SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD,
-                                                              referenceDate, toDate(localRef), name);
+                                                              referenceDate, localDate, name,
+                                                              localDate.durationFrom(referenceDate));
                                 }
                             }
 
diff --git a/src/main/java/org/orekit/forces/gravity/potential/SHMFormatReader.java b/src/main/java/org/orekit/forces/gravity/potential/SHMFormatReader.java
index ef981e1c6e7b86d6f7b493fbe84d5b77b9bf602f..d17118ce373df093999db0101beb3641d23d55b6 100644
--- a/src/main/java/org/orekit/forces/gravity/potential/SHMFormatReader.java
+++ b/src/main/java/org/orekit/forces/gravity/potential/SHMFormatReader.java
@@ -179,8 +179,10 @@ public class SHMFormatReader extends PotentialCoefficientsReader {
                                         // first reference found, store it
                                         referenceDate = toDate(localRef);
                                     } else if (!referenceDate.equals(toDate(localRef))) {
+                                        final AbsoluteDate localDate = toDate(localRef);
                                         throw new OrekitException(OrekitMessages.SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD,
-                                                                  referenceDate, toDate(localRef), name);
+                                                                  referenceDate, localDate, name,
+                                                                  localDate.durationFrom(referenceDate));
                                     }
 
                                 } else {
diff --git a/src/main/java/org/orekit/frames/EOPHistory.java b/src/main/java/org/orekit/frames/EOPHistory.java
index 7f8efc0553c4a0c7d491da70480c327a0f39d7a2..fb736a28bbf255da30f0560d3fc1df0b018c0ef4 100644
--- a/src/main/java/org/orekit/frames/EOPHistory.java
+++ b/src/main/java/org/orekit/frames/EOPHistory.java
@@ -617,8 +617,9 @@ public class EOPHistory implements Serializable {
 
             // compare the dates of preceding and current entries
             if (preceding != null && (current.getDate().durationFrom(preceding.getDate())) > maxGap) {
-                throw new OrekitException(OrekitMessages.MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES,
-                                          preceding.getDate(), current.getDate());
+                throw new OrekitException(OrekitMessages.MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP,
+                                          preceding.getDate(), current.getDate(),
+                                          current.getDate().durationFrom(preceding.getDate()));
             }
 
             // prepare next iteration
diff --git a/src/main/java/org/orekit/models/earth/atmosphere/data/CssiSpaceWeatherData.java b/src/main/java/org/orekit/models/earth/atmosphere/data/CssiSpaceWeatherData.java
index 39b950ff38d2fc1dd1f11988bdf0d4563cfa0079..d19b16218bf7eda72850db4bcd294e94a280fda7 100644
--- a/src/main/java/org/orekit/models/earth/atmosphere/data/CssiSpaceWeatherData.java
+++ b/src/main/java/org/orekit/models/earth/atmosphere/data/CssiSpaceWeatherData.java
@@ -145,8 +145,13 @@ public class CssiSpaceWeatherData extends AbstractSelfFeedingLoader
      * @param date date to bracket
      */
     private void bracketDate(final AbsoluteDate date) {
-        if (date.durationFrom(firstDate) < 0 || date.durationFrom(lastDate) > 0) {
-            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, date, firstDate, lastDate);
+        if (date.durationFrom(firstDate) < 0) {
+            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE,
+                    date, firstDate, lastDate, firstDate.durationFrom(date));
+        }
+        if (date.durationFrom(lastDate) > 0) {
+            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER,
+                    date, firstDate, lastDate, date.durationFrom(lastDate));
         }
 
         // don't search if the cached selection is fine
@@ -158,7 +163,7 @@ public class CssiSpaceWeatherData extends AbstractSelfFeedingLoader
         final List<TimeStamped> neigbors = data.getNeighbors(date).collect(Collectors.toList());
         previousParam = (LineParameters) neigbors.get(0);
         nextParam = (LineParameters) neigbors.get(1);
-        if (previousParam.getDate().compareTo(date) > 0) {
+        if (previousParam.getDate().compareTo(date) > 0) { // TODO delete dead code
             /**
              * Throwing exception if neighbors are unbalanced because we are at the
              * beginning of the data set
diff --git a/src/main/java/org/orekit/models/earth/atmosphere/data/MarshallSolarActivityFutureEstimation.java b/src/main/java/org/orekit/models/earth/atmosphere/data/MarshallSolarActivityFutureEstimation.java
index 05dd35ac73bcccf83a871dea71abac34c13b40bc..2a904d2f8f475245724a00c7552772e15051f6bf 100644
--- a/src/main/java/org/orekit/models/earth/atmosphere/data/MarshallSolarActivityFutureEstimation.java
+++ b/src/main/java/org/orekit/models/earth/atmosphere/data/MarshallSolarActivityFutureEstimation.java
@@ -238,9 +238,13 @@ public class MarshallSolarActivityFutureEstimation extends AbstractSelfFeedingLo
      */
     private void bracketDate(final AbsoluteDate date) {
 
-        if (date.durationFrom(firstDate) < 0 || date.durationFrom(lastDate) > 0) {
-            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE,
-                                      date, firstDate, lastDate);
+        if (date.durationFrom(firstDate) < 0) {
+            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE,
+                    date, firstDate, lastDate, firstDate.durationFrom(date));
+        }
+        if (date.durationFrom(lastDate) > 0) {
+            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER,
+                    date, firstDate, lastDate, date.durationFrom(lastDate));
         }
 
         // don't search if the cached selection is fine
diff --git a/src/main/java/org/orekit/propagation/events/DateDetector.java b/src/main/java/org/orekit/propagation/events/DateDetector.java
index b877a0c2ee69f5f82efdf4ba2bbaa0480d29f12d..a4004da5fbc7c3e2c39f1ca88924bf23aeb1a08a 100644
--- a/src/main/java/org/orekit/propagation/events/DateDetector.java
+++ b/src/main/java/org/orekit/propagation/events/DateDetector.java
@@ -149,19 +149,23 @@ public class DateDetector extends AbstractDetector<DateDetector> implements Time
             eventDateList.add(new EventDate(target, increasing));
         } else {
             final int lastIndex = eventDateList.size() - 1;
-            if (eventDateList.get(0).getDate().durationFrom(target) > getMaxCheckInterval()) {
+            final AbsoluteDate firstDate = eventDateList.get(0).getDate();
+            final AbsoluteDate lastDate = eventDateList.get(lastIndex).getDate();
+            if (firstDate.durationFrom(target) > getMaxCheckInterval()) {
                 increasing = !eventDateList.get(0).isgIncrease();
                 eventDateList.add(0, new EventDate(target, increasing));
                 currentIndex++;
-            } else if (target.durationFrom(eventDateList.get(lastIndex).getDate()) > getMaxCheckInterval()) {
+            } else if (target.durationFrom(lastDate) > getMaxCheckInterval()) {
                 increasing = !eventDateList.get(lastIndex).isgIncrease();
                 eventDateList.add(new EventDate(target, increasing));
             } else {
                 throw new OrekitIllegalArgumentException(OrekitMessages.EVENT_DATE_TOO_CLOSE,
                                                          target,
-                                                         eventDateList.get(0).getDate(),
-                                                         eventDateList.get(lastIndex).getDate(),
-                                                         getMaxCheckInterval());
+                                                         firstDate,
+                                                         lastDate,
+                                                         getMaxCheckInterval(),
+                                                         firstDate.durationFrom(target),
+                                                         target.durationFrom(lastDate));
             }
         }
     }
diff --git a/src/main/java/org/orekit/propagation/integration/FieldIntegratedEphemeris.java b/src/main/java/org/orekit/propagation/integration/FieldIntegratedEphemeris.java
index d29254c3578ba8fc5ce1234b6bd18b3e4ceb34a1..53692001c42f6f31cde65aed8a8e0bc081876af5 100644
--- a/src/main/java/org/orekit/propagation/integration/FieldIntegratedEphemeris.java
+++ b/src/main/java/org/orekit/propagation/integration/FieldIntegratedEphemeris.java
@@ -147,11 +147,15 @@ public class FieldIntegratedEphemeris <T extends CalculusFieldElement<T>>
 
         // compare using double precision instead of FieldAbsoluteDate<T>.compareTo(...)
         // because time is expressed as a double when searching for events
-        if (date.compareTo(minDate.shiftedBy(-EXTRAPOLATION_TOLERANCE)) < 0 ||
-                date.compareTo(maxDate.shiftedBy(EXTRAPOLATION_TOLERANCE)) > 0 ) {
+        if (date.compareTo(minDate.shiftedBy(-EXTRAPOLATION_TOLERANCE)) < 0) {
             // date is outside of supported range
-            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE,
-                                           date, minDate, maxDate);
+            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE,
+                    date, minDate, maxDate, minDate.durationFrom(date).getReal());
+        }
+        if (date.compareTo(maxDate.shiftedBy(EXTRAPOLATION_TOLERANCE)) > 0) {
+            // date is outside of supported range
+            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER,
+                    date, minDate, maxDate, date.durationFrom(maxDate).getReal());
         }
 
         return model.getInterpolatedState(date.durationFrom(startDate));
diff --git a/src/main/java/org/orekit/propagation/integration/IntegratedEphemeris.java b/src/main/java/org/orekit/propagation/integration/IntegratedEphemeris.java
index a4e5bc5ddec4a0bf0ed0891856276226a10fbfaf..3850051781e72e5e4cd62b6337f12f760b9d37e7 100644
--- a/src/main/java/org/orekit/propagation/integration/IntegratedEphemeris.java
+++ b/src/main/java/org/orekit/propagation/integration/IntegratedEphemeris.java
@@ -144,11 +144,15 @@ public class IntegratedEphemeris
 
         // compare using double precision instead of AbsoluteDate.compareTo(...)
         // because time is expressed as a double when searching for events
-        if (date.compareTo(minDate.shiftedBy(-EXTRAPOLATION_TOLERANCE)) < 0 ||
-                date.compareTo(maxDate.shiftedBy(EXTRAPOLATION_TOLERANCE)) > 0 ) {
+        if (date.compareTo(minDate.shiftedBy(-EXTRAPOLATION_TOLERANCE)) < 0) {
             // date is outside of supported range
-            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE,
-                                           date, minDate, maxDate);
+            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE,
+                    date, minDate, maxDate, minDate.durationFrom(date));
+        }
+        if (date.compareTo(maxDate.shiftedBy(EXTRAPOLATION_TOLERANCE)) > 0) {
+            // date is outside of supported range
+            throw new OrekitException(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER,
+                    date, minDate, maxDate, date.durationFrom(maxDate));
         }
 
         return model.getInterpolatedState(date.durationFrom(startDate));
diff --git a/src/main/java/org/orekit/time/AbsoluteDate.java b/src/main/java/org/orekit/time/AbsoluteDate.java
index 021d7aab944e77a4bbc62bc373dee21056c07eda..70239d4825f10ba876bcf14be6e2d9717aa78409 100644
--- a/src/main/java/org/orekit/time/AbsoluteDate.java
+++ b/src/main/java/org/orekit/time/AbsoluteDate.java
@@ -1307,26 +1307,63 @@ public class AbsoluteDate
         return (int) (l ^ (l >>> 32));
     }
 
-    /** Get a String representation of the instant location in UTC time scale.
+    /**
+     * Get a String representation of the instant location with up to 16 digits of
+     * precision for the seconds value.
+     *
+     * <p> Since this method is used in exception messages and error handling every
+     * effort is made to return some representation of the instant. If UTC is available
+     * from the default data context then it is used to format the string in UTC. If not
+     * then TAI is used. Finally if the prior attempts fail this method falls back to
+     * converting this class's internal representation to a string.
      *
      * <p>This method uses the {@link DataContext#getDefault() default data context}.
      *
-     * @return a string representation of the instance,
-     * in ISO-8601 format with milliseconds accuracy
+     * @return a string representation of the instance, in ISO-8601 format if UTC is
+     * available from the default data context.
      * @see #toString(TimeScale)
+     * @see #toStringRfc3339(TimeScale)
+     * @see DateTimeComponents#toString(int, int)
      */
     @DefaultDataContext
     public String toString() {
-        return toString(DataContext.getDefault().getTimeScales().getUTC());
+        // CHECKSTYLE: stop IllegalCatch check
+        try {
+            // try to use UTC first at that is likely most familiar to the user.
+            return toString(DataContext.getDefault().getTimeScales().getUTC()) + "Z";
+        } catch (RuntimeException e1) {
+            // catch OrekitException, OrekitIllegalStateException, etc.
+            try {
+                // UTC failed, try to use TAI
+                return toString(new TAIScale()) + " TAI";
+            } catch (RuntimeException e2) {
+                // catch OrekitException, OrekitIllegalStateException, etc.
+                // Likely failed to convert to ymdhms.
+                // Give user some indication of what time it is.
+                try {
+                    return "(" + this.epoch + " + " + this.offset + ") seconds past epoch";
+                } catch (RuntimeException e3) {
+                    // give up and throw an exception
+                    e2.addSuppressed(e3);
+                    e1.addSuppressed(e2);
+                    throw e1;
+                }
+            }
+        }
+        // CHECKSTYLE: resume IllegalCatch check
     }
 
-    /** Get a String representation of the instant location.
+    /**
+     * Get a String representation of the instant location in ISO-8601 format without the
+     * UTC offset and with up to 16 digits of precision for the seconds value.
+     *
      * @param timeScale time scale to use
-     * @return a string representation of the instance,
-     * in ISO-8601 format with milliseconds accuracy
+     * @return a string representation of the instance.
+     * @see #toStringRfc3339(TimeScale)
+     * @see DateTimeComponents#toString(int, int)
      */
     public String toString(final TimeScale timeScale) {
-        return getComponents(timeScale).toString(timeScale.minuteDuration(this));
+        return getComponents(timeScale).toStringWithoutUtcOffset();
     }
 
     /** Get a String representation of the instant location for a local time.
@@ -1355,6 +1392,8 @@ public class AbsoluteDate
      * @return string representation of the instance, in ISO-8601 format with milliseconds
      * accuracy
      * @since 10.1
+     * @see #getComponents(int, TimeScale)
+     * @see DateTimeComponents#toString(int, int)
      */
     public String toString(final int minutesFromUTC, final TimeScale utc) {
         final int minuteDuration = utc.minuteDuration(this);
@@ -1384,6 +1423,8 @@ public class AbsoluteDate
      * @return string representation of the instance, in ISO-8601 format with milliseconds
      * accuracy
      * @since 10.1
+     * @see #getComponents(TimeZone, TimeScale)
+     * @see DateTimeComponents#toString(int, int)
      */
     public String toString(final TimeZone timeZone, final TimeScale utc) {
         final int minuteDuration = utc.minuteDuration(this);
@@ -1392,7 +1433,8 @@ public class AbsoluteDate
 
     /**
      * Represent the given date as a string according to the format in RFC 3339. RFC3339
-     * is a restricted subset of ISO 8601 with a well defined grammar.
+     * is a restricted subset of ISO 8601 with a well defined grammar. Enough digits are
+     * included in the seconds value to avoid rounding up to the next minute.
      *
      * <p>This method is different than {@link AbsoluteDate#toString(TimeScale)} in that
      * it includes a {@code "Z"} at the end to indicate the time zone and enough precision
diff --git a/src/main/java/org/orekit/time/DateTimeComponents.java b/src/main/java/org/orekit/time/DateTimeComponents.java
index 240a26d8dde8de3375411174b1fe172f5d51900e..b5e3a6962e367fd32900b072c626823395f94248 100644
--- a/src/main/java/org/orekit/time/DateTimeComponents.java
+++ b/src/main/java/org/orekit/time/DateTimeComponents.java
@@ -231,24 +231,70 @@ public class DateTimeComponents implements Serializable, Comparable<DateTimeComp
     }
 
     /** Return a string representation of this pair.
-     * <p>The format used is ISO8601.</p>
+     * <p>The format used is ISO8601 including the UTC offset.</p>
      * @return string representation of this pair
      */
     public String toString() {
-        return toString(60);
+        return date.toString() + 'T' + time.toString();
     }
 
-    /** Return a string representation of this pair.
-     * <p>The format used is ISO8601.</p>
-     * @param minuteDuration 60 or 61 depending on the date being
-     * close to a leap second introduction
-     * @return string representation of this pair
+    /**
+     * Get a string representation of the date-time without the offset from UTC. The
+     * format used is ISO6801, except without the offset from UTC.
+     *
+     * @return a string representation of the date-time.
+     * @see #toString(int, int)
+     * @see #toStringRfc3339()
+     */
+    public String toStringWithoutUtcOffset() {
+        return date.toString() + 'T' + time.toStringWithoutUtcOffset();
+    }
+
+
+    /**
+     * Return a string representation of this date-time, rounded to millisecond
+     * precision.
+     *
+     * <p>The format used is ISO8601 including the UTC offset.</p>
+     *
+     * @param minuteDuration 60, 61, or 62 seconds depending on the date being close to a
+     *                       leap second introduction and the magnitude of the leap
+     *                       second.
+     * @return string representation of this date, time, & UTC offset
+     * @see #toString(int, int)
      */
     public String toString(final int minuteDuration) {
+        return toString(minuteDuration, 3);
+    }
+
+    /**
+     * Return a string representation of this date-time, rounded to the given precision.
+     *
+     * <p>The format used is ISO8601 including the UTC offset.</p>
+     *
+     * @param minuteDuration 59, 60, 61, or 62 seconds depending on the date being close
+     *                       to a leap second introduction and the magnitude of the leap
+     *                       second.
+     * @param fractionDigits the number of digits to include after the decimal point in
+     *                       the string representation of the seconds. The date & time is
+     *                       first rounded as necessary. {@code fractionDigits} must be
+     *                       greater than or equal to {@code 0}.
+     * @return string representation of this date, time, & UTC offset
+     * @see #toStringRfc3339()
+     * @see #toStringWithoutUtcOffset()
+     * @since 11.0
+     */
+    public String toString(final int minuteDuration, final int fractionDigits) {
+        final DecimalFormat secondsFormat =
+                new DecimalFormat("00", new DecimalFormatSymbols(Locale.US));
+        secondsFormat.setMaximumFractionDigits(fractionDigits);
+        secondsFormat.setMinimumFractionDigits(fractionDigits);
+        DateComponents roundedDate = this.date;
+        TimeComponents roundedTime = this.time;
         double second = time.getSecond();
-        final double wrap = minuteDuration - 0.0005;
+        final double wrap = minuteDuration - 0.5 * FastMath.pow(10, -fractionDigits);
         if (second >= wrap) {
-            // we should wrap around next millisecond
+            // we should wrap around to the next minute
             int minute = time.getMinute();
             int hour   = time.getHour();
             int j2000  = date.getJ2000Day();
@@ -262,9 +308,12 @@ public class DateTimeComponents implements Serializable, Comparable<DateTimeComp
                     ++j2000;
                 }
             }
-            return new DateComponents(j2000).toString() + 'T' + new TimeComponents(hour, minute, second).toString();
+            roundedDate = new DateComponents(j2000);
+            roundedTime = new TimeComponents(hour, minute, second);
         }
-        return date.toString() + 'T' + time.toString();
+        return roundedDate.toString() + 'T' +
+                roundedTime.toStringWithoutUtcOffset(secondsFormat) +
+                roundedTime.formatUtcOffset();
     }
 
     /**
@@ -280,7 +329,8 @@ public class DateTimeComponents implements Serializable, Comparable<DateTimeComp
      * @return RFC 3339 format string.
      * @see <a href="https://tools.ietf.org/html/rfc3339#page-8">RFC 3339</a>
      * @see AbsoluteDate#toStringRfc3339(TimeScale)
-     * @see #toString(int)
+     * @see #toString(int, int)
+     * @see #toStringWithoutUtcOffset()
      */
     public String toStringRfc3339() {
         final DateComponents d = this.getDate();
diff --git a/src/main/java/org/orekit/time/FieldAbsoluteDate.java b/src/main/java/org/orekit/time/FieldAbsoluteDate.java
index e50eeccf9d98ad24fc999e31058852aab5b748b2..d269d3353efc51a27545fd652b29869458a8f89c 100644
--- a/src/main/java/org/orekit/time/FieldAbsoluteDate.java
+++ b/src/main/java/org/orekit/time/FieldAbsoluteDate.java
@@ -1480,26 +1480,39 @@ public class FieldAbsoluteDate<T extends CalculusFieldElement<T>>
         return (int) (l ^ (l >>> 32));
     }
 
-    /** Get a String representation of the instant location in UTC time scale.
+    /**
+     * Get a String representation of the instant location with up to 16 digits of
+     * precision for the seconds value.
+     *
+     * <p> Since this method is used in exception messages and error handling every
+     * effort is made to return some representation of the instant. If UTC is available
+     * from the default data context then it is used to format the string in UTC. If not
+     * then TAI is used. Finally if the prior attempts fail this method falls back to
+     * converting this class's internal representation to a string.
      *
      * <p>This method uses the {@link DataContext#getDefault() default data context}.
      *
-     * @return a string representation of the instance,
-     * in ISO-8601 format with milliseconds accuracy
+     * @return a string representation of the instance, in ISO-8601 format if UTC is
+     * available from the default data context.
+     * @see AbsoluteDate#toString()
      * @see #toString(TimeScale)
+     * @see DateTimeComponents#toString(int, int)
      */
     @DefaultDataContext
     public String toString() {
-        return toString(DataContext.getDefault().getTimeScales().getUTC());
+        return toAbsoluteDate().toString();
     }
 
-    /** Get a String representation of the instant location.
+    /**
+     * Get a String representation of the instant location in ISO-8601 format without the
+     * UTC offset and with up to 16 digits of precision for the seconds value.
+     *
      * @param timeScale time scale to use
-     * @return a string representation of the instance,
-     * in ISO-8601 format with milliseconds accuracy
+     * @return a string representation of the instance.
+     * @see DateTimeComponents#toString(int, int)
      */
     public String toString(final TimeScale timeScale) {
-        return getComponents(timeScale).toString(timeScale.minuteDuration(this));
+        return getComponents(timeScale).toStringWithoutUtcOffset();
     }
 
     /** Get a String representation of the instant location for a local time.
diff --git a/src/main/java/org/orekit/time/TimeComponents.java b/src/main/java/org/orekit/time/TimeComponents.java
index f65e627f52c1f6157600a5689028c330d5704e97..5091b1af21c057bf7f0d22d5f9e7556c6dad90ff 100644
--- a/src/main/java/org/orekit/time/TimeComponents.java
+++ b/src/main/java/org/orekit/time/TimeComponents.java
@@ -47,12 +47,9 @@ public class TimeComponents implements Serializable, Comparable<TimeComponents>
     /** Serializable UID. */
     private static final long serialVersionUID = 20160331L;
 
-    /** Format for hours and minutes. */
-    private static final DecimalFormat TWO_DIGITS = new DecimalFormat("00");
-
-    /** Format for seconds. */
-    private static final DecimalFormat SECONDS_FORMAT =
-        new DecimalFormat("00.000", new DecimalFormatSymbols(Locale.US));
+    /** Formatting symbols used in {@link #toString()}. */
+    private static final DecimalFormatSymbols US_SYMBOLS =
+            new DecimalFormatSymbols(Locale.US);
 
     /** Basic and extends formats for local time, with optional timezone. */
     private static final Pattern ISO8601_FORMATS = Pattern.compile("^(\\d\\d):?(\\d\\d):?(\\d\\d(?:[.,]\\d+)?)?(?:Z|([-+]\\d\\d(?::?\\d\\d)?))?$");
@@ -420,21 +417,57 @@ public class TimeComponents implements Serializable, Comparable<TimeComponents>
         return second + 60 * (minute - minutesFromUTC) + 3600 * hour;
     }
 
-    /** Get a string representation of the time.
-     * @return string representation of the time
+    /**
+     * Package private method that allows specification of seconds format. Allows access
+     * from {@link DateTimeComponents#toString(int, int)}. Access from outside of rounding
+     * methods would result in invalid times, see #590, #591.
+     *
+     * @param secondsFormat for the seconds.
+     * @return string without UTC offset.
+     */
+    String toStringWithoutUtcOffset(final DecimalFormat secondsFormat) {
+        return String.format("%02d:%02d:%s", hour, minute, secondsFormat.format(second));
+    }
+
+    /**
+     * Get a string representation of the time without the offset from UTC.
+     *
+     * @return a string representation of the time in an ISO 8601 like format.
+     * @see #formatUtcOffset()
+     * @see #toString()
+     */
+    public String toStringWithoutUtcOffset() {
+        // create formats here as they are not thread safe
+        // Format for seconds to prevent rounding up to an invalid time. See #591
+        final DecimalFormat secondsFormat =
+                new DecimalFormat("00.000###########", US_SYMBOLS);
+        return toStringWithoutUtcOffset(secondsFormat);
+    }
+
+    /**
+     * Get the UTC offset as a string in ISO8601 format. For example, {@code +00:00}.
+     *
+     * @return the UTC offset as a string.
+     * @see #toStringWithoutUtcOffset()
+     * @see #toString()
+     */
+    public String formatUtcOffset() {
+        final int hourOffset = FastMath.abs(minutesFromUTC) / 60;
+        final int minuteOffset = FastMath.abs(minutesFromUTC) % 60;
+        return (minutesFromUTC < 0 ? '-' : '+') +
+                String.format("%02d:%02d", hourOffset, minuteOffset);
+    }
+
+    /**
+     * Get a string representation of the time including the offset from UTC.
+     *
+     * @return string representation of the time in an ISO 8601 like format including the
+     * UTC offset.
+     * @see #toStringWithoutUtcOffset()
+     * @see #formatUtcOffset()
      */
     public String toString() {
-        StringBuilder builder  = new StringBuilder().
-                                 append(TWO_DIGITS.format(hour)).append(':').
-                                 append(TWO_DIGITS.format(minute)).append(':').
-                                 append(SECONDS_FORMAT.format(second));
-        if (minutesFromUTC != 0) {
-            builder = builder.
-                      append(minutesFromUTC < 0 ? '-' : '+').
-                      append(TWO_DIGITS.format(FastMath.abs(minutesFromUTC) / 60)).append(':').
-                      append(TWO_DIGITS.format(FastMath.abs(minutesFromUTC) % 60));
-        }
-        return builder.toString();
+        return toStringWithoutUtcOffset() + formatUtcOffset();
     }
 
     /** {@inheritDoc} */
diff --git a/src/main/java/org/orekit/utils/GenericTimeStampedCache.java b/src/main/java/org/orekit/utils/GenericTimeStampedCache.java
index eea454ffc09969b32eb8707afdb836439b39ccb1..e96578a54fde17b37c2e7381a566361b57161f51 100644
--- a/src/main/java/org/orekit/utils/GenericTimeStampedCache.java
+++ b/src/main/java/org/orekit/utils/GenericTimeStampedCache.java
@@ -724,9 +724,10 @@ public class GenericTimeStampedCache<T extends TimeStamped> implements TimeStamp
             }
 
             if (!inserted) {
+                final AbsoluteDate earliest = cache.get(0).getData().getDate();
                 throw new TimeStampedCacheException(
                         OrekitMessages.UNABLE_TO_GENERATE_NEW_DATA_BEFORE,
-                        cache.get(0).getData().getDate(), requestedDate);
+                        earliest, requestedDate, earliest.durationFrom(requestedDate));
             }
 
             // evict excess data at end
@@ -763,10 +764,10 @@ public class GenericTimeStampedCache<T extends TimeStamped> implements TimeStamp
             }
 
             if (!appended) {
+                final AbsoluteDate latest = cache.get(cache.size() - 1).getData().getDate();
                 throw new TimeStampedCacheException(
                         OrekitMessages.UNABLE_TO_GENERATE_NEW_DATA_AFTER,
-                        cache.get(cache.size() - 1).getData().getDate(),
-                        requestedDate);
+                        latest, requestedDate, requestedDate.durationFrom(latest));
             }
 
             // evict excess data at start
@@ -794,10 +795,11 @@ public class GenericTimeStampedCache<T extends TimeStamped> implements TimeStamp
                 throw new TimeStampedCacheException(OrekitMessages.NO_DATA_GENERATED, date);
             }
             for (int i = 1; i < entries.size(); ++i) {
-                if (entries.get(i).getDate().compareTo(entries.get(i - 1).getDate()) < 0) {
+                final AbsoluteDate previous = entries.get(i - 1).getDate();
+                final AbsoluteDate current = entries.get(i).getDate();
+                if (current.compareTo(previous) < 0) {
                     throw new TimeStampedCacheException(OrekitMessages.NON_CHRONOLOGICALLY_SORTED_ENTRIES,
-                                                                  entries.get(i - 1).getDate(),
-                                                                  entries.get(i).getDate());
+                            previous, current, previous.durationFrom(current));
                 }
             }
             return entries;
diff --git a/src/main/java/org/orekit/utils/ImmutableTimeStampedCache.java b/src/main/java/org/orekit/utils/ImmutableTimeStampedCache.java
index 4eb9adbb486401260bef481a2c8732b3f5b17bb7..f7b2b3695264b02d764c996c661318dd453c18b0 100644
--- a/src/main/java/org/orekit/utils/ImmutableTimeStampedCache.java
+++ b/src/main/java/org/orekit/utils/ImmutableTimeStampedCache.java
@@ -116,11 +116,13 @@ public class ImmutableTimeStampedCache<T extends TimeStamped>
 
         // check index in in the range of the data
         if (i < 0) {
+            final AbsoluteDate earliest = this.getEarliest().getDate();
             throw new TimeStampedCacheException(OrekitMessages.UNABLE_TO_GENERATE_NEW_DATA_BEFORE,
-                                                this.getEarliest().getDate(), central);
+                    earliest, central, earliest.durationFrom(central));
         } else if (i >= this.data.size()) {
+            final AbsoluteDate latest = this.getLatest().getDate();
             throw new TimeStampedCacheException(OrekitMessages.UNABLE_TO_GENERATE_NEW_DATA_AFTER,
-                                                this.getLatest().getDate(), central);
+                    latest, central, central.durationFrom(latest));
         }
 
         // force unbalanced range if necessary
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_da.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_da.utf8
index 1123a967e83ba8f9de6ca1f8f7196823ceb00ffd..44b39ced44ce550c5aabdcafe04b1218cd2d58f8 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_da.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_da.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = ingen jordorienteringsparametre er indl
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = manglende jordorienteringsparametre mellem {0} og {1}
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = <MISSING TRANSLATION>
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = ingen jordorienteringsparametre
 
@@ -148,8 +151,9 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = for høj grad (n = {0}, maksimal potentiel
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = for høj kontrol (m = {0}, maksimal potentiel kontrol er {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = flere referencedatoer ({0} og {1}) fundet i tyngdefeltsfilen {2}
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+# SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = flere referencedatoer ({0} og {1}) fundet i tyngdefeltsfilen {2}
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = <MISSING TRANSLATION>
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = ingen TLE data tilgængelig for objektet {0}
@@ -232,8 +236,9 @@ FRAMES_MISMATCH = ramme ({0}) passer ikke med ramme ({1})
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = initialstatus er ikke præciseret for banepropagation
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE = hændelsesdatoen {0}, større end {1} minus {3} sekunder og mindre end {2} plus {3} sekunder, kan ikke lægges til
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+# EVENT_DATE_TOO_CLOSE = hændelsesdatoen {0}, større end {1} minus {3} sekunder og mindre end {2} plus {3} sekunder, kan ikke lægges til
+EVENT_DATE_TOO_CLOSE = <MISSING TRANSLATION>
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = kan ikke læse startblokken fra den binære JPL efemeridefil {0}
@@ -262,6 +267,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = dato udenfor gyldighedsperioden for {0} efe
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = dato udenfor gyldighedsperioden for efemeriderne: {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = <MISSING TRANSLATION>
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = <MISSING TRANSLATION>
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = to uventede højdeværdier: {0} og {1}, for en asimut: {2}
 
@@ -394,16 +405,17 @@ NOT_ENOUGH_CACHED_NEIGHBORS = for få mellemlagrede naboer: {0} (skal mindst væ
 # no cached entries
 NO_CACHED_ENTRIES = ingen mellemlagrede poster
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = genererede poster er ikke sorterede: {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+# NON_CHRONOLOGICALLY_SORTED_ENTRIES = genererede poster er ikke sorterede: {0} > {1}
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = <MISSING TRANSLATION>
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = ingen data genereret rundt om dato: {0}
 
-# unable to generate new data before {0}, data requested for {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
 UNABLE_TO_GENERATE_NEW_DATA_BEFORE = <MISSING TRANSLATION>
 
-# unable to generate new data after {0}, data requested for {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
 UNABLE_TO_GENERATE_NEW_DATA_AFTER = <MISSING TRANSLATION>
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
@@ -621,13 +633,13 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = <MISSING TRANSLATION
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = <MISSING TRANSLATION>
 
-# observations {0} and {1} are not in chronological dates
+# observations are not in chronological order: {0} is {2} s after {1}
 NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = <MISSING TRANSLATION>
 
-# observations {0}, {1} and {2} must have different dates
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
 NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # observations are not in the same plane
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_de.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_de.utf8
index 7f8a67c13f684a353b6d1a8060f52af4cdfb55dd..ed94a4d3cd976a10f177d7c0745b4b1d6728e3f0 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_de.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_de.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = Orientierungsparameter der Erde sind ni
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = Orientierungsparameter der Erde zwischen {0} und {1} fehlen
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = <MISSING TRANSLATION>
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = Es sind keine Orientierungsparameter der Erde geladen
 
@@ -148,8 +151,9 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = Degree zu groß (n = {0}, maximaler Degree
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = Order zu groß (m = {0}, maximale Order des Potenzials ist {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = mehrere Referenz-Daten ({0} und {1}) in Gravitätsfeld Datei {2} gefunden
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+# SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = mehrere Referenz-Daten ({0} und {1}) in Gravitätsfeld Datei {2} gefunden
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = <MISSING TRANSLATION>
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = keine TLE Daten verfügbar für Objekt {0}
@@ -232,8 +236,9 @@ FRAMES_MISMATCH = Koordinatennetz ({0}) stimmt nicht mit Koordinatennetz ({1}) 
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = Anfangs Status nicht spezifiziert für Orbit-propagation
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE = Ereignisdatum {0}, grösser als {1} minus {3} Sekunden and kleiner als {2} plus {3} Sekunden, kann nicht addiert werden
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+# EVENT_DATE_TOO_CLOSE = Ereignisdatum {0}, grösser als {1} minus {3} Sekunden and kleiner als {2} plus {3} Sekunden, kann nicht addiert werden
+EVENT_DATE_TOO_CLOSE = <MISSING TRANSLATION>
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = Die Kopfzeile der JPL Ephemerides Binärdatei {0} ist nicht lesbar
@@ -262,6 +267,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = Datum nicht im zulässigen Bereich für {0}
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = Datum nicht im zulässigen Bereich für ephemerides: {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = <MISSING TRANSLATION>
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = <MISSING TRANSLATION>
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = unerwartet zwei Höhenwerte: {0} und {1}, für einen Azimutwinkel: {2}
 
@@ -394,16 +405,17 @@ NOT_ENOUGH_CACHED_NEIGHBORS = nicht genug Nachbareinträge im Cache verfügbar:
 # no cached entries
 NO_CACHED_ENTRIES = keine Cache Einträge verfügbar
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = generierte Einträge sind nicht chronologisch sortiert: {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+# NON_CHRONOLOGICALLY_SORTED_ENTRIES = generierte Einträge sind nicht chronologisch sortiert: {0} > {1}
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = <MISSING TRANSLATION>
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = es wurden keine Daten rund um das Datum {0} generiert
 
-# unable to generate new data before {0}, data requested for {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
 UNABLE_TO_GENERATE_NEW_DATA_BEFORE = <MISSING TRANSLATION>
 
-# unable to generate new data after {0}, data requested for {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
 UNABLE_TO_GENERATE_NEW_DATA_AFTER = <MISSING TRANSLATION>
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
@@ -621,13 +633,14 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = Ungültige Messtypen
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = Die Frequenzen {0} und {1} sind nicht kompatibel für folgende Kombinationen {2}
 
-# observations {0} and {1} are not in chronological dates
-NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = Die Beobachtungen {0} und {1} besitzen keine chronologischen Daten
+# observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}
+# NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = Die Beobachtungen {0} und {1} besitzen keine chronologischen Daten
+NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = Momentan wird noch die ExceptionalDataContext Klasse benutzt. Diese wird typischerweise ausschließlich für das Erkennen von Entwicklerfehler benutzt.
 
-# observations {0}, {1} and {2} must have different dates
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
 NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # observations are not in the same plane
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_el.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_el.utf8
index faa4b62815649e9702103150ba3e4f1e47dc077e..6cb30b6b826940abe8f9ceebaf2dede5744ae072 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_el.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_el.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = καμία φορτωμένη Παρά
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = ελλιπείς Παράμετροι Προσανατολισμού της Γης μεταξύ {0} και{1}  
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = <MISSING TRANSLATION>
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = <MISSING TRANSLATION>
 
@@ -148,8 +151,9 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = πολύ μεγάλος βαθμός (n = {
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = πολύ μεγάλη τάξη (m = {0}, δυνατή μέγιστη τάξη είναι {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = διάφορες ημερομηνίες αναφοράς ({0} και {1}) βρέθηκαν στο αρχείο βαρυτικού πεδίου {2}
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+# SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = διάφορες ημερομηνίες αναφοράς ({0} και {1}) βρέθηκαν στο αρχείο βαρυτικού πεδίου {2}
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = <MISSING TRANSLATION>
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = κανένα δεδομένο TLE διαθέσιμο για το αντικείμενο {0}
@@ -232,8 +236,9 @@ FRAMES_MISMATCH =  Το πλαίσιο ({0}) δεν αντιστοιχεί στ
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = H αρχική κατάσταση δεν προσδιορίζεται για την τροχιά διάδοσης 
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE = ημερομηνία γεγονότος {0}, μεγαλύτερη από {1} μείον {3} δευτερόλεπτα και μικρότερη από {2} συν {3} δευτερόλεπτα, δεν μπορεί να προστεθεί
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+# EVENT_DATE_TOO_CLOSE = ημερομηνία γεγονότος {0}, μεγαλύτερη από {1} μείον {3} δευτερόλεπτα και μικρότερη από {2} συν {3} δευτερόλεπτα, δεν μπορεί να προστεθεί
+EVENT_DATE_TOO_CLOSE = <MISSING TRANSLATION>
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = αδύνατο να διαβάσει καταγραφή επικεφαλίδος από το JPL δυαδικό αρχείο {0}
@@ -262,6 +267,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = ημερομηνία εκτός εύρου
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = ημερομηνία εκτός εύρους για εφημερίδες: {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = <MISSING TRANSLATION>
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = <MISSING TRANSLATION>
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = απροσδόκητες υψομετρικές τιμές: ({0} και {1}), για ένα αζιμούθιο: {2}
 
@@ -394,16 +405,17 @@ NOT_ENOUGH_CACHED_NEIGHBORS = πολύ μικρός αριθμός των προ
 # no cached entries
 NO_CACHED_ENTRIES = καμία προσωρινά αποθηκευμένη καταχώρηση
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = οι παράγωγες είσοδοι δεν είναι ταξινομημένες: {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+# NON_CHRONOLOGICALLY_SORTED_ENTRIES = οι παράγωγες είσοδοι δεν είναι ταξινομημένες: {0} > {1}
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = <MISSING TRANSLATION>
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = κανένα δεδομένο δεν έχει παραχθεί γύρω από την ημερομηνία: {0}
 
-# unable to generate new data before {0}, data requested for {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
 UNABLE_TO_GENERATE_NEW_DATA_BEFORE = <MISSING TRANSLATION>
 
-# unable to generate new data after {0}, data requested for {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
 UNABLE_TO_GENERATE_NEW_DATA_AFTER = <MISSING TRANSLATION>
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
@@ -621,13 +633,13 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = <MISSING TRANSLATION
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = <MISSING TRANSLATION>
 
-# observations {0} and {1} are not in chronological dates
+# observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}
 NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = <MISSING TRANSLATION>
 
-# observations {0}, {1} and {2} must have different dates
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
 NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # observations are not in the same plane
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_en.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_en.utf8
index 0ab4c34ad0b8632dfdba7c886be12de6168ccbef..ae638487a5e3e086be94fab95cb253bb9c0ed47b 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_en.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_en.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = no Earth Orientation Parameters loaded
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = missing Earth Orientation Parameters between {0} and {1}
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = missing Earth Orientation Parameters
 
@@ -148,8 +151,8 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = too large degree (n = {0}, potential maxima
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = too large order (m = {0}, potential maximal order is {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = several reference dates ({0} and {1}) found in gravity field file {2}
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = no TLE data available for object {0}
@@ -232,8 +235,8 @@ FRAMES_MISMATCH = frame {0} does not match frame {1}
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = initial state not specified for orbit propagation
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE = event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+EVENT_DATE_TOO_CLOSE = target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = unable to read header record from JPL ephemerides binary file {0}
@@ -262,6 +265,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = out of range date for {0} ephemerides: {1}
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = out of range date for ephemerides: {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 
@@ -394,17 +403,17 @@ NOT_ENOUGH_CACHED_NEIGHBORS =  too small number of cached neighbors: {0} (must b
 # no cached entries
 NO_CACHED_ENTRIES = no cached entries
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = generated entries not sorted: {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = no data generated around date: {0}
 
-# unable to generate new data before {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_BEFORE = unable to generate new data before {0}, data requested for {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
+UNABLE_TO_GENERATE_NEW_DATA_BEFORE = unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
 
-# unable to generate new data after {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_AFTER = unable to generate new data after {0}, data requested for {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after then
+UNABLE_TO_GENERATE_NEW_DATA_AFTER = unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
 UNABLE_TO_COMPUTE_HYPERBOLIC_ECCENTRIC_ANOMALY = unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
@@ -621,14 +630,14 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = invalid measurement
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = frequencies {0} and {1} are incompatibles for the {2} combination
 
-# observations {0} and {1} are not in chronological dates
-NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = observations {0} and {1} are not in chronological dates
+# observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}
+NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 
-# observations {0}, {1} and {2} must have different dates
-NON_DIFFERENT_DATES_FOR_OBSERVATIONS = observations {0}, {1} and {2} must have different dates
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
+NON_DIFFERENT_DATES_FOR_OBSERVATIONS = Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
 
 # observations are not in the same plane
 NON_COPLANAR_POINTS = observations are not in the same plane
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_es.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_es.utf8
index 4534c26cd662f7fb2aa7a957385eded7befcf2a6..6fce3184a3ca4184b5408f63184719bf981cfb81 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_es.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_es.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = los parámetros de orientación de la T
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = faltan parámetros de orientación de la Tierra entre {0} y {1}
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = <MISSING TRANSLATION>
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = faltan los parámetros de orientación de la Tierra
 
@@ -148,8 +151,9 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = grado demasiado alto (n = {0}, el grado de
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = orden demasiado alto (n = {0}, el orden de potencial máximo es {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = se han encontrado varias fechas de referencia ({0} y {1}) en el fichero de campo de gravedad {2}
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+# SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = se han encontrado varias fechas de referencia ({0} y {1}) en el fichero de campo de gravedad {2}
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = <MISSING TRANSLATION>
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = no hay datos TLE disponibles para el objeto {0}
@@ -232,8 +236,9 @@ FRAMES_MISMATCH = el sistema de referencia ({0}) no corresponde al sistema de re
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = estado inicial no especificado para la extrapolación de órbita
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE = la fecha acontecimiento {0}, más grande que {1} menos {3} segundos y más pequeña que {2} más {3} segundos, no puede ser añadida
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+# EVENT_DATE_TOO_CLOSE = la fecha acontecimiento {0}, más grande que {1} menos {3} segundos y más pequeña que {2} más {3} segundos, no puede ser añadida
+EVENT_DATE_TOO_CLOSE = <MISSING TRANSLATION>
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = imposible de leer el encabezado del fichero binario de efemérides del JPL {0}
@@ -262,6 +267,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = fecha fuera del rango de validez de las efe
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = fecha fuera del rango de validez de las efemérides : {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = <MISSING TRANSLATION>
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = <MISSING TRANSLATION>
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = datos inesperados, dos valores de elevación: {0} y {1}, para un acimut : {2}
 
@@ -394,17 +405,20 @@ NOT_ENOUGH_CACHED_NEIGHBORS = número de vecinos almacenados demasiado pequeño
 # no cached entries
 NO_CACHED_ENTRIES = ninguna entrada almacenada
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = las entradas generadas no están ordenadas: {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+# NON_CHRONOLOGICALLY_SORTED_ENTRIES = las entradas generadas no están ordenadas: {0} > {1}
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = <MISSING TRANSLATION>
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = ningún dato generado alrededor de la fecha: {0}
 
-# unable to generate new data before {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_BEFORE = no se pueden generar datos antes de {0}, los datos solicitados para {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
+# UNABLE_TO_GENERATE_NEW_DATA_BEFORE = no se pueden generar datos antes de {0}, los datos solicitados para {1}
+UNABLE_TO_GENERATE_NEW_DATA_BEFORE = <MISSING TRANSLATION>
 
-# unable to generate new data after {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_AFTER = no se pueden generar datos después de {0}, los datos solicitados para {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
+# UNABLE_TO_GENERATE_NEW_DATA_AFTER = no se pueden generar datos después de {0}, los datos solicitados para {1}
+UNABLE_TO_GENERATE_NEW_DATA_AFTER = <MISSING TRANSLATION>
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
 UNABLE_TO_COMPUTE_HYPERBOLIC_ECCENTRIC_ANOMALY = después de {0} iteraciones no se ha conseguido calcular la anomalía excéntrica hiperbólica a partir de la anomalía media
@@ -621,13 +635,13 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = <MISSING TRANSLATION
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = <MISSING TRANSLATION>
 
-# observations {0} and {1} are not in chronological dates
+# observations are not in chronological order: {0} is {2} s after {1}
 NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = <MISSING TRANSLATION>
 
-# observations {0}, {1} and {2} must have different dates
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
 NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # observations are not in the same plane
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_fr.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_fr.utf8
index afb04cba370a5742fc23e049a89e3c8300e04272..186297e31d0f0b57d691ba56e327bcd8c5b08877 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_fr.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_fr.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = aucun Paramètre d''Orientation de la T
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = paramètres d''Orientation de la Terre manquants entre {0} et {1}
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = <MISSING TRANSLATION>
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = paramètres d''Orientation de la Terre manquants
 
@@ -148,8 +151,9 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = degré trop important (n = {0}, le degré d
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = ordre trop important (n = {0}, l''ordre de potentiel maximal est {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = plusieurs dates de références ({0} et {1}) trouvées dans le fichier de champ de gravité {2}
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+# SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = plusieurs dates de références ({0} et {1}) trouvées dans le fichier de champ de gravité {2}
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = <MISSING TRANSLATION>
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = aucune donnée TLE n''est disponible pour l''objet {0}
@@ -232,8 +236,9 @@ FRAMES_MISMATCH = le repère ({0}) ne correspond pas au repère ({1})
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = état initial non spécifié pour l''extrapolation d''orbite
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE = la date évènement {0}, plus grande que {1} moins {3} secondes et plus petite que {2} plus {3} secondes, ne peut pas être ajoutée
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+# EVENT_DATE_TOO_CLOSE = la date évènement {0}, plus grande que {1} moins {3} secondes et plus petite que {2} plus {3} secondes, ne peut pas être ajoutée
+EVENT_DATE_TOO_CLOSE = <MISSING TRANSLATION>
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = impossible de lire l''en-tête du fichier d''éphémérides du JPL {0}
@@ -262,6 +267,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = date hors du domaine de validité des éph
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = date hors du domaine de validité des éphémérides : {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = <MISSING TRANSLATION>
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = <MISSING TRANSLATION>
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = données inattendues, deux valeurs de site : {0} et {1}, pour un azimut : {2}
 
@@ -394,17 +405,18 @@ NOT_ENOUGH_CACHED_NEIGHBORS =  nombre de voisins en cache trop petit : {0} (il f
 # no cached entries
 NO_CACHED_ENTRIES = aucune entrée en cache
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = les entrées générées ne sont pas dans l''ordre chronologique : {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+# NON_CHRONOLOGICALLY_SORTED_ENTRIES = les entrées générées ne sont pas dans l''ordre chronologique : {0} > {1}
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = <MISSING TRANSLATION>
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = aucune donnée générée aux alentours de la date : {0}
 
-# unable to generate new data before {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_BEFORE = impossible de générer des données avant le {0}, données requises pour {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
+UNABLE_TO_GENERATE_NEW_DATA_BEFORE = impossible de générer des données avant le {0}, données requises pour {1} qui est {2,number,0.0##############E0} s avant
 
-# unable to generate new data after {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_AFTER = impossible de générer des données après le {0}, données requises pour {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
+UNABLE_TO_GENERATE_NEW_DATA_AFTER = impossible de générer des données après le {0}, données requises pour {1} qui est {2,number,0.0##############E0} s après
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
 UNABLE_TO_COMPUTE_HYPERBOLIC_ECCENTRIC_ANOMALY = impossible de calculer l''anomalie excentrique hyperbolique à partir de l''anomalie moyenne après {0} itérations
@@ -621,14 +633,16 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = les types de mesure
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = les fréquences {0} et {1} sont incompatibles pour la combinaison {2}
 
-# observations {0} and {1} are not in chronological dates
-NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = les observations aux dates {0} et {1} ne sont pas dans l''ordre chronologique
+# observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}
+# NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = les observations aux dates {0} et {1} ne sont pas dans l''ordre chronologique
+NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = une utilisation de ExceptionalDataContext a été détectée. Ce mécanisme est généralement activé explicitement pour détecter des erreur de développement
 
-# observations {0}, {1} and {2} must have different dates
-NON_DIFFERENT_DATES_FOR_OBSERVATIONS = les observations {0}, {1} et {2} doivent avoir des dates différentes
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
+# NON_DIFFERENT_DATES_FOR_OBSERVATIONS = les observations {0}, {1} et {2} doivent avoir des dates différentes
+NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # observations are not in the same plane
 NON_COPLANAR_POINTS = les observations ne sont pas dans le même plan
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_gl.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_gl.utf8
index 26291d7e7487dd3262dfd019ef050b2779888205..70b5c9dc90a0e661ba022de18108996cc6ad9af4 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_gl.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_gl.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = os parámetros de orientación da Terra
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = faltan Parámetros de Orientación da Terra entre {0} e {1}
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = <MISSING TRANSLATION>
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = <MISSING TRANSLATION>
 
@@ -148,8 +151,9 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = grao demasiado grande (n = {0}, o grao de p
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = orde demasiado importante (n = {0}, a orde máxima de potencial é {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = varias datas de referencias ({0} e {1}) atopadas no ficheiro de campo de gravidade {2}
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+# SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = varias datas de referencias ({0} e {1}) atopadas no ficheiro de campo de gravidade {2}
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = <MISSING TRANSLATION>
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = non hay datos TLE disponibles para o obxeto {0}
@@ -232,8 +236,9 @@ FRAMES_MISMATCH = o sistema de referencia ({0}) non corresponde ao sistema de re
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = estado inicial non especificado para a extrapolación de órbita
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE =  a data acontecemento {0}, máis grande que {1}, menos {3} segundos e máis pequena que {2} máis {3} segundos, non pode ser engadida
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+# EVENT_DATE_TOO_CLOSE =  a data acontecemento {0}, máis grande que {1}, menos {3} segundos e máis pequena que {2} máis {3} segundos, non pode ser engadida
+EVENT_DATE_TOO_CLOSE =  <MISSING TRANSLATION>
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = imposible de ler o encabezado do ficheiro de efemérides do JPL {0}
@@ -262,6 +267,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = data fora do rango de validez das efemérid
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = data fora do rango de validez das efemérides : {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = <MISSING TRANSLATION>
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = <MISSING TRANSLATION>
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = datos inesperados, dous valores de elevación: {0} e {1}, para un acimut : {2}
 
@@ -394,17 +405,20 @@ NOT_ENOUGH_CACHED_NEIGHBORS = número de vecinos almacenados demasiado pequeno:
 # no cached entries
 NO_CACHED_ENTRIES = ningunha entrada almacenada
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = as entradas xeneradas non están en orde cronolóxica: {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+# NON_CHRONOLOGICALLY_SORTED_ENTRIES = as entradas xeneradas non están en orde cronolóxica: {0} > {1}
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = <MISSING TRANSLATION>
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = ningún dato xerado alrededor da data: {0}
 
-# unable to generate new data before {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_BEFORE = imposible de xerar datos antes de {0}, datos necesarios para {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
+# UNABLE_TO_GENERATE_NEW_DATA_BEFORE = imposible de xerar datos antes de {0}, datos necesarios para {1}
+UNABLE_TO_GENERATE_NEW_DATA_BEFORE = <MISSING TRANSLATION>
 
-# unable to generate new data after {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_AFTER = imposible de xerar datos despois de {0}, datos necesarios para {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
+# UNABLE_TO_GENERATE_NEW_DATA_AFTER = imposible de xerar datos despois de {0}, datos necesarios para {1}
+UNABLE_TO_GENERATE_NEW_DATA_AFTER = <MISSING TRANSLATION>
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
 UNABLE_TO_COMPUTE_HYPERBOLIC_ECCENTRIC_ANOMALY = imposible de calcular la anomalía excéntrica hiperbólica a partir de la anomalía media después de {0} iteraciones
@@ -621,13 +635,13 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = <MISSING TRANSLATION
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = <MISSING TRANSLATION>
 
-# observations {0} and {1} are not in chronological dates
+# observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}
 NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = <MISSING TRANSLATION>
 
-# observations {0}, {1} and {2} must have different dates
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
 NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # observations are not in the same plane
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_it.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_it.utf8
index 1f68723ee62a70821273f6a06b174ad7119bbfaf..3223822e05f55b7a0b35ba93d2874c542aebe1f5 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_it.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_it.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = nessun Parametro d''Orientamento della
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = Parametri d''Orientamento della Terra mancanti tra {0} e {1}
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = <MISSING TRANSLATION>
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = Parametri d''Orientamento della Terra mancanti
 
@@ -148,8 +151,9 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = grado troppo elevato (n = {0}, il grado mas
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = ordine troppo elevato (m = {0}, l''ordine massimo per il potenziale è {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = diverse date di riferimento ({0} e {1}) trovate nel file di campo gravitazionale {2}
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+# SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = diverse date di riferimento ({0} e {1}) trovate nel file di campo gravitazionale {2}
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = <MISSING TRANSLATION>
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = dati TLE non disponibili per l''oggetto {0}
@@ -232,8 +236,9 @@ FRAMES_MISMATCH = il sistema di riferimento ({0}) non corrisponde al sistema di
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = stato iniziale non specificato per la propagazione dell''orbita
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE = la data dell''evento {0}, superiore a {1} meno {3} secondi e inferiore a {2} più {3} secondi, non può esses aggiunta
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+# EVENT_DATE_TOO_CLOSE = la data dell''evento {0}, superiore a {1} meno {3} secondi e inferiore a {2} più {3} secondi, non può esses aggiunta
+EVENT_DATE_TOO_CLOSE = <MISSING TRANSLATION>
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = impossibile leggere l''intestazione del file di effemeridi del JPL {0}
@@ -262,6 +267,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = data fuori dell''intervallo di validità pe
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = data fuori dell''intervallo di validità per le effemeridi: {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = <MISSING TRANSLATION>
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = <MISSING TRANSLATION>
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = due valori di elevazione inattesi: {0} e {1}, per un solo azimut: {2}
 
@@ -394,17 +405,20 @@ NOT_ENOUGH_CACHED_NEIGHBORS = numero di vicini in cache troppo piccolo: {0} (dev
 # no cached entries
 NO_CACHED_ENTRIES = nessun dato nella cache
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = dati generati non in ordine cronologico: {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+# NON_CHRONOLOGICALLY_SORTED_ENTRIES = dati generati non in ordine cronologico: {0} > {1}
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = <MISSING TRANSLATION>
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = nessun dato generato intorno alla data: {0}
 
-# unable to generate new data before {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_BEFORE = impossibile generare dati prima del {0}, dati richiesti per {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
+# UNABLE_TO_GENERATE_NEW_DATA_BEFORE = impossibile generare dati prima del {0}, dati richiesti per {1}
+UNABLE_TO_GENERATE_NEW_DATA_BEFORE = <MISSING TRANSLATION>
 
-# unable to generate new data after {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_AFTER = impossibile generare dati dopo il {0}, dati richiesti per {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
+# UNABLE_TO_GENERATE_NEW_DATA_AFTER = impossibile generare dati dopo il {0}, dati richiesti per {1}
+UNABLE_TO_GENERATE_NEW_DATA_AFTER = <MISSING TRANSLATION>
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
 UNABLE_TO_COMPUTE_HYPERBOLIC_ECCENTRIC_ANOMALY = impossibile calcolare l''anomalia eccentrica iperbolica a partire dall''anomalia media dopo {0} iterazioni
@@ -621,14 +635,16 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = impossibile realizza
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = impossibile combinare le frequenze {0} e {1} per ottenere {2}
 
-# observations {0} and {1} are not in chronological dates
-NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = le osservazioni {0} e {1} non sono in ordine cronologico
+# observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}
+# NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = le osservazioni {0} e {1} non sono in ordine cronologico
+NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = rilevato utilizzo di ExceptionalDataContext. Si utilizza solitamente per rilevare errori di programmazione
 
-# observations {0}, {1} and {2} must have different dates
-NON_DIFFERENT_DATES_FOR_OBSERVATIONS = le osservazioni {0}, {1} e {2} non possono avere la stessa data
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
+# NON_DIFFERENT_DATES_FOR_OBSERVATIONS = le osservazioni {0}, {1} e {2} non possono avere la stessa data
+NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # observations are not in the same plane
 NON_COPLANAR_POINTS = le osservazioni non sono sullo stesso piano
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_no.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_no.utf8
index 5c4d019ce441540081ecad6e7aa4f7bd2479bc3b..0873c1935c2f4b6de910be044fa99589678b9b5f 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_no.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_no.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = ingen jordorienteringsparametere er las
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = manglende jordorienteringsparametere mellom {0} og {1}
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = <MISSING TRANSLATION>
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = manglende jordorienteringsparametere
 
@@ -148,8 +151,9 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = for høy grad (n = {0}, maksimal potensial
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = for høy kontroll (m = {0}, maksimal potensial kontrol er {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = flere referansedatoer ({0} og {1}) funnet i tyngdefeltsfilen {2}
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+# SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = flere referansedatoer ({0} og {1}) funnet i tyngdefeltsfilen {2}
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = <MISSING TRANSLATION>
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = ingen TLE data tilgjengelig for objektet {0}
@@ -232,8 +236,9 @@ FRAMES_MISMATCH = ramme ({0}) passer ikke med ramme ({1})
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = initialstatusen er ikke presisert for banepropagasjon
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE = hendelsedatoen {0}, større enn {1} minus {3} sekunder og mindre enn {2} pluss {3} sekunder, kan ikke bli legget til
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+# EVENT_DATE_TOO_CLOSE = hendelsedatoen {0}, større enn {1} minus {3} sekunder og mindre enn {2} pluss {3} sekunder, kan ikke bli legget til
+EVENT_DATE_TOO_CLOSE = <MISSING TRANSLATION>
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = umulig å lese startblokken fra den binære JPL efemeridefilen {0}
@@ -262,6 +267,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = dato utenfor gyldighetsperioden til {0} efe
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = dato utenfor gyldighetsperioden til efemeridene: {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = <MISSING TRANSLATION>
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = <MISSING TRANSLATION>
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = uventete to høydeverdier: {0} og {1}, for en asimut: {2}
 
@@ -394,16 +405,19 @@ NOT_ENOUGH_CACHED_NEIGHBORS = for få bufrete naboer: {0} (må i allefall være
 # no cached entries
 NO_CACHED_ENTRIES = ingen bufrete oppføringer
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = generte oppføringer er ikke sorterte: {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+# NON_CHRONOLOGICALLY_SORTED_ENTRIES = generte oppføringer er ikke sorterte: {0} > {1}
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = <MISSING TRANSLATION>
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = ingen data generert rundt dato: {0}
 
-# unable to generate new data before {0}, data requested for {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
+# UNABLE_TO_GENERATE_NEW_DATA_BEFORE = <MISSING TRANSLATION>
 UNABLE_TO_GENERATE_NEW_DATA_BEFORE = <MISSING TRANSLATION>
 
-# unable to generate new data after {0}, data requested for {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
+# UNABLE_TO_GENERATE_NEW_DATA_AFTER = <MISSING TRANSLATION>
 UNABLE_TO_GENERATE_NEW_DATA_AFTER = <MISSING TRANSLATION>
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
@@ -621,13 +635,15 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = ugyldige målingstyp
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = frekvensene {0} og {1} er uforenlige for {2} kombinasjonen
 
-# observations {0} and {1} are not in chronological dates
-NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = observasjonene {0} og {1} er ikke kronologiske datoer
+# observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}
+# NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = observasjonene {0} og {1} er ikke kronologiske datoer
+NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = Bruk av ExceptionalDataContext funnet. Denne brukes typisk til å oppdage utviklingsproblemer.
 
-# observations {0}, {1} and {2} must have different dates
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
+# NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # observations are not in the same plane
diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_ro.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_ro.utf8
index fba750f4d35119244c4d5713a28d0cf2743867b0..0b095d7bdc93e7f368cd14c7f3b30f4d2e65bb1f 100644
--- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_ro.utf8
+++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_ro.utf8
@@ -67,6 +67,9 @@ NO_EARTH_ORIENTATION_PARAMETERS_LOADED = niciun Parametru de Orientare al Pămâ
 # missing Earth Orientation Parameters between {0} and {1}
 MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES = Parametrii de Orientare ai Pământului lipsesc între {0} și {1}
 
+# missing Earth Orientation Parameters between {0} and {1}, gap is {2,number,0.0##############E0} s
+MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP = <MISSING TRANSLATION>
+
 # missing Earth Orientation Parameters
 NO_EARTH_ORIENTATION_PARAMETERS = Parametrii de Orientare ai Pământului lipsesc
 
@@ -148,8 +151,9 @@ TOO_LARGE_DEGREE_FOR_GRAVITY_FIELD = grad prea mare (n = {0}, gradul maxim al po
 # too large order (m = {0}, potential maximal order is {1})
 TOO_LARGE_ORDER_FOR_GRAVITY_FIELD = ordin prea mare (n = {0}, ordinul maxim al potențialului este {1})
 
-# several reference dates ({0} and {1}) found in gravity field file {2}
-SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = mai multe date de referință ({0} and {1}) descoperite în fișierul de câmp gravitațional {2}
+# several reference dates ({0} and {1} differ by {3,number,0.0##############E0} s) found in gravity field file {2}
+# SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = mai multe date de referință ({0} and {1}) descoperite în fișierul de câmp gravitațional {2}
+SEVERAL_REFERENCE_DATES_IN_GRAVITY_FIELD = <MISSING TRANSLATION>
 
 # no TLE data available for object {0}
 NO_TLE_FOR_OBJECT = nu sunt disponibile date TLE pentru obiectul {0}
@@ -232,8 +236,9 @@ FRAMES_MISMATCH = sistemul de referință {0} nu corespunde sistemului de referi
 # initial state not specified for orbit propagation
 INITIAL_STATE_NOT_SPECIFIED_FOR_ORBIT_PROPAGATION = stare inițială nespecificată pentru propagarea orbitală
 
-# event date {0}, greater than {1} minus {3} seconds and smaller than {2} plus {3} seconds, cannot be added
-EVENT_DATE_TOO_CLOSE = data evenimentului {0}, mai mare decât {1} minus {3} secunde și mai mică decât {2} plus {3} secunde, nu poate fi adăugată
+# target event date must be before {1} by {3,number,0.0##############E0} seconds or after {2} by {3,number,0.0##############E0} seconds, but target event date {0} is {4,number,0.0##############E0} seconds before {1} and {5,number,0.0##############E0} seconds after {2} so it cannot be added
+# EVENT_DATE_TOO_CLOSE = data evenimentului {0}, mai mare decât {1} minus {3} secunde și mai mică decât {2} plus {3} secunde, nu poate fi adăugată
+EVENT_DATE_TOO_CLOSE = <MISSING TRANSLATION>
 
 # unable to read header record from JPL ephemerides binary file {0}
 UNABLE_TO_READ_JPL_HEADER = imposibil de citit antetul fișierului de efemeride JPL {0}
@@ -262,6 +267,12 @@ OUT_OF_RANGE_BODY_EPHEMERIDES_DATE = dată în afara domeniului de valabilitate
 # out of range date for ephemerides: {0}, [{1}, {2}]
 OUT_OF_RANGE_EPHEMERIDES_DATE = dată în afara domeniului de valabilitate al efemeridelor : {0}, [{1}, {2}]
 
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s before [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE = <MISSING TRANSLATION>
+
+# out of range date for ephemerides: {0} is {3,number,0.0##############E0} s after [{1}, {2}]
+OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER = <MISSING TRANSLATION>
+
 # unexpected two elevation values: {0} and {1}, for one azimuth: {2}
 UNEXPECTED_TWO_ELEVATION_VALUES_FOR_ONE_AZIMUTH = date neașteptate, două valori ale elevației: {0} and {1}, pentru o singură valoare a azimutului: {2}
 
@@ -394,17 +405,20 @@ NOT_ENOUGH_CACHED_NEIGHBORS =  numărul de vecini din cache este prea mic: {0} (
 # no cached entries
 NO_CACHED_ENTRIES = nu există înregistrări în cache
 
-# generated entries not sorted: {0} > {1}
-NON_CHRONOLOGICALLY_SORTED_ENTRIES = înregistrările generate nu sunt în ordine cronologică: {0} > {1}
+# generated entries not sorted: {0} > {1} by {2,number,0.0##############E0} s
+# NON_CHRONOLOGICALLY_SORTED_ENTRIES = înregistrările generate nu sunt în ordine cronologică: {0} > {1}
+NON_CHRONOLOGICALLY_SORTED_ENTRIES = <MISSING TRANSLATION>
 
 # no data generated around date: {0}
 NO_DATA_GENERATED = nu există informații generate în jurul datei: {0}
 
-# unable to generate new data before {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_BEFORE = imposibil de generat noi date înainte de {0}, date solicitate pentru {1}
+# unable to generate new data before {0}, but data is requested for {1} which is {2,number,0.0##############E0} s before
+# UNABLE_TO_GENERATE_NEW_DATA_BEFORE = imposibil de generat noi date înainte de {0}, date solicitate pentru {1}
+UNABLE_TO_GENERATE_NEW_DATA_BEFORE = <MISSING TRANSLATION>
 
-# unable to generate new data after {0}, data requested for {1}
-UNABLE_TO_GENERATE_NEW_DATA_AFTER = imposibil de generat noi date după {0}, date solicitate pentru {1}
+# unable to generate new data after {0}, but data is requested for {1} which is {2,number,0.0##############E0} s after
+# UNABLE_TO_GENERATE_NEW_DATA_AFTER = imposibil de generat noi date după {0}, date solicitate pentru {1}
+UNABLE_TO_GENERATE_NEW_DATA_AFTER = <MISSING TRANSLATION>
 
 # unable to compute hyperbolic eccentric anomaly from the mean anomaly after {0} iterations
 UNABLE_TO_COMPUTE_HYPERBOLIC_ECCENTRIC_ANOMALY = imposibil de calculat anomalia excentrică hiperbolică pornind de la anomalia medie după {0} iterații
@@ -621,14 +635,16 @@ INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = tipurile de măsuri
 # frequencies {0} and {1} are incompatibles for the {2} combination
 INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = frecvențele {0} și {1} sunt incompatibile pentru combinația {2}
 
-# observations {0} and {1} are not in chronological dates
-NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = observațiile de la datele {0} și {1} nu sunt în ordine cronologică
+# observations are not in chronological order: {0} is {2,number,0.0##############E0} s after {1}
+# NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = observațiile de la datele {0} și {1} nu sunt în ordine cronologică
+NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # Use of the ExceptionalDataContext detected. This is typically used to detect developer errors.
 EXCEPTIONAL_DATA_CONTEXT = a fost detectată o utilizare a ExceptionalDataContext. Acest mecanism este utilizat în general pentru detectarea unei erori de dezvoltare
 
-# observations {0}, {1} and {2} must have different dates
-NON_DIFFERENT_DATES_FOR_OBSERVATIONS = observațiile {0}, {1} și {2} trebuie să aibă date diferite
+# Observations must have different dates: {0}, {1} ({3,number,0.0##############E0} s from first observation), and {2} ({4,number,0.0##############E0} s from first observation, {5,number,0.0##############E0} s from second observation)
+# NON_DIFFERENT_DATES_FOR_OBSERVATIONS = observațiile {0}, {1} și {2} trebuie să aibă date diferite
+NON_DIFFERENT_DATES_FOR_OBSERVATIONS = <MISSING TRANSLATION>
 
 # observations are not in the same plane
 NON_COPLANAR_POINTS = observațiile nu sunt în același plan
diff --git a/src/test/java/org/orekit/errors/OrekitMessagesTest.java b/src/test/java/org/orekit/errors/OrekitMessagesTest.java
index a0489d15eadbed1289bb890fe13683523e6f957c..ac493c3ab3ba4fcccbdfef5523b0e11f18010d97 100644
--- a/src/test/java/org/orekit/errors/OrekitMessagesTest.java
+++ b/src/test/java/org/orekit/errors/OrekitMessagesTest.java
@@ -30,7 +30,7 @@ public class OrekitMessagesTest {
 
     @Test
     public void testMessageNumber() {
-        Assert.assertEquals(244, OrekitMessages.values().length);
+        Assert.assertEquals(247, OrekitMessages.values().length);
     }
 
     @Test
diff --git a/src/test/java/org/orekit/errors/TimeStampedCacheExceptionTest.java b/src/test/java/org/orekit/errors/TimeStampedCacheExceptionTest.java
index 8504b608c7af34236cf981631b9645fa7f3402e4..c57d4fc1c577be92e2a581edfca6b27850c29efe 100644
--- a/src/test/java/org/orekit/errors/TimeStampedCacheExceptionTest.java
+++ b/src/test/java/org/orekit/errors/TimeStampedCacheExceptionTest.java
@@ -32,12 +32,14 @@ public class TimeStampedCacheExceptionTest {
     public void testMessage() {
         TimeStampedCacheException e =
                         new TimeStampedCacheException(OrekitMessages.UNABLE_TO_GENERATE_NEW_DATA_BEFORE,
-                                                      AbsoluteDate.MODIFIED_JULIAN_EPOCH);
+                                                      AbsoluteDate.MODIFIED_JULIAN_EPOCH,
+                                                      AbsoluteDate.MODIFIED_JULIAN_EPOCH.shiftedBy(-1e-16),
+                                                      1e-16);
         Assert.assertEquals(OrekitMessages.UNABLE_TO_GENERATE_NEW_DATA_BEFORE, e.getSpecifier());
-        Assert.assertEquals(1, e.getParts().length);
+        Assert.assertEquals(3, e.getParts().length);
         Assert.assertEquals(0, ((AbsoluteDate) e.getParts()[0]).durationFrom(AbsoluteDate.MODIFIED_JULIAN_EPOCH), 1.0e-10);
         Assert.assertEquals(e.getMessage(Locale.getDefault()), e.getLocalizedMessage());
-        Assert.assertEquals("impossible de générer des données avant le 1858-11-16T23:59:27.816, données requises pour {1}",
+        Assert.assertEquals("impossible de générer des données avant le 1858-11-16T23:59:27.816Z, données requises pour 1858-11-16T23:59:27.816Z qui est 1,0E-16 s avant",
                             e.getMessage(Locale.FRENCH));
     }
 
@@ -52,7 +54,7 @@ public class TimeStampedCacheExceptionTest {
         Assert.assertEquals(1, e.getParts().length);
         Assert.assertEquals(0, ((AbsoluteDate) e.getParts()[0]).durationFrom(AbsoluteDate.MODIFIED_JULIAN_EPOCH), 1.0e-10);
         Assert.assertEquals(e.getMessage(Locale.getDefault()), e.getLocalizedMessage());
-        Assert.assertEquals("impossible de générer des données avant le 1858-11-16T23:59:27.816, données requises pour {1}",
+        Assert.assertEquals("impossible de générer des données avant le 1858-11-16T23:59:27.816Z, données requises pour {1} qui est {2} s avant",
                             e.getMessage(Locale.FRENCH));
     }
 
diff --git a/src/test/java/org/orekit/estimation/measurements/gnss/MeasurementCombinationFactoryTest.java b/src/test/java/org/orekit/estimation/measurements/gnss/MeasurementCombinationFactoryTest.java
index 0b676c0837a23903ed5ff446479273bcbbfd99f7..fa4b31c7789b3c3df9f67cb3ab489ecdb7a7ebc6 100644
--- a/src/test/java/org/orekit/estimation/measurements/gnss/MeasurementCombinationFactoryTest.java
+++ b/src/test/java/org/orekit/estimation/measurements/gnss/MeasurementCombinationFactoryTest.java
@@ -382,7 +382,7 @@ public class MeasurementCombinationFactoryTest {
         // Verify receiver clock
         Assert.assertEquals(0.0, combinedDataSet.getRcvrClkOffset(), eps);
         // Verify date
-        Assert.assertEquals("2016-02-13T00:49:43.000", combinedDataSet.getDate().toString());
+        Assert.assertEquals("2016-02-13T00:49:43.000Z", combinedDataSet.getDate().toString());
     }
 
     private RinexObservationLoader load(final String name) {
diff --git a/src/test/java/org/orekit/forces/drag/TimeSpanDragForceTest.java b/src/test/java/org/orekit/forces/drag/TimeSpanDragForceTest.java
index eb485ec70cc178bed0393a28e4f86bd440066b98..bf167bfa6676c19ca6d89be2394a733736009f1c 100644
--- a/src/test/java/org/orekit/forces/drag/TimeSpanDragForceTest.java
+++ b/src/test/java/org/orekit/forces/drag/TimeSpanDragForceTest.java
@@ -65,6 +65,7 @@ import org.orekit.time.AbsoluteDate;
 import org.orekit.time.DateComponents;
 import org.orekit.time.FieldAbsoluteDate;
 import org.orekit.time.TimeComponents;
+import org.orekit.time.TimeScale;
 import org.orekit.time.TimeScalesFactory;
 import org.orekit.utils.Constants;
 import org.orekit.utils.FieldPVCoordinates;
@@ -76,6 +77,8 @@ import org.orekit.utils.TimeSpanMap;
 public class TimeSpanDragForceTest extends AbstractLegacyForceModelTest {
 
     private static final AttitudeProvider DEFAULT_LAW = Utils.defaultLaw();
+    /** UTC time scale. */
+    private TimeScale utc;
 
     /** Compute acceleration derivatives around input position at input date.
      *  Using finite differences in position.
@@ -297,12 +300,12 @@ public class TimeSpanDragForceTest extends AbstractLegacyForceModelTest {
         drivers = forceModel.getParametersDrivers();
         Assert.assertEquals(3,  drivers.size());
         Assert.assertEquals(dragCd2,  drivers.get(0).getValue(), 0.);
-        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_BEFORE + date.shiftedBy(-dt).toString(),
+        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_BEFORE + date.shiftedBy(-dt).toString(utc),
                             drivers.get(0).getName());
         Assert.assertEquals(dragCd0,  drivers.get(1).getValue(), 0.);
         Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT,  drivers.get(1).getName());
         Assert.assertEquals(dragCd0,  drivers.get(1).getValue(), 0.);
-        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_AFTER + date.shiftedBy(+dt).toString(),
+        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_AFTER + date.shiftedBy(+dt).toString(utc),
                             drivers.get(2).getName());
         
         // Check that proper models are returned at significant test dates
@@ -616,14 +619,14 @@ public class TimeSpanDragForceTest extends AbstractLegacyForceModelTest {
         drivers = forceModel.getParametersDrivers();
         Assert.assertEquals(3,  drivers.size());
         Assert.assertEquals(dragCd2,  drivers.get(0).getValue(), 0.);
-        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_BEFORE + date.shiftedBy(-dt).toString(),
+        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_BEFORE + date.shiftedBy(-dt).toString(utc),
                             drivers.get(0).getName());
         
         Assert.assertEquals(dragCd0,  drivers.get(1).getValue(), 0.);
         Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT,  drivers.get(1).getName());
         
         Assert.assertEquals(dragCd1,  drivers.get(2).getValue(), 0.);
-        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_AFTER + date.shiftedBy(+dt).toString(),
+        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_AFTER + date.shiftedBy(+dt).toString(utc),
                             drivers.get(2).getName());
         
         // Check the models at dates
@@ -722,10 +725,10 @@ public class TimeSpanDragForceTest extends AbstractLegacyForceModelTest {
         drivers = forceModel.getParametersDrivers();
         Assert.assertEquals(6,  drivers.size());
         Assert.assertEquals(dragCd2,  drivers.get(0).getValue(), 0.);
-        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_BEFORE + date.shiftedBy(-dt).toString(),
+        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_BEFORE + date.shiftedBy(-dt).toString(utc),
                             drivers.get(0).getName());
         Assert.assertEquals(dragCl2,  drivers.get(1).getValue(), 0.);
-        Assert.assertEquals(DragSensitive.LIFT_RATIO + TimeSpanDragForce.DATE_BEFORE + date.shiftedBy(-dt).toString(),
+        Assert.assertEquals(DragSensitive.LIFT_RATIO + TimeSpanDragForce.DATE_BEFORE + date.shiftedBy(-dt).toString(utc),
                             drivers.get(1).getName());
         
         Assert.assertEquals(dragCd0,  drivers.get(2).getValue(), 0.);
@@ -734,10 +737,10 @@ public class TimeSpanDragForceTest extends AbstractLegacyForceModelTest {
         Assert.assertEquals(DragSensitive.LIFT_RATIO,  drivers.get(3).getName());
         
         Assert.assertEquals(dragCd1,  drivers.get(4).getValue(), 0.);
-        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_AFTER + date.shiftedBy(+dt).toString(),
+        Assert.assertEquals(DragSensitive.DRAG_COEFFICIENT + TimeSpanDragForce.DATE_AFTER + date.shiftedBy(+dt).toString(utc),
                             drivers.get(4).getName());
         Assert.assertEquals(dragCl1,  drivers.get(5).getValue(), 0.);
-        Assert.assertEquals(DragSensitive.LIFT_RATIO + TimeSpanDragForce.DATE_AFTER + date.shiftedBy(+dt).toString(),
+        Assert.assertEquals(DragSensitive.LIFT_RATIO + TimeSpanDragForce.DATE_AFTER + date.shiftedBy(+dt).toString(utc),
                             drivers.get(5).getName());
         
         // Check the models at dates
@@ -831,7 +834,7 @@ public class TimeSpanDragForceTest extends AbstractLegacyForceModelTest {
         forceModel.addDragSensitiveValidBefore(box3, date3);
         
         // Name of Cl3 is kept as default for the test
-        final String nameCl3 = DragSensitive.LIFT_RATIO + TimeSpanDragForce.DATE_BEFORE + date3;
+        final String nameCl3 = DragSensitive.LIFT_RATIO + TimeSpanDragForce.DATE_BEFORE + date3.toString(utc);
         
 
         Assert.assertFalse(forceModel.dependsOnPositionOnly());
@@ -919,7 +922,7 @@ public class TimeSpanDragForceTest extends AbstractLegacyForceModelTest {
         forceModel.addDragSensitiveValidBefore(box3, date3);
         
         // Name of Cl3 is kept as default for the test
-        final String nameCl3 = DragSensitive.LIFT_RATIO + TimeSpanDragForce.DATE_BEFORE + date3;
+        final String nameCl3 = DragSensitive.LIFT_RATIO + TimeSpanDragForce.DATE_BEFORE + date3.toString(utc);
         
 
         Assert.assertFalse(forceModel.dependsOnPositionOnly());
@@ -1607,6 +1610,7 @@ public class TimeSpanDragForceTest extends AbstractLegacyForceModelTest {
     @Before
     public void setUp() {
         Utils.setDataRoot("regular-data");
+        utc = TimeScalesFactory.getUTC();
     }
 }
 
diff --git a/src/test/java/org/orekit/frames/EOPHistoryTest.java b/src/test/java/org/orekit/frames/EOPHistoryTest.java
index bdf5f417e321ad434944a19c9568f80b4bbce223..8d8cc0e659aea9e6554523df248045abb51c8293 100644
--- a/src/test/java/org/orekit/frames/EOPHistoryTest.java
+++ b/src/test/java/org/orekit/frames/EOPHistoryTest.java
@@ -89,7 +89,7 @@ public class EOPHistoryTest {
             FramesFactory.getEOPHistory(IERSConventions.IERS_2010, true).getUT1MinusUTC(date);
             Assert.fail("an exception should have been thrown");
         } catch (OrekitException oe) {
-            Assert.assertEquals(OrekitMessages.MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES,
+            Assert.assertEquals(OrekitMessages.MISSING_EARTH_ORIENTATION_PARAMETERS_BETWEEN_DATES_GAP,
                                 oe.getSpecifier());
         }
     }
diff --git a/src/test/java/org/orekit/models/earth/atmosphere/data/CssiSpaceWeatherLoaderTest.java b/src/test/java/org/orekit/models/earth/atmosphere/data/CssiSpaceWeatherLoaderTest.java
index 69d630652ede82c7efb4d0b8eb5726c34ab274d4..0d0c92a003388b9f8cd06c9153a4dc36d2f79a39 100644
--- a/src/test/java/org/orekit/models/earth/atmosphere/data/CssiSpaceWeatherLoaderTest.java
+++ b/src/test/java/org/orekit/models/earth/atmosphere/data/CssiSpaceWeatherLoaderTest.java
@@ -118,7 +118,7 @@ public class CssiSpaceWeatherLoaderTest {
             cswl.getAp(date);
             Assert.fail("an exception should have been thrown");
         } catch (OrekitException oe) {
-            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, oe.getSpecifier());
+            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE, oe.getSpecifier());
         }
     }
 
@@ -135,7 +135,7 @@ public class CssiSpaceWeatherLoaderTest {
             cswl.getAp(date);
             Assert.fail("an exception should have been thrown");
         } catch (OrekitException oe) {
-            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, oe.getSpecifier());
+            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE, oe.getSpecifier());
         }
     }
 
@@ -152,7 +152,7 @@ public class CssiSpaceWeatherLoaderTest {
             cswl.getAp(date);
             Assert.fail("an exception should have been thrown");
         } catch (OrekitException oe) {
-            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, oe.getSpecifier());
+            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE, oe.getSpecifier());
         }
     }
 
diff --git a/src/test/java/org/orekit/propagation/events/EventDetectorTest.java b/src/test/java/org/orekit/propagation/events/EventDetectorTest.java
index 132184046f4d813d52e25711203e76de4c659b97..e39d465cc6b8fb0c32f3b9f99778af6ad6d75b14 100644
--- a/src/test/java/org/orekit/propagation/events/EventDetectorTest.java
+++ b/src/test/java/org/orekit/propagation/events/EventDetectorTest.java
@@ -305,9 +305,9 @@ public class EventDetectorTest {
         } catch (OrekitException oe) {
             Assert.assertSame(OrekitException.class, oe.getClass());
             Assert.assertSame(dummyCause, oe.getCause().getCause());
-            String expected = "failed to find root between 2011-05-11T00:00:00.000 " +
-                    "(g=-3.6E3) and 2012-05-10T06:00:00.000 (g=3.1554E7)\n" +
-                    "Last iteration at 2011-05-11T00:00:00.000 (g=-3.6E3)";
+            String expected = "failed to find root between 2011-05-11T00:00:00.000Z " +
+                    "(g=-3.6E3) and 2012-05-10T06:00:00.000Z (g=3.1554E7)\n" +
+                    "Last iteration at 2011-05-11T00:00:00.000Z (g=-3.6E3)";
             MatcherAssert.assertThat(oe.getMessage(Locale.US),
                     CoreMatchers.containsString(expected));
         }
diff --git a/src/test/java/org/orekit/propagation/events/FieldEventDetectorTest.java b/src/test/java/org/orekit/propagation/events/FieldEventDetectorTest.java
index c13bf3c454e0c88625be1d39b4c9208ea1833429..555b6a9e793f5313c43bbff10ad4573eb1d6719d 100644
--- a/src/test/java/org/orekit/propagation/events/FieldEventDetectorTest.java
+++ b/src/test/java/org/orekit/propagation/events/FieldEventDetectorTest.java
@@ -375,9 +375,9 @@ public class FieldEventDetectorTest {
         } catch (OrekitException oe) {
             Assert.assertSame(OrekitException.class, oe.getClass());
             Assert.assertSame(dummyCause, oe.getCause().getCause());
-            String expected = "failed to find root between 2011-05-11T00:00:00.000 " +
-                    "(g=-3.6E3) and 2012-05-10T06:00:00.000 (g=3.1554E7)\n" +
-                    "Last iteration at 2011-05-11T01:00:00.000 (g=-3.6E3)";
+            String expected = "failed to find root between 2011-05-11T00:00:00.000Z " +
+                    "(g=-3.6E3) and 2012-05-10T06:00:00.000Z (g=3.1554E7)\n" +
+                    "Last iteration at 2011-05-11T01:00:00.000Z (g=-3.6E3)";
             MatcherAssert.assertThat(oe.getMessage(Locale.US),
                     CoreMatchers.containsString(expected));
         }
diff --git a/src/test/java/org/orekit/propagation/numerical/FieldNumericalPropagatorTest.java b/src/test/java/org/orekit/propagation/numerical/FieldNumericalPropagatorTest.java
index 9eb76b7fe1a3cb9cacebf3e70388deae036ff9fb..6e16200718df31eabbf74123c7fcea6a6d1393e8 100644
--- a/src/test/java/org/orekit/propagation/numerical/FieldNumericalPropagatorTest.java
+++ b/src/test/java/org/orekit/propagation/numerical/FieldNumericalPropagatorTest.java
@@ -1162,13 +1162,13 @@ public class FieldNumericalPropagatorTest {
             ephemeris1.propagate(ephemeris1.getMinDate().shiftedBy(-10.0));
             Assert.fail("an exception should have been thrown");
         } catch (OrekitException pe) {
-            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, pe.getSpecifier());
+            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE, pe.getSpecifier());
         }
         try {
             ephemeris1.propagate(ephemeris1.getMaxDate().shiftedBy(+10.0));
             Assert.fail("an exception should have been thrown");
         } catch (OrekitException pe) {
-            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, pe.getSpecifier());
+            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER, pe.getSpecifier());
         }
 
         double shift = -60;
diff --git a/src/test/java/org/orekit/propagation/numerical/NumericalPropagatorTest.java b/src/test/java/org/orekit/propagation/numerical/NumericalPropagatorTest.java
index 95fbd4b4fe5e711fef1dfab4e782802dcd030836..35bcca03f93e871dbb0f0a534a177e43af9ccb33 100644
--- a/src/test/java/org/orekit/propagation/numerical/NumericalPropagatorTest.java
+++ b/src/test/java/org/orekit/propagation/numerical/NumericalPropagatorTest.java
@@ -906,13 +906,13 @@ public class NumericalPropagatorTest {
             ephemeris1.propagate(ephemeris1.getMinDate().shiftedBy(-10.0));
             Assert.fail("an exception should have been thrown");
         } catch (OrekitException pe) {
-            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, pe.getSpecifier());
+            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_BEFORE, pe.getSpecifier());
         }
         try {
             ephemeris1.propagate(ephemeris1.getMaxDate().shiftedBy(+10.0));
             Assert.fail("an exception should have been thrown");
         } catch (OrekitException pe) {
-            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE, pe.getSpecifier());
+            Assert.assertEquals(OrekitMessages.OUT_OF_RANGE_EPHEMERIDES_DATE_AFTER, pe.getSpecifier());
         }
 
         double shift = -60;
diff --git a/src/test/java/org/orekit/time/AbsoluteDateTest.java b/src/test/java/org/orekit/time/AbsoluteDateTest.java
index dc34462fa5acf39e352060021deb7c4247f2c3d3..e7494837e85461d08b8db35889a16ff671af49d5 100644
--- a/src/test/java/org/orekit/time/AbsoluteDateTest.java
+++ b/src/test/java/org/orekit/time/AbsoluteDateTest.java
@@ -38,6 +38,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.orekit.OrekitMatchers;
 import org.orekit.Utils;
+import org.orekit.data.DataContext;
 import org.orekit.errors.OrekitException;
 import org.orekit.errors.OrekitIllegalArgumentException;
 import org.orekit.errors.OrekitMessages;
@@ -181,12 +182,13 @@ public class AbsoluteDateTest {
     public void testTimeZoneDisplay() {
         final TimeScale utc = TimeScalesFactory.getUTC();
         final AbsoluteDate date = new AbsoluteDate("2000-01-01T01:01:01.000", utc);
-        Assert.assertEquals("2000-01-01T01:01:01.000",       date.toString());
+        Assert.assertEquals("2000-01-01T01:01:01.000Z",      date.toString());
         Assert.assertEquals("2000-01-01T11:01:01.000+10:00", date.toString( 600));
         Assert.assertEquals("1999-12-31T23:01:01.000-02:00", date.toString(-120));
+        Assert.assertEquals("2000-01-01T01:01:01.000+00:00", date.toString(0));
 
         // winter time, Europe is one hour ahead of UTC
-        final TimeZone tz = TimeZone.getTimeZone("Europe/Paris");
+        TimeZone tz = TimeZone.getTimeZone("Europe/Paris");
         Assert.assertEquals("2001-01-22T11:30:00.000+01:00",
                             new AbsoluteDate("2001-01-22T10:30:00", utc).toString(tz));
 
@@ -194,6 +196,11 @@ public class AbsoluteDateTest {
         Assert.assertEquals("2001-06-23T11:30:00.000+02:00",
                             new AbsoluteDate("2001-06-23T09:30:00", utc).toString(tz));
 
+        // check with UTC
+        tz = TimeZone.getTimeZone("UTC");
+        Assert.assertEquals("2001-06-23T09:30:00.000+00:00",
+                new AbsoluteDate("2001-06-23T09:30:00", utc).toString(tz));
+
     }
 
     @Test
@@ -287,13 +294,13 @@ public class AbsoluteDateTest {
         AbsoluteDate date = new AbsoluteDate(new DateComponents(2002, 01, 01),
                                              new TimeComponents(00, 00, 01),
                                              utc);
-        Assert.assertEquals("2002-01-01T00:00:01.000", date.toString());
+        Assert.assertEquals("2002-01-01T00:00:01.000Z", date.toString());
     }
 
     @Test
     public void test1970() {
         AbsoluteDate date = new AbsoluteDate(new Date(0l), utc);
-        Assert.assertEquals("1970-01-01T00:00:00.000", date.toString());
+        Assert.assertEquals("1970-01-01T00:00:00.000Z", date.toString());
     }
 
     @Test
@@ -650,8 +657,8 @@ public class AbsoluteDateTest {
         Assert.assertTrue(Double.isInfinite(AbsoluteDate.PAST_INFINITY.durationFrom(AbsoluteDate.J2000_EPOCH)));
         Assert.assertTrue(Double.isNaN(AbsoluteDate.FUTURE_INFINITY.durationFrom(AbsoluteDate.FUTURE_INFINITY)));
         Assert.assertTrue(Double.isNaN(AbsoluteDate.PAST_INFINITY.durationFrom(AbsoluteDate.PAST_INFINITY)));
-        Assert.assertEquals("5881610-07-11T23:59:59.999",  AbsoluteDate.FUTURE_INFINITY.toString());
-        Assert.assertEquals("-5877490-03-03T00:00:00.000", AbsoluteDate.PAST_INFINITY.toString());
+        Assert.assertEquals("5881610-07-11T23:59:59.999Z",  AbsoluteDate.FUTURE_INFINITY.toString());
+        Assert.assertEquals("-5877490-03-03T00:00:00.000Z", AbsoluteDate.PAST_INFINITY.toString());
         Assert.assertEquals(true, AbsoluteDate.FUTURE_INFINITY.equals(AbsoluteDate.FUTURE_INFINITY));
         Assert.assertEquals(true, AbsoluteDate.PAST_INFINITY.equals(AbsoluteDate.PAST_INFINITY));
         Assert.assertEquals(false, AbsoluteDate.PAST_INFINITY.equals(AbsoluteDate.FUTURE_INFINITY));
@@ -881,16 +888,17 @@ public class AbsoluteDateTest {
         Assert.assertEquals(   7, dtc.getTime().getHour());
         Assert.assertEquals(  54, dtc.getTime().getMinute());
         Assert.assertEquals(60 - 9.094947e-13, dtc.getTime().getSecond(), 1.0e-15);
-        Assert.assertEquals("2015-09-30T07:55:00.000",
+        Assert.assertEquals("2015-09-30T07:54:59.99999999999909",
                             date.toString(utc));
         AbsoluteDate beforeMidnight = new AbsoluteDate(2008, 2, 29, 23, 59, 59.9994, utc);
         AbsoluteDate stillBeforeMidnight = beforeMidnight.shiftedBy(2.0e-4);
         Assert.assertEquals(59.9994, beforeMidnight.getComponents(utc).getTime().getSecond(), 1.0e-15);
         Assert.assertEquals(59.9996, stillBeforeMidnight.getComponents(utc).getTime().getSecond(), 1.0e-15);
-        Assert.assertEquals("2008-02-29T23:59:59.999", beforeMidnight.toString(utc));
-        Assert.assertEquals("2008-03-01T00:00:00.000", stillBeforeMidnight.toString(utc));
+        Assert.assertEquals("2008-02-29T23:59:59.9994", beforeMidnight.toString(utc));
+        Assert.assertEquals("2008-02-29T23:59:59.9996", stillBeforeMidnight.toString(utc));
     }
 
+
     @Test
     public void testLastLeapOutput() {
         UTCScale utc = TimeScalesFactory.getUTC();
@@ -910,8 +918,8 @@ public class AbsoluteDateTest {
         Assert.assertEquals(  23,        t.getComponents(utc).getTime().getHour());
         Assert.assertEquals(  59,        t.getComponents(utc).getTime().getMinute());
         Assert.assertEquals(  59.999999, t.getComponents(utc).getTime().getSecond(), 1.0e-6);
-        Assert.assertEquals("2015-06-30T23:59:60.000", t.toString(utc));
-        Assert.assertEquals("2015-07-01T02:59:60.000", t.toString(TimeScalesFactory.getGLONASS()));
+        Assert.assertEquals("2015-06-30T23:59:59.999999", t.toString(utc));
+        Assert.assertEquals("2015-07-01T02:59:59.999999", t.toString(TimeScalesFactory.getGLONASS()));
     }
 
     @Test
@@ -1193,22 +1201,22 @@ public class AbsoluteDateTest {
         checkToString(date, "2009-01-01T00:00:00.000");
         checkToString(date.shiftedBy(1), "2009-01-01T00:00:01.000");
         // test digits and rounding
-        checkToString(date.shiftedBy(12.3456789123456789), "2009-01-01T00:00:12.346");
-        checkToString(date.shiftedBy(0.0123456789123456789), "2009-01-01T00:00:00.012");
+        checkToString(date.shiftedBy(12.3456789123456789), "2009-01-01T00:00:12.34567891234568");
+        checkToString(date.shiftedBy(0.0123456789123456789), "2009-01-01T00:00:00.01234567891235");
         // test min and max values
         checkToString(date.shiftedBy(zeroUlp), "2009-01-01T00:00:00.000");
         // Orekit 10.1 rounds up
-        checkToString(date.shiftedBy(59.0).shiftedBy(one), "2009-01-01T00:01:00.000");
+        checkToString(date.shiftedBy(59.0).shiftedBy(one), "2009-01-01T00:00:59.99999999999999");
         // Orekit 10.1 rounds up
-        checkToString(date.shiftedBy(86399).shiftedBy(one), "2009-01-02T00:00:00.000");
+        checkToString(date.shiftedBy(86399).shiftedBy(one), "2009-01-01T23:59:59.99999999999999");
         checkToString(date.shiftedBy(oneUlp), "2009-01-01T00:00:00.000");
         checkToString(date.shiftedBy(one), "2009-01-01T00:00:01.000");
         checkToString(date.shiftedBy(-zeroUlp), "2009-01-01T00:00:00.000");
         // test leap
         // Orekit 10.1 throw OIAE, 10.2 rounds up
-        checkToString(date.shiftedBy(-oneUlp), "2009-01-01T00:00:00.000");
+        checkToString(date.shiftedBy(-oneUlp), "2008-12-31T23:59:60.99999999999999");
         // Orekit 10.1 rounds up
-        checkToString(date.shiftedBy(-1).shiftedBy(one), "2009-01-01T00:00:00.000");
+        checkToString(date.shiftedBy(-1).shiftedBy(one), "2008-12-31T23:59:60.99999999999999");
         checkToString(date.shiftedBy(-0.5), "2008-12-31T23:59:60.500");
         checkToString(date.shiftedBy(-1).shiftedBy(zeroUlp), "2008-12-31T23:59:60.000");
         checkToString(date.shiftedBy(-1), "2008-12-31T23:59:60.000");
@@ -1216,14 +1224,14 @@ public class AbsoluteDateTest {
         checkToString(date.shiftedBy(-1).shiftedBy(-oneUlp), "2008-12-31T23:59:60.000");
         checkToString(date.shiftedBy(-2), "2008-12-31T23:59:59.000");
         // Orekit 10.1 rounds up
-        checkToString(date.shiftedBy(-1).shiftedBy(-sixtyUlp), "2008-12-31T23:59:60.000");
+        checkToString(date.shiftedBy(-1).shiftedBy(-sixtyUlp), "2008-12-31T23:59:59.99999999999999");
         checkToString(date.shiftedBy(-61).shiftedBy(zeroUlp), "2008-12-31T23:59:00.000");
         checkToString(date.shiftedBy(-61).shiftedBy(oneUlp), "2008-12-31T23:59:00.000");
         // test UTC weirdness
         // These have more error because of additional multiplications and additions
         // up to 2 ULPs or ulp(60.0) of error.
         // toStringRFC3339 only has 14 digits of precision after the decimal point
-        final DecimalFormat format = new DecimalFormat("00.000", new DecimalFormatSymbols(Locale.US));
+        final DecimalFormat format = new DecimalFormat("00.##############", new DecimalFormatSymbols(Locale.US));
         AbsoluteDate d = new AbsoluteDate(1966, 1, 1, utc);
         double ratePost = 0.0025920 / Constants.JULIAN_DAY;
         double factorPost = ratePost / (1 + ratePost);
@@ -1234,9 +1242,9 @@ public class AbsoluteDateTest {
         checkToString(d.shiftedBy(oneUlp), "1966-01-01T00:00:00.000"); //, oneUlp, 0.5, 0, 0);
         checkToString(d.shiftedBy(one), "1966-01-01T00:00:" + format.format( one * (1 - factorPost))); //, 0.5, 2, 0);
         // Orekit 10.1 rounds up
-        checkToString(d.shiftedBy(59).shiftedBy(one), "1966-01-01T00:01:00.000"); // + format.format( sixty * (1 - factorPost)) + "Z"); //, 1, 1, 0);
+        checkToString(d.shiftedBy(59).shiftedBy(one), "1966-01-01T00:00:" + format.format( 60 * (1 - factorPost))); //  + "Z"); //, 1, 1, 0);
         // one ulp of error
-        checkToString(d.shiftedBy(86399).shiftedBy(one), "1966-01-01T23:59:59.997"); // + format.format( sixty - 86400 * factorPost) + "Z"); //, 1, 1, 0);
+        checkToString(d.shiftedBy(86399).shiftedBy(one), "1966-01-01T23:59:" + format.format( 60 - 86400 * factorPost)); //  + "Z"); //, 1, 1, 0);
         checkToString(d.shiftedBy(-zeroUlp), "1966-01-01T00:00:00.000"); // , 0.5, 0, 0);
         // actual leap is small ~1e-16, but during a leap rounding up to 60.0 is ok
         checkToString(d.shiftedBy(-oneUlp), "1965-12-31T23:59:60.000"); // , 1, 0, 0);
@@ -1244,7 +1252,7 @@ public class AbsoluteDateTest {
         checkToString(d.shiftedBy(-1).shiftedBy(-zeroUlp), "1965-12-31T23:59:" + format.format( 59 + factorPre) ); //, 0.5, 0, 0);
         checkToString(d.shiftedBy(-1).shiftedBy(-oneUlp), "1965-12-31T23:59:" + format.format( 59 + factorPre) ); //, 0.5, 0, 0);
         // one ulp of error
-        checkToString(d.shiftedBy(-1).shiftedBy(-sixtyUlp), "1965-12-31T23:59:59.000"); // + format.format( 59 + (1 + sixtyUlp) * factorPre) + "Z"); //, 0.5, 1, 0);
+        checkToString(d.shiftedBy(-1).shiftedBy(-sixtyUlp), "1965-12-31T23:59:59.00000001499999"); // + format.format(59 + factorPre)+ "Z"); //, 0.5, 1, 0);
         // since second ~= 0 there is significant cancellation
         checkToString(d.shiftedBy(-60).shiftedBy(zeroUlp), "1965-12-31T23:59:" + format.format( 60 * factorPre) ); //, 0, 0, sixtyUlp);
         checkToString(d.shiftedBy(-60).shiftedBy(oneUlp), "1965-12-31T23:59:" + format.format( (oneUlp - oneUlp * factorPre) + 60 * factorPre) ); //, 0.5, 0, sixtyUlp);
@@ -1280,13 +1288,38 @@ public class AbsoluteDateTest {
     }
 
     private void checkToString(final AbsoluteDate d, final String s) {
-        MatcherAssert.assertThat(d.toString(), CoreMatchers.is(s));
-        // there is no way for the second form here to know whether it is in a leap second
-        // or not so it makes poor choices regarding rounding during a leap second.
-        // Only check it when not during a leap second.
-        if (s.charAt(s.length() - 6) != '6') {
-            MatcherAssert.assertThat(d.getComponents(utc).toString(), CoreMatchers.is(s));
+        MatcherAssert.assertThat(d.toString(), CoreMatchers.is(s + "Z"));
+        MatcherAssert.assertThat(d.getComponents(utc).toString(), CoreMatchers.is(s + "+00:00"));
+    }
+
+    /**
+     * Check {@link AbsoluteDate#toString()} when UTC throws an exception. This ~is~ was
+     * the most common issue new and old users face.
+     */
+    @Test
+    public void testToStringException() {
+        Utils.setDataRoot("no-data");
+        try {
+            DataContext.getDefault().getTimeScales().getUTC();
+            Assert.fail("Expected Exception");
+        } catch (OrekitException e) {
+            // expected
+            Assert.assertEquals(e.getSpecifier(), OrekitMessages.NO_IERS_UTC_TAI_HISTORY_DATA_LOADED);
         }
+        // try some unusual values
+        MatcherAssert.assertThat(present.toString(), CoreMatchers.is("2000-01-01T12:00:32.000 TAI"));
+        MatcherAssert.assertThat(present.shiftedBy(Double.POSITIVE_INFINITY).toString(),
+                CoreMatchers.is("5881610-07-11T23:59:59.999 TAI"));
+        MatcherAssert.assertThat(present.shiftedBy(Double.NEGATIVE_INFINITY).toString(),
+                CoreMatchers.is("-5877490-03-03T00:00:00.000 TAI"));
+        String nan = "1.8".equals(System.getProperty("java.specification.version")) ? "\uFFFD" : "NaN";
+        MatcherAssert.assertThat(present.shiftedBy(Double.NaN).toString(),
+                CoreMatchers.is("2000-01-01T12:00:" + nan + " TAI"));
+        // infinity is special cased, but I can make AbsoluteDate.offset larger than
+        // Long.MAX_VALUE see #584
+        AbsoluteDate d = present.shiftedBy(1e300).shiftedBy(1e300).shiftedBy(1e300);
+        MatcherAssert.assertThat(d.toString(),
+                CoreMatchers.is("(-9223372036854775779 + 3.0E300) seconds past epoch"));
     }
 
     @Before
diff --git a/src/test/java/org/orekit/time/DateTimeComponentsTest.java b/src/test/java/org/orekit/time/DateTimeComponentsTest.java
index c6f932e0660c117f546fe393b653187c2f3fc118..37365f0aca790a7822b79b96f4a3a5a0716677fc 100644
--- a/src/test/java/org/orekit/time/DateTimeComponentsTest.java
+++ b/src/test/java/org/orekit/time/DateTimeComponentsTest.java
@@ -73,7 +73,7 @@ public class DateTimeComponentsTest {
     public void testString() {
         final DateTimeComponents date =
             new DateTimeComponents(DateComponents.J2000_EPOCH, TimeComponents.H12);
-        Assert.assertEquals("2000-01-01T12:00:00.000", date.toString());
+        Assert.assertEquals("2000-01-01T12:00:00.000+00:00", date.toString());
     }
 
     @Test
@@ -87,6 +87,8 @@ public class DateTimeComponentsTest {
     @Test
     public void testParse() {
         String s = "2000-01-02T03:04:05.000";
+        Assert.assertEquals(s, DateTimeComponents.parseDateTime(s).toStringWithoutUtcOffset());
+        s = "2000-01-02T03:04:05.000+00:00";
         Assert.assertEquals(s, DateTimeComponents.parseDateTime(s).toString());
     }
 
@@ -151,4 +153,46 @@ public class DateTimeComponentsTest {
         MatcherAssert.assertThat(actual.toStringRfc3339(), CoreMatchers.is(expected));
     }
 
+    @Test
+    public void testToStringRounding() {
+        // these tests were copied from AbsoluteDateTest
+        check(2015, 9, 30, 7, 54, 60 - 9.094947e-13, 60,
+                "2015-09-30T07:54:59.99999999999909+00:00",
+                "2015-09-30T07:55:00.000+00:00",
+                "2015-09-30T07:55:00+00:00");
+        check(2008, 2, 29, 23, 59, 59.9994, 60,
+                "2008-02-29T23:59:59.99940000000000+00:00",
+                "2008-02-29T23:59:59.999+00:00",
+                "2008-03-01T00:00:00+00:00");
+        check(2008, 2, 29, 23, 59, 59.9996, 60,
+                "2008-02-29T23:59:59.99960000000000+00:00",
+                "2008-03-01T00:00:00.000+00:00",
+                "2008-03-01T00:00:00+00:00");
+        // check a leap second
+        check(2015, 6, 30, 23, 59, 59.999999, 61,
+                "2015-06-30T23:59:59.99999900000000+00:00",
+                "2015-06-30T23:59:60.000+00:00",
+                "2015-06-30T23:59:60+00:00");
+        check(2015, 6, 30, 23, 59, 60.5, 61,
+                "2015-06-30T23:59:60.50000000000000+00:00",
+                "2015-06-30T23:59:60.500+00:00",
+                "2015-07-01T00:00:00+00:00");
+        // check a bigger leap second. First leap was 1.422818 s.
+        // TODO can't run this test because of #707
+        //check(1960, 12, 31, 23, 59, 61.42281, 62,
+        //        "1960-12-31T23:59:61.42281000000000+00:00",
+        //        "1960-12-31T23:59:61.42300000000000+00:00", // TODO this date is invalid
+        //        "1961-01-01T00:00:00+00:00");
+    }
+
+    private void check(int year, int month, int day, int hour, int minute, double second,
+                       int minuteDuration, String full, String medium, String shor) {
+        DateTimeComponents dtc =
+                new DateTimeComponents(year, month, day, hour, minute, second);
+        MatcherAssert.assertThat(dtc.toString(minuteDuration), CoreMatchers.is(medium));
+        MatcherAssert.assertThat(dtc.toString(minuteDuration, 3), CoreMatchers.is(medium));
+        MatcherAssert.assertThat(dtc.toString(minuteDuration, 0), CoreMatchers.is(shor));
+        MatcherAssert.assertThat(dtc.toString(minuteDuration, 14), CoreMatchers.is(full));
+    }
+
 }
diff --git a/src/test/java/org/orekit/time/FieldAbsoluteDateTest.java b/src/test/java/org/orekit/time/FieldAbsoluteDateTest.java
index 2a9405208ccfbf2fa069ed52336121e64a770eca..0f232fbeb906a725579e9512c2b5695e77131e15 100644
--- a/src/test/java/org/orekit/time/FieldAbsoluteDateTest.java
+++ b/src/test/java/org/orekit/time/FieldAbsoluteDateTest.java
@@ -418,7 +418,7 @@ public class FieldAbsoluteDateTest {
     private <T extends CalculusFieldElement<T>> void doTestTimeZoneDisplay(final Field<T> field) {
         final TimeScale utc = TimeScalesFactory.getUTC();
         final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, "2000-01-01T01:01:01.000", utc);
-        Assert.assertEquals("2000-01-01T01:01:01.000",       date.toString());
+        Assert.assertEquals("2000-01-01T01:01:01.000Z",      date.toString());
         Assert.assertEquals("2000-01-01T11:01:01.000+10:00", date.toString( 600));
         Assert.assertEquals("1999-12-31T23:01:01.000-02:00", date.toString(-120));
 
@@ -526,12 +526,12 @@ public class FieldAbsoluteDateTest {
         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new DateComponents(2002, 01, 01),
                                                             new TimeComponents(00, 00, 01),
                                                             utc);
-        Assert.assertEquals("2002-01-01T00:00:01.000", date.toString());
+        Assert.assertEquals("2002-01-01T00:00:01.000Z", date.toString());
     }
 
     private <T extends CalculusFieldElement<T>> void doTest1970(final Field<T> field) {
         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, new Date(0l), utc);
-        Assert.assertEquals("1970-01-01T00:00:00.000", date.toString());
+        Assert.assertEquals("1970-01-01T00:00:00.000Z", date.toString());
     }
 
     private <T extends CalculusFieldElement<T>> void doTestUtcGpsOffset(final Field<T> field) {
@@ -972,8 +972,8 @@ public class FieldAbsoluteDateTest {
         Assert.assertTrue(Double.isInfinite(FieldAbsoluteDate.getFutureInfinity(field).durationFrom(FieldAbsoluteDate.getJ2000Epoch(field)).getReal()));
         Assert.assertTrue(Double.isInfinite(FieldAbsoluteDate.getFutureInfinity(field).durationFrom(FieldAbsoluteDate.getPastInfinity(field)).getReal()));
         Assert.assertTrue(Double.isInfinite(FieldAbsoluteDate.getPastInfinity(field).durationFrom(FieldAbsoluteDate.getJ2000Epoch(field)).getReal()));
-        Assert.assertEquals("5881610-07-11T23:59:59.999",  FieldAbsoluteDate.getFutureInfinity(field).toString());
-        Assert.assertEquals("-5877490-03-03T00:00:00.000", FieldAbsoluteDate.getPastInfinity(field).toString());
+        Assert.assertEquals("5881610-07-11T23:59:59.999Z",  FieldAbsoluteDate.getFutureInfinity(field).toString());
+        Assert.assertEquals("-5877490-03-03T00:00:00.000Z", FieldAbsoluteDate.getPastInfinity(field).toString());
 
         final FieldAbsoluteDate<T> j2000     = FieldAbsoluteDate.getJ2000Epoch(field);
         final FieldAbsoluteDate<T> arbitrary = FieldAbsoluteDate.getArbitraryEpoch(field);
@@ -1094,14 +1094,14 @@ public class FieldAbsoluteDateTest {
         Assert.assertEquals(   7, dtc.getTime().getHour());
         Assert.assertEquals(  54, dtc.getTime().getMinute());
         Assert.assertEquals(60 - 9.094947e-13, dtc.getTime().getSecond(), 1.0e-15);
-        Assert.assertEquals("2015-09-30T07:55:00.000",
+        Assert.assertEquals("2015-09-30T07:54:59.99999999999909",
                             date.toString(utc));
         FieldAbsoluteDate<T> beforeMidnight = new FieldAbsoluteDate<>(field, 2008, 2, 29, 23, 59, 59.9994, utc);
         FieldAbsoluteDate<T> stillBeforeMidnight = beforeMidnight.shiftedBy(2.0e-4);
         Assert.assertEquals(59.9994, beforeMidnight.getComponents(utc).getTime().getSecond(), 1.0e-15);
         Assert.assertEquals(59.9996, stillBeforeMidnight.getComponents(utc).getTime().getSecond(), 1.0e-15);
-        Assert.assertEquals("2008-02-29T23:59:59.999", beforeMidnight.toString(utc));
-        Assert.assertEquals("2008-03-01T00:00:00.000", stillBeforeMidnight.toString(utc));
+        Assert.assertEquals("2008-02-29T23:59:59.9994", beforeMidnight.toString(utc));
+        Assert.assertEquals("2008-02-29T23:59:59.9996", stillBeforeMidnight.toString(utc));
     }
 
     private <T extends CalculusFieldElement<T>> void doTestIssue508(final Field<T> field) {
diff --git a/src/test/java/org/orekit/time/GLONASSScaleTest.java b/src/test/java/org/orekit/time/GLONASSScaleTest.java
index c2bf4898333c5cc08907d166fd87f8f0d8a9ffd0..5260af868a80fb3663b37f604e78a9d8f853ae06 100644
--- a/src/test/java/org/orekit/time/GLONASSScaleTest.java
+++ b/src/test/java/org/orekit/time/GLONASSScaleTest.java
@@ -132,7 +132,8 @@ public class GLONASSScaleTest {
     @Test
     public void testWrapBeforeLeap() {
         AbsoluteDate t = new AbsoluteDate("2015-07-01T02:59:59.999999", glonass);
-        Assert.assertEquals("2015-07-01T02:59:60.000", t.toString(glonass));
+        Assert.assertEquals("2015-07-01T02:59:60.000+00:00",
+                t.getComponents(glonass).toString(glonass.minuteDuration(t)));
     }
 
     @Test
diff --git a/src/test/java/org/orekit/time/TimeComponentsTest.java b/src/test/java/org/orekit/time/TimeComponentsTest.java
index 5baf087ad54ba479189048a34be0c15253cf5cd8..857790297365a8b7c5efccee258a697d602d15d3 100644
--- a/src/test/java/org/orekit/time/TimeComponentsTest.java
+++ b/src/test/java/org/orekit/time/TimeComponentsTest.java
@@ -106,16 +106,23 @@ public class TimeComponentsTest {
 
     @Test
     public void testString() {
-        Assert.assertEquals("00:00:00.000", new TimeComponents(0).toString());
-        Assert.assertEquals("06:00:00.000", new TimeComponents(21600).toString());
-        Assert.assertEquals("12:00:00.000", new TimeComponents(43200).toString());
-        Assert.assertEquals("18:00:00.000", new TimeComponents(64800).toString());
-        Assert.assertEquals("23:59:59.900", new TimeComponents(86399.9).toString());
+        Assert.assertEquals("00:00:00.000+00:00", new TimeComponents(0).toString());
+        Assert.assertEquals("06:00:00.000+00:00", new TimeComponents(21600).toString());
+        Assert.assertEquals("12:00:00.000+00:00", new TimeComponents(43200).toString());
+        Assert.assertEquals("18:00:00.000+00:00", new TimeComponents(64800).toString());
+        Assert.assertEquals("23:59:59.89999999999418+00:00", new TimeComponents(86399.9).toString());
         Assert.assertEquals("00:00:00.000+10:00", new TimeComponents( 0,  0,  0,    600).toString());
         Assert.assertEquals("06:00:00.000+10:00", new TimeComponents( 6,  0,  0,    600).toString());
         Assert.assertEquals("12:00:00.000-04:30", new TimeComponents(12,  0,  0,   -270).toString());
         Assert.assertEquals("18:00:00.000-04:30", new TimeComponents(18,  0,  0,   -270).toString());
         Assert.assertEquals("23:59:59.900-04:30", new TimeComponents(23, 59, 59.9, -270).toString());
+        // test leap seconds
+        Assert.assertEquals("23:59:60.500+00:00", TimeComponents.fromSeconds(86399, 0.5, 1, 61).toString());
+        // leap second on 1961 is between 1 and 2 seconds in duration
+        Assert.assertEquals("23:59:61.32281798015773+00:00", TimeComponents.fromSeconds(86399, 0.32281798015773, 2, 62).toString());
+        // test rounding
+        Assert.assertEquals("23:59:59.99999999998545+00:00", new TimeComponents(86399.99999999999).toString());
+        Assert.assertEquals("23:59:59.99999999999999+00:00", TimeComponents.fromSeconds(86399, FastMath.nextDown(1.0), 0, 60).toString());
     }
 
     @Test
diff --git a/src/test/java/org/orekit/time/UTCScaleTest.java b/src/test/java/org/orekit/time/UTCScaleTest.java
index e0df9ffb1ef4c6823bfd4ba27efb9bd323dda03c..51feea801253c25134eb61c62e756d8eb20a4b64 100644
--- a/src/test/java/org/orekit/time/UTCScaleTest.java
+++ b/src/test/java/org/orekit/time/UTCScaleTest.java
@@ -51,7 +51,7 @@ public class UTCScaleTest {
         AbsoluteDate d1 = new AbsoluteDate(new DateComponents(2020, 12, 31),
                                            new TimeComponents(23, 59, 59),
                                            utc);
-        Assert.assertEquals("2020-12-31T23:59:59.000", d1.toString());
+        Assert.assertEquals("2020-12-31T23:59:59.000Z", d1.toString());
     }
 
     @Test
@@ -130,7 +130,8 @@ public class UTCScaleTest {
     @Test
     public void testWrapBeforeLeap() {
         AbsoluteDate t = new AbsoluteDate("2015-06-30T23:59:59.999999", utc);
-        Assert.assertEquals("2015-06-30T23:59:60.000", t.toString(utc));
+        Assert.assertEquals("2015-06-30T23:59:60.000+00:00",
+                t.getComponents(utc).toString(utc.minuteDuration(t)));
     }
 
     @Test