Added a Formatter parameter to DateUtils.formatDateRange

DateUtils.formatDateRange is using String.format which isn't efficient for
formatting large number of strings. I have added the Formatter parameter which
allows the caller to reuse the formatter of subsequent calls for faster
performance.
diff --git a/api/current.xml b/api/current.xml
index eeeab80..c92b018 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -126565,6 +126565,27 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="formatDateRange"
+ return="java.util.Formatter"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="formatter" type="java.util.Formatter">
+</parameter>
+<parameter name="startMillis" type="long">
+</parameter>
+<parameter name="endMillis" type="long">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
 <method name="formatDateTime"
  return="java.lang.String"
  abstract="false"
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 1a4eb699..9dd8ceb 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -25,7 +25,9 @@
 
 import java.util.Calendar;
 import java.util.Date;
+import java.util.Formatter;
 import java.util.GregorianCalendar;
+import java.util.Locale;
 import java.util.TimeZone;
 
 /**
@@ -1040,6 +1042,31 @@
 
     /**
      * Formats a date or a time range according to the local conventions.
+     * <p>
+     * Note that this is a convenience method. Using it involves creating an
+     * internal {@link java.util.Formatter} instance on-the-fly, which is
+     * somewhat costly in terms of memory and time. This is probably acceptable
+     * if you use the method only rarely, but if you rely on it for formatting a
+     * large number of dates, consider creating and reusing your own
+     * {@link java.util.Formatter} instance and use the version of
+     * {@link #formatDateRange(Context, long, long, int) formatDateRange}
+     * that takes a {@link java.util.Formatter}.
+     * 
+     * @param context the context is required only if the time is shown
+     * @param startMillis the start time in UTC milliseconds
+     * @param endMillis the end time in UTC milliseconds
+     * @param flags a bit mask of options See
+     * {@link #formatDateRange(Context, long, long, int) formatDateRange}
+     * @return a string containing the formatted date/time range.
+     */
+    public static String formatDateRange(Context context, long startMillis,
+            long endMillis, int flags) {
+        Formatter f = new Formatter(new StringBuilder(50), Locale.getDefault());
+        return formatDateRange(context, f, startMillis, endMillis, flags).toString();
+    }
+
+    /**
+     * Formats a date or a time range according to the local conventions.
      * 
      * <p>
      * Example output strings (date formats in these examples are shown using
@@ -1181,14 +1208,17 @@
      * instead of "December 31, 2008".
      * 
      * @param context the context is required only if the time is shown
+     * @param formatter the Formatter used for formatting the date range.
+     * Note: be sure to call setLength(0) on StringBuilder passed to
+     * the Formatter constructor unless you want the results to accumulate.
      * @param startMillis the start time in UTC milliseconds
      * @param endMillis the end time in UTC milliseconds
      * @param flags a bit mask of options
      *   
-     * @return a string containing the formatted date/time range.
+     * @return the formatter with the formatted date/time range appended to the string buffer.
      */
-    public static String formatDateRange(Context context, long startMillis,
-                long endMillis, int flags) {
+    public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
+            long endMillis, int flags) {
         Resources res = Resources.getSystem();
         boolean showTime = (flags & FORMAT_SHOW_TIME) != 0;
         boolean showWeekDay = (flags & FORMAT_SHOW_WEEKDAY) != 0;
@@ -1423,8 +1453,7 @@
 
         if (noMonthDay && startMonthNum == endMonthNum) {
             // Example: "January, 2008"
-            String startDateString = startDate.format(defaultDateFormat);
-            return startDateString;
+            return formatter.format("%s", startDate.format(defaultDateFormat));
         }
 
         if (startYear != endYear || noMonthDay) {
@@ -1436,10 +1465,9 @@
 
             // The values that are used in a fullFormat string are specified
             // by position.
-            dateRange = String.format(fullFormat,
+            return formatter.format(fullFormat,
                     startWeekDayString, startDateString, startTimeString,
                     endWeekDayString, endDateString, endTimeString);
-            return dateRange;
         }
 
         // Get the month, day, and year strings for the start and end dates
@@ -1476,12 +1504,11 @@
 
             // The values that are used in a fullFormat string are specified
             // by position.
-            dateRange = String.format(fullFormat,
+            return formatter.format(fullFormat,
                     startWeekDayString, startMonthString, startMonthDayString,
                     startYearString, startTimeString,
                     endWeekDayString, endMonthString, endMonthDayString,
                     endYearString, endTimeString);
-            return dateRange;
         }
 
         if (startDay != endDay) {
@@ -1496,12 +1523,11 @@
 
             // The values that are used in a fullFormat string are specified
             // by position.
-            dateRange = String.format(fullFormat,
+            return formatter.format(fullFormat,
                     startWeekDayString, startMonthString, startMonthDayString,
                     startYearString, startTimeString,
                     endWeekDayString, endMonthString, endMonthDayString,
                     endYearString, endTimeString);
-            return dateRange;
         }
 
         // Same start and end day
@@ -1522,6 +1548,7 @@
             } else {
                 // Example: "10:00 - 11:00 am"
                 String timeFormat = res.getString(com.android.internal.R.string.time1_time2);
+                // Don't use the user supplied Formatter because the result will pollute the buffer.
                 timeString = String.format(timeFormat, startTimeString, endTimeString);
             }
         }
@@ -1545,7 +1572,7 @@
                     fullFormat = res.getString(com.android.internal.R.string.time_date);
                 } else {
                     // Example: "Oct 9"
-                    return dateString;
+                    return formatter.format("%s", dateString);
                 }
             }
         } else if (showWeekDay) {
@@ -1554,16 +1581,15 @@
                 fullFormat = res.getString(com.android.internal.R.string.time_wday);
             } else {
                 // Example: "Tue"
-                return startWeekDayString;
+                return formatter.format("%s", startWeekDayString);
             }
         } else if (showTime) {
-            return timeString;
+            return formatter.format("%s", timeString);
         }
 
         // The values that are used in a fullFormat string are specified
         // by position.
-        dateRange = String.format(fullFormat, timeString, startWeekDayString, dateString);
-        return dateRange;
+        return formatter.format(fullFormat, timeString, startWeekDayString, dateString);
     }
 
     /**