Commit 01a812a7 authored by Evan Ward's avatar Evan Ward
Browse files

Merge branch 'legacy-to-string' into 'develop'

Fix #880 #881 AbsoluteDate toString with and without UTC offset

Closes #880 and #881

See merge request !227
parents 9d621ecf 969afd98
Pipeline #1651 passed with stages
in 23 minutes and 1 second
......@@ -21,6 +21,14 @@
</properties>
<body>
<release version="11.1" date="TBD" description="TBD">
<action dev="evan" type="add" issue="881">
Add AbsoluteDate.toStringWithoutUtcOffset(TimeScale, int) and
DateTimeComponents.toStringWithoutUtcOffset(int, int) to emulate
AbsoluteDate.toString() from Orekit 10.
</action>
<action dev="evan" type="fix" issue="880">
Fix UTC offset in DateTimeComponents.toString(int, int)
</action>
<action dev="luc" type="fix" issue="849">
Added detector to FieldEventHandler.init arguments list.
</action>
......
......@@ -1455,4 +1455,31 @@ public class AbsoluteDate
return this.getComponents(utc).toStringRfc3339();
}
/**
* Return a string representation of this date-time, rounded to the given precision.
*
* <p>The format used is ISO8601 without the UTC offset.</p>
*
* <p>Calling {@code toStringWithoutUtcOffset(DataContext.getDefault().getTimeScales().getUTC(),
* 3)} will emulate the behavior of {@link #toString()} in Orekit 10 and earlier. Note
* this method is more accurate as it correctly handles rounding during leap seconds.
*
* @param timeScale to use to compute components.
* @param fractionDigits the number of digits to include after the decimal point in
* the string representation of the seconds. The date and time
* is first rounded as necessary. {@code fractionDigits} must be
* greater than or equal to {@code 0}.
* @return string representation of this date, time, and UTC offset
* @see #toString(TimeScale)
* @see #toStringRfc3339(TimeScale)
* @see DateTimeComponents#toString(int, int)
* @see DateTimeComponents#toStringWithoutUtcOffset(int, int)
* @since 11.1
*/
public String toStringWithoutUtcOffset(final TimeScale timeScale,
final int fractionDigits) {
return this.getComponents(timeScale)
.toStringWithoutUtcOffset(timeScale.minuteDuration(this), fractionDigits);
}
}
......@@ -243,6 +243,7 @@ public class DateTimeComponents implements Serializable, Comparable<DateTimeComp
* format used is ISO6801, except without the offset from UTC.
*
* @return a string representation of the date-time.
* @see #toStringWithoutUtcOffset(int, int)
* @see #toString(int, int)
* @see #toStringRfc3339()
*/
......@@ -282,9 +283,34 @@ public class DateTimeComponents implements Serializable, Comparable<DateTimeComp
* @return string representation of this date, time, and UTC offset
* @see #toStringRfc3339()
* @see #toStringWithoutUtcOffset()
* @see #toStringWithoutUtcOffset(int, int)
* @since 11.0
*/
public String toString(final int minuteDuration, final int fractionDigits) {
return toStringWithoutUtcOffset(minuteDuration, fractionDigits) +
time.formatUtcOffset();
}
/**
* Return a string representation of this date-time, rounded to the given precision.
*
* <p>The format used is ISO8601 without 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 and time
* is first rounded as necessary. {@code fractionDigits} must
* be greater than or equal to {@code 0}.
* @return string representation of this date, time, and UTC offset
* @see #toStringRfc3339()
* @see #toStringWithoutUtcOffset()
* @see #toString(int, int)
* @since 11.1
*/
public String toStringWithoutUtcOffset(final int minuteDuration,
final int fractionDigits) {
final DecimalFormat secondsFormat =
new DecimalFormat("00", new DecimalFormatSymbols(Locale.US));
secondsFormat.setMaximumFractionDigits(fractionDigits);
......@@ -312,8 +338,7 @@ public class DateTimeComponents implements Serializable, Comparable<DateTimeComp
roundedTime = new TimeComponents(hour, minute, second);
}
return roundedDate.toString() + 'T' +
roundedTime.toStringWithoutUtcOffset(secondsFormat) +
roundedTime.formatUtcOffset();
roundedTime.toStringWithoutUtcOffset(secondsFormat);
}
/**
......
......@@ -1292,6 +1292,57 @@ public class AbsoluteDateTest {
MatcherAssert.assertThat(d.getComponents(utc).toString(), CoreMatchers.is(s + "+00:00"));
}
@Test
public void testToStringWithoutUtcOffset() {
// setup
AbsoluteDate date = new AbsoluteDate(2009, 1, 1, utc);
double one = FastMath.nextDown(1.0);
double zeroUlp = FastMath.nextUp(0.0);
double oneUlp = FastMath.ulp(1.0);
//double sixty = FastMath.nextDown(60.0);
double sixtyUlp = FastMath.ulp(60.0);
// action
// test midnight
checkToStringNoOffset(date, "2009-01-01T00:00:00.000");
checkToStringNoOffset(date.shiftedBy(1), "2009-01-01T00:00:01.000");
// test digits and rounding
checkToStringNoOffset(date.shiftedBy(12.3456789123456789), "2009-01-01T00:00:12.346");
checkToStringNoOffset(date.shiftedBy(0.0123456789123456789), "2009-01-01T00:00:00.012");
// test min and max values
checkToStringNoOffset(date.shiftedBy(zeroUlp), "2009-01-01T00:00:00.000");
// Orekit 10.1 rounds up
checkToStringNoOffset(date.shiftedBy(59.0).shiftedBy(one), "2009-01-01T00:01:00.000");
// Orekit 10.1 rounds up
checkToStringNoOffset(date.shiftedBy(86399).shiftedBy(one), "2009-01-02T00:00:00.000");
checkToStringNoOffset(date.shiftedBy(oneUlp), "2009-01-01T00:00:00.000");
checkToStringNoOffset(date.shiftedBy(one), "2009-01-01T00:00:01.000");
checkToStringNoOffset(date.shiftedBy(-zeroUlp), "2009-01-01T00:00:00.000");
// test leap
// Orekit 10.1 throw OIAE, 10.2 rounds up
checkToStringNoOffset(date.shiftedBy(-oneUlp), "2009-01-01T00:00:00.000");
// Orekit 10.1 rounds up
checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(one), "2009-01-01T00:00:00.000");
checkToStringNoOffset(date.shiftedBy(-0.5), "2008-12-31T23:59:60.500");
checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(zeroUlp), "2008-12-31T23:59:60.000");
checkToStringNoOffset(date.shiftedBy(-1), "2008-12-31T23:59:60.000");
checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(-zeroUlp), "2008-12-31T23:59:60.000");
checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(-oneUlp), "2008-12-31T23:59:60.000");
checkToStringNoOffset(date.shiftedBy(-2), "2008-12-31T23:59:59.000");
// Orekit 10.1 rounds up
checkToStringNoOffset(date.shiftedBy(-1).shiftedBy(-sixtyUlp), "2008-12-31T23:59:60.000");
checkToStringNoOffset(date.shiftedBy(-61).shiftedBy(zeroUlp), "2008-12-31T23:59:00.000");
checkToStringNoOffset(date.shiftedBy(-61).shiftedBy(oneUlp), "2008-12-31T23:59:00.000");
}
private void checkToStringNoOffset(final AbsoluteDate d, final String s) {
MatcherAssert.assertThat(d.toStringWithoutUtcOffset(utc, 3), CoreMatchers.is(s));
MatcherAssert.assertThat(
d.getComponents(utc).toStringWithoutUtcOffset(utc.minuteDuration(d), 3),
CoreMatchers.is(s));
}
/**
* Check {@link AbsoluteDate#toString()} when UTC throws an exception. This ~is~ was
* the most common issue new and old users face.
......
......@@ -195,4 +195,23 @@ public class DateTimeComponentsTest {
MatcherAssert.assertThat(dtc.toString(minuteDuration, 14), CoreMatchers.is(full));
}
@Test
public void testToStringRoundingUtcOffset() {
DateTimeComponents dtc =
new DateTimeComponents(new DateComponents(2000, 12, 31), new TimeComponents(23, 59, 59.9, -92));
MatcherAssert.assertThat(dtc.toString(60), CoreMatchers.is("2000-12-31T23:59:59.900-01:32"));
MatcherAssert.assertThat(dtc.toString(60, 3), CoreMatchers.is("2000-12-31T23:59:59.900-01:32"));
MatcherAssert.assertThat(dtc.toString(60, 0), CoreMatchers.is("2001-01-01T00:00:00-01:32"));
MatcherAssert.assertThat(dtc.toString(60, 14), CoreMatchers.is("2000-12-31T23:59:59.90000000000000-01:32"));
}
@Test
public void testToStringWithoutUtcOffsetRoundingUtcOffset() {
DateTimeComponents dtc =
new DateTimeComponents(new DateComponents(2000, 12, 31), new TimeComponents(23, 59, 59.9, -92));
MatcherAssert.assertThat(dtc.toStringWithoutUtcOffset(60, 3), CoreMatchers.is("2000-12-31T23:59:59.900"));
MatcherAssert.assertThat(dtc.toStringWithoutUtcOffset(60, 0), CoreMatchers.is("2001-01-01T00:00:00"));
MatcherAssert.assertThat(dtc.toStringWithoutUtcOffset(60, 14), CoreMatchers.is("2000-12-31T23:59:59.90000000000000"));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment