Merge "Reenable EcdhTest#testModifiedPublic"
diff --git a/luni/src/main/java/libcore/icu/DateIntervalFormat.java b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
index eb6b501..472d99b 100644
--- a/luni/src/main/java/libcore/icu/DateIntervalFormat.java
+++ b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
@@ -61,16 +61,24 @@
endCalendar = DateUtilsBridge.createIcuCalendar(icuTimeZone, icuLocale, endMs);
}
- boolean endsAtMidnight = isMidnight(endCalendar);
-
- // If we're not showing the time or the start and end times are on the same day, and the
- // end time is midnight, fudge the end date so we don't count the day that's about to start.
- // This is not the behavior of icu4j's DateIntervalFormat, but it's the historical behavior
+ // Special handling when the range ends at midnight:
+ // - If we're not showing times, and the range is non-empty, we fudge the end date so we don't
+ // count the day that's about to start.
+ // - If we are showing times, and the range ends at exactly 00:00 of the day following its start
+ // (which can be thought of as 24:00 the same day), we fudge the end date so we don't show the
+ // dates --- unless the start is anything displayed as 00:00, in which case we include both
+ // dates to disambiguate.
+ // This is not the behavior of icu4j's DateIntervalFormat, but it's the required behavior
// of Android's DateUtils.formatDateRange.
- if (startMs != endMs && endsAtMidnight &&
- ((flags & DateUtilsBridge.FORMAT_SHOW_TIME) == 0
- || DateUtilsBridge.dayDistance(startCalendar, endCalendar) <= 1)) {
- endCalendar.add(Calendar.DAY_OF_MONTH, -1);
+ if (isExactlyMidnight(endCalendar)) {
+ boolean showTime =
+ (flags & DateUtilsBridge.FORMAT_SHOW_TIME) == DateUtilsBridge.FORMAT_SHOW_TIME;
+ boolean endsDayAfterStart = DateUtilsBridge.dayDistance(startCalendar, endCalendar) == 1;
+ if ((!showTime && startMs != endMs)
+ || (endsDayAfterStart
+ && !DateUtilsBridge.isDisplayMidnightUsingSkeleton(startCalendar))) {
+ endCalendar.add(Calendar.DAY_OF_MONTH, -1);
+ }
}
String skeleton = DateUtilsBridge.toSkeleton(startCalendar, endCalendar, flags);
@@ -95,11 +103,10 @@
return formatter;
}
- private static boolean isMidnight(Calendar c) {
+ private static boolean isExactlyMidnight(Calendar c) {
return c.get(Calendar.HOUR_OF_DAY) == 0 &&
c.get(Calendar.MINUTE) == 0 &&
c.get(Calendar.SECOND) == 0 &&
c.get(Calendar.MILLISECOND) == 0;
}
-
}
diff --git a/luni/src/main/java/libcore/icu/DateUtilsBridge.java b/luni/src/main/java/libcore/icu/DateUtilsBridge.java
index 6e28874..ac7a036 100644
--- a/luni/src/main/java/libcore/icu/DateUtilsBridge.java
+++ b/luni/src/main/java/libcore/icu/DateUtilsBridge.java
@@ -151,6 +151,16 @@
return c2.get(Calendar.JULIAN_DAY) - c1.get(Calendar.JULIAN_DAY);
}
+ /**
+ * Returns whether the argument will be displayed as if it were midnight, using any of the
+ * skeletons provided by {@link #toSkeleton}.
+ */
+ public static boolean isDisplayMidnightUsingSkeleton(Calendar c) {
+ // All the skeletons returned by toSkeleton have minute precision (they may abbreviate 4:00 PM
+ // to 4 PM but will still show the following minute as 4:01 PM).
+ return c.get(Calendar.HOUR_OF_DAY) == 0 && c.get(Calendar.MINUTE) == 0;
+ }
+
private static boolean onTheHour(Calendar c) {
return c.get(Calendar.MINUTE) == 0 && c.get(Calendar.SECOND) == 0;
}
diff --git a/luni/src/test/java/libcore/libcore/icu/DateIntervalFormatTest.java b/luni/src/test/java/libcore/libcore/icu/DateIntervalFormatTest.java
index 3c6049b..6b33f13 100644
--- a/luni/src/test/java/libcore/libcore/icu/DateIntervalFormatTest.java
+++ b/luni/src/test/java/libcore/libcore/icu/DateIntervalFormatTest.java
@@ -431,4 +431,42 @@
assertEquals("11:00 PM – 12:00 AM", formatDateRange(locale, timeZone,
1430434800000L, 1430438400000L, FORMAT_SHOW_TIME));
}
+
+ // http://b/68847519
+ public void testEndAtMidnight() {
+ ULocale locale = new ULocale("en");
+ TimeZone timeZone = TimeZone.getTimeZone("UTC");
+ int dateTimeFlags = FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_24HOUR;
+ // If we're showing times and the end-point is midnight the following day, we want the
+ // behaviour of suppressing the date for the end...
+ assertEquals("February 27, 04:00 – 00:00",
+ formatDateRange(locale, timeZone, 1519704000000L, 1519776000000L, dateTimeFlags));
+ // ...unless the start-point is also midnight, in which case we need dates to disambiguate.
+ assertEquals("February 27, 00:00 – February 28, 00:00",
+ formatDateRange(locale, timeZone, 1519689600000L, 1519776000000L, dateTimeFlags));
+ // We want to show the date if the end-point is a millisecond after midnight the following
+ // day, or if it is exactly midnight the day after that.
+ assertEquals("February 27, 04:00 – February 28, 00:00",
+ formatDateRange(locale, timeZone, 1519704000000L, 1519776000001L, dateTimeFlags));
+ assertEquals("February 27, 04:00 – March 1, 00:00",
+ formatDateRange(locale, timeZone, 1519704000000L, 1519862400000L, dateTimeFlags));
+ // We want to show the date if the start-point is anything less than a minute after midnight,
+ // since that gets displayed as midnight...
+ assertEquals("February 27, 00:00 – February 28, 00:00",
+ formatDateRange(locale, timeZone, 1519689659999L, 1519776000000L, dateTimeFlags));
+ // ...but not if it is exactly one minute after midnight.
+ assertEquals("February 27, 00:01 – 00:00",
+ formatDateRange(locale, timeZone, 1519689660000L, 1519776000000L, dateTimeFlags));
+ int dateOnlyFlags = FORMAT_SHOW_DATE;
+ // If we're only showing dates and the end-point is midnight of any day, we want the
+ // behaviour of showing an end date one earlier. So if the end-point is March 2, 00:00, show
+ // March 1 instead (whether the start-point is midnight or not).
+ assertEquals("February 27 – March 1",
+ formatDateRange(locale, timeZone, 1519689600000L, 1519948800000L, dateOnlyFlags));
+ assertEquals("February 27 – March 1",
+ formatDateRange(locale, timeZone, 1519704000000L, 1519948800000L, dateOnlyFlags));
+ // We want to show the true date if the end-point is a millisecond after midnight.
+ assertEquals("February 27 – March 2",
+ formatDateRange(locale, timeZone, 1519689600000L, 1519948800001L, dateOnlyFlags));
+ }
}