DateUtils.java revision 25d8b05fb77e8ee755aacd27c1c2d3b237537b7a
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.text.format;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.R;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Configuration;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Calendar;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Date;
27becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chanimport java.util.Formatter;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.GregorianCalendar;
29becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chanimport java.util.Locale;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.TimeZone;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class contains various date-related utilities for creating text for things like
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * elapsed time and date ranges, strings for days of the week and months, and AM/PM text etc.
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class DateUtils
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final Object sLock = new Object();
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] sDaysLong = new int[] {
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_long_sunday,
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_long_monday,
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_long_tuesday,
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_long_wednesday,
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_long_thursday,
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_long_friday,
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_long_saturday,
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] sDaysMedium = new int[] {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_medium_sunday,
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_medium_monday,
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_medium_tuesday,
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_medium_wednesday,
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_medium_thursday,
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_medium_friday,
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_medium_saturday,
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] sDaysShort = new int[] {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_short_sunday,
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_short_monday,
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_short_tuesday,
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_short_wednesday,
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_short_thursday,
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_short_friday,
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_short_saturday,
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] sDaysShortest = new int[] {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_shortest_sunday,
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_shortest_monday,
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_shortest_tuesday,
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_shortest_wednesday,
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_shortest_thursday,
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_shortest_friday,
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.day_of_week_shortest_saturday,
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
755bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer    private static final int[] sMonthsStandaloneLong = new int [] {
765bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_january,
775bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_february,
785bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_march,
795bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_april,
805bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_may,
815bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_june,
825bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_july,
835bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_august,
845bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_september,
855bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_october,
865bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_november,
875bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            com.android.internal.R.string.month_long_standalone_december,
885bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        };
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] sMonthsLong = new int [] {
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_january,
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_february,
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_march,
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_april,
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_may,
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_june,
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_july,
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_august,
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_september,
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_october,
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_november,
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_long_december,
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] sMonthsMedium = new int [] {
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_january,
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_february,
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_march,
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_april,
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_may,
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_june,
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_july,
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_august,
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_september,
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_october,
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_november,
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_medium_december,
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] sMonthsShortest = new int [] {
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_january,
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_february,
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_march,
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_april,
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_may,
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_june,
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_july,
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_august,
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_september,
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_october,
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_november,
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.month_shortest_december,
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] sAmPm = new int[] {
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.am,
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            com.android.internal.R.string.pm,
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static Configuration sLastConfig;
1365bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer    private static java.text.DateFormat sStatusTimeFormat;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String sElapsedFormatMMSS;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String sElapsedFormatHMMSS;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String FAST_FORMAT_HMMSS = "%1$d:%2$02d:%3$02d";
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String FAST_FORMAT_MMSS = "%1$02d:%2$02d";
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final char TIME_PADDING = '0';
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final char TIME_SEPARATOR = ':';
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long SECOND_IN_MILLIS = 1000;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
15184c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer    /**
15284c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * This constant is actually the length of 364 days, not of a year!
15384c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     */
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long YEAR_IN_MILLIS = WEEK_IN_MILLIS * 52;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The following FORMAT_* symbols are used for specifying the format of
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // dates and times in the formatDateRange method.
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_SHOW_TIME = 0x00001;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_SHOW_WEEKDAY = 0x00002;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_SHOW_YEAR = 0x00004;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_YEAR = 0x00008;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_SHOW_DATE = 0x00010;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_MONTH_DAY = 0x00020;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_12HOUR = 0x00040;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_24HOUR = 0x00080;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_CAP_AMPM = 0x00100;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_NOON = 0x00200;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_CAP_NOON = 0x00400;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_MIDNIGHT = 0x00800;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_CAP_MIDNIGHT = 0x01000;
171577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    /**
172577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @deprecated Use
173577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
174577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * and pass in {@link Time#TIMEZONE_UTC Time.TIMEZONE_UTC} for the timeZone instead.
175577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     */
176577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    @Deprecated
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_UTC = 0x02000;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_TIME = 0x04000;
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_WEEKDAY = 0x08000;
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_MONTH = 0x10000;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NUMERIC_DATE = 0x20000;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_RELATIVE = 0x40000;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_ALL = 0x80000;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_CAP_NOON_MIDNIGHT = (FORMAT_CAP_NOON | FORMAT_CAP_MIDNIGHT);
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_NOON_MIDNIGHT = (FORMAT_NO_NOON | FORMAT_NO_MIDNIGHT);
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Date and time format strings that are constant and don't need to be
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // translated.
18984c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer    /**
19084c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * This is not actually the preferred 24-hour date format in all locales.
19184c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     */
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String HOUR_MINUTE_24 = "%H:%M";
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String MONTH_FORMAT = "%B";
1945669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer    /**
1955669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer     * This is not actually a useful month name in all locales.
1965669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer     */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String ABBREV_MONTH_FORMAT = "%b";
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String NUMERIC_MONTH_FORMAT = "%m";
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String MONTH_DAY_FORMAT = "%-d";
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String YEAR_FORMAT = "%Y";
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String YEAR_FORMAT_TWO_DIGITS = "%g";
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String WEEKDAY_FORMAT = "%A";
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String ABBREV_WEEKDAY_FORMAT = "%a";
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This table is used to lookup the resource string id of a format string
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // used for formatting a start and end date that fall in the same year.
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The index is constructed from a bit-wise OR of the boolean values:
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // {showTime, showYear, showWeekDay}.  For example, if showYear and
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // showWeekDay are both true, then the index would be 3.
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int sameYearTable[] = {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_md1_md2,
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_wday1_md1_wday2_md2,
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_mdy1_mdy2,
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_wday1_mdy1_wday2_mdy2,
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_md1_time1_md2_time2,
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_wday1_md1_time1_wday2_md2_time2,
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_mdy1_time1_mdy2_time2,
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_wday1_mdy1_time1_wday2_mdy2_time2,
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Numeric date strings
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_md1_md2,
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_md1_wday2_md2,
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_mdy1_mdy2,
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_mdy1_wday2_mdy2,
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_md1_time1_md2_time2,
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_md1_time1_wday2_md2_time2,
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_mdy1_time1_mdy2_time2,
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_mdy1_time1_wday2_mdy2_time2,
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This table is used to lookup the resource string id of a format string
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // used for formatting a start and end date that fall in the same month.
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The index is constructed from a bit-wise OR of the boolean values:
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // {showTime, showYear, showWeekDay}.  For example, if showYear and
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // showWeekDay are both true, then the index would be 3.
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int sameMonthTable[] = {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_md1_md2,
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_wday1_md1_wday2_md2,
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_mdy1_mdy2,
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_wday1_mdy1_wday2_mdy2,
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_md1_time1_md2_time2,
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_wday1_md1_time1_wday2_md2_time2,
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_mdy1_time1_mdy2_time2,
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_wday1_mdy1_time1_wday2_mdy2_time2,
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_md1_md2,
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_md1_wday2_md2,
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_mdy1_mdy2,
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_mdy1_wday2_mdy2,
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_md1_time1_md2_time2,
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_md1_time1_wday2_md2_time2,
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_mdy1_time1_mdy2_time2,
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_mdy1_time1_wday2_mdy2_time2,
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request the full spelled-out name. For use with the 'abbrev' parameter of
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getDayOfWeekString} and {@link #getMonthString}.
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @more <p>
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *       e.g. "Sunday" or "January"
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_LONG = 10;
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request an abbreviated version of the name. For use with the 'abbrev'
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @more <p>
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *       e.g. "Sun" or "Jan"
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_MEDIUM = 20;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request a shorter abbreviated version of the name.
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @more
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>e.g. "Su" or "Jan"
2795bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * <p>In most languages, the results returned for LENGTH_SHORT will be the same as
2805bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * the results returned for {@link #LENGTH_MEDIUM}.
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_SHORT = 30;
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request an even shorter abbreviated version of the name.
2865bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * Do not use this.  Currently this will always return the same result
2875bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * as {@link #LENGTH_SHORT}.
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_SHORTER = 40;
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request an even shorter abbreviated version of the name.
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @more
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>e.g. "S", "T", "T" or "J"
2965bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * <p>In some languages, the results returned for LENGTH_SHORTEST will be the same as
2975bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * the results returned for {@link #LENGTH_SHORT}.
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_SHORTEST = 50;
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a string for the day of the week.
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dayOfWeek One of {@link Calendar#SUNDAY Calendar.SUNDAY},
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               {@link Calendar#MONDAY Calendar.MONDAY}, etc.
3055bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT},
3065bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               {@link #LENGTH_MEDIUM}, or {@link #LENGTH_SHORTEST}.
3075bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               Note that in most languages, {@link #LENGTH_SHORT}
3085bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               will return the same as {@link #LENGTH_MEDIUM}.
3095bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               Undefined lengths will return {@link #LENGTH_MEDIUM}
3105bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               but may return something different in the future.
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IndexOutOfBoundsException if the dayOfWeek is out of bounds.
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String getDayOfWeekString(int dayOfWeek, int abbrev) {
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int[] list;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (abbrev) {
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LENGTH_LONG:       list = sDaysLong;       break;
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LENGTH_MEDIUM:     list = sDaysMedium;     break;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LENGTH_SHORT:      list = sDaysShort;      break;
3195bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            case LENGTH_SHORTER:    list = sDaysShort;      break;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LENGTH_SHORTEST:   list = sDaysShortest;   break;
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:                list = sDaysMedium;     break;
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources r = Resources.getSystem();
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return r.getString(list[dayOfWeek - Calendar.SUNDAY]);
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a localized string for AM or PM.
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param ampm Either {@link Calendar#AM Calendar.AM} or {@link Calendar#PM Calendar.PM}.
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IndexOutOfBoundsException if the ampm is out of bounds.
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Localized version of "AM" or "PM".
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String getAMPMString(int ampm) {
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources r = Resources.getSystem();
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return r.getString(sAmPm[ampm - Calendar.AM]);
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3405bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * Return a localized string for the month of the year.
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param month One of {@link Calendar#JANUARY Calendar.JANUARY},
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
3435bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_MEDIUM},
3445bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               or {@link #LENGTH_SHORTEST}.
3455bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               Undefined lengths will return {@link #LENGTH_MEDIUM}
3465bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               but may return something different in the future.
3475bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @return Localized month of the year.
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String getMonthString(int month, int abbrev) {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER.
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This is a shortcut to not spam the translators with too many variations
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // of the same string.  If we find that in a language the distinction
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // is necessary, we can can add more without changing this API.
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int[] list;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (abbrev) {
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LENGTH_LONG:       list = sMonthsLong;     break;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LENGTH_MEDIUM:     list = sMonthsMedium;   break;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LENGTH_SHORT:      list = sMonthsMedium;   break;
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LENGTH_SHORTER:    list = sMonthsMedium;   break;
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LENGTH_SHORTEST:   list = sMonthsShortest; break;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:                list = sMonthsMedium;   break;
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources r = Resources.getSystem();
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return r.getString(list[month - Calendar.JANUARY]);
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3695bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * Return a localized string for the month of the year, for
3705bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * contexts where the month is not formatted together with
3715bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * a day of the month.
3725bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *
3735bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @param month One of {@link Calendar#JANUARY Calendar.JANUARY},
3745bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
3755bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_MEDIUM},
3765bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               or {@link #LENGTH_SHORTEST}.
3775bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               Undefined lengths will return {@link #LENGTH_MEDIUM}
3785bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               but may return something different in the future.
3795bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @return Localized month of the year.
3805bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @hide Pending API council approval
3815bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     */
3825bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer    public static String getStandaloneMonthString(int month, int abbrev) {
3835bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        // Note that here we use sMonthsMedium for MEDIUM, SHORT and SHORTER.
3845bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        // This is a shortcut to not spam the translators with too many variations
3855bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        // of the same string.  If we find that in a language the distinction
3865bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        // is necessary, we can can add more without changing this API.
3875bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        int[] list;
3885bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        switch (abbrev) {
3895bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            case LENGTH_LONG:       list = sMonthsStandaloneLong;
3905bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer                                                            break;
3915bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            case LENGTH_MEDIUM:     list = sMonthsMedium;   break;
3925bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            case LENGTH_SHORT:      list = sMonthsMedium;   break;
3935bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            case LENGTH_SHORTER:    list = sMonthsMedium;   break;
3945bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            case LENGTH_SHORTEST:   list = sMonthsShortest; break;
3955bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer            default:                list = sMonthsMedium;   break;
3965bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        }
3975bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer
3985bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        Resources r = Resources.getSystem();
3995bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        return r.getString(list[month - Calendar.JANUARY]);
4005bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer    }
4015bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer
4025bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer    /**
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a string describing the elapsed time since startTime.
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param startTime some time in the past.
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a String object containing the elapsed time.
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getRelativeTimeSpanString(long, long, long)
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(long startTime) {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return getRelativeTimeSpanString(startTime, System.currentTimeMillis(), MINUTE_IN_MILLIS);
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a string describing 'time' as a time relative to 'now'.
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time spans in the past are formatted like "42 minutes ago".
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time spans in the future are formatted like "in 42 minutes".
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param time the time to describe, in milliseconds
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param now the current time in milliseconds
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param minResolution the minimum timespan to report. For example, a time 3 seconds in the
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     past will be reported as "0 minutes ago" if this is set to MINUTE_IN_MILLIS. Pass one of
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution) {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_ABBREV_MONTH;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return getRelativeTimeSpanString(time, now, minResolution, flags);
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a string describing 'time' as a time relative to 'now'.
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time spans in the past are formatted like "42 minutes ago". Time spans in
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the future are formatted like "in 42 minutes".
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Can use {@link #FORMAT_ABBREV_RELATIVE} flag to use abbreviated relative
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * times, like "42 mins ago".
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param time the time to describe, in milliseconds
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param now the current time in milliseconds
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param minResolution the minimum timespan to report. For example, a time
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            3 seconds in the past will be reported as "0 minutes ago" if
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            this is set to MINUTE_IN_MILLIS. Pass one of 0,
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS,
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            WEEK_IN_MILLIS
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags a bit mask of formatting options, such as
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #FORMAT_NUMERIC_DATE} or
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #FORMAT_ABBREV_RELATIVE}
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution,
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int flags) {
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources r = Resources.getSystem();
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean abbrevRelative = (flags & (FORMAT_ABBREV_RELATIVE | FORMAT_ABBREV_ALL)) != 0;
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean past = (now >= time);
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long duration = Math.abs(now - time);
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int resId;
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long count;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (duration < MINUTE_IN_MILLIS && minResolution < MINUTE_IN_MILLIS) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count = duration / SECOND_IN_MILLIS;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_num_seconds_ago;
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.num_seconds_ago;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_in_num_seconds;
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.in_num_seconds;
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (duration < HOUR_IN_MILLIS && minResolution < HOUR_IN_MILLIS) {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count = duration / MINUTE_IN_MILLIS;
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_num_minutes_ago;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.num_minutes_ago;
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_in_num_minutes;
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.in_num_minutes;
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (duration < DAY_IN_MILLIS && minResolution < DAY_IN_MILLIS) {
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count = duration / HOUR_IN_MILLIS;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_num_hours_ago;
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.num_hours_ago;
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_in_num_hours;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.in_num_hours;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) {
5056a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            count = getNumberOfDaysPassed(time, now);
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_num_days_ago;
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.num_days_ago;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_in_num_days;
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.in_num_days;
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // We know that we won't be showing the time, so it is safe to pass
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // in a null context.
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return formatDateRange(null, time, time, flags);
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String format = r.getQuantityString(resId, (int) count);
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String.format(format, count);
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5306a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     * Returns the number of days passed between two dates.
5316a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     *
5326a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     * @param date1 first date
5336a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     * @param date2 second date
5346a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     * @return number of days passed between to dates.
5356a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     */
5366a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques    private synchronized static long getNumberOfDaysPassed(long date1, long date2) {
5376a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        if (sThenTime == null) {
5386a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            sThenTime = new Time();
5396a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        }
5406a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        sThenTime.set(date1);
5416a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        int day1 = Time.getJulianDay(date1, sThenTime.gmtoff);
5426a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        sThenTime.set(date2);
5436a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        int day2 = Time.getJulianDay(date2, sThenTime.gmtoff);
5446a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        return Math.abs(day2 - day1);
5456a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques    }
5466a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques
5476a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques    /**
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return string describing the elapsed time since startTime formatted like
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "[relative time/date], [time]".
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example output strings for the US date format.
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>3 mins ago, 10:15 AM</li>
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>yesterday, 12:20 PM</li>
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Dec 12, 4:12 AM</li>
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>11/14/2007, 8:20 AM</li>
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param time some time in the past.
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param minResolution the minimum elapsed time (in milliseconds) to report
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            when showing relative times. For example, a time 3 seconds in
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            the past will be reported as "0 minutes ago" if this is set to
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #MINUTE_IN_MILLIS}.
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param transitionResolution the elapsed time (in milliseconds) at which
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            to stop reporting relative measurements. Elapsed times greater
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            than this resolution will default to normal date formatting.
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            For example, will transition from "6 days ago" to "Dec 12"
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            when using {@link #WEEK_IN_MILLIS}.
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution,
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long transitionResolution, int flags) {
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources r = Resources.getSystem();
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long now = System.currentTimeMillis();
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long duration = Math.abs(now - time);
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // getRelativeTimeSpanString() doesn't correctly format relative dates
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // above a week or exact dates below a day, so clamp
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // transitionResolution as needed.
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (transitionResolution > WEEK_IN_MILLIS) {
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            transitionResolution = WEEK_IN_MILLIS;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (transitionResolution < DAY_IN_MILLIS) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            transitionResolution = DAY_IN_MILLIS;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CharSequence timeClause = formatDateRange(c, time, time, FORMAT_SHOW_TIME);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String result;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (duration < transitionResolution) {
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CharSequence relativeClause = getRelativeTimeSpanString(time, now, minResolution, flags);
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = r.getString(com.android.internal.R.string.relative_time, relativeClause, timeClause);
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CharSequence dateClause = getRelativeTimeSpanString(c, time, false);
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = r.getString(com.android.internal.R.string.date_time, dateClause, timeClause);
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a string describing a day relative to the current day. For example if the day is
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * today this function returns "Today", if the day was a week ago it returns "7 days ago", and
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if the day is in 2 weeks it returns "in 14 days".
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param r the resources to get the strings from
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param day the relative day to describe in UTC milliseconds
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param today the current time in UTC milliseconds
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a formatting string
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String getRelativeDayString(Resources r, long day, long today) {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Time startTime = new Time();
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        startTime.set(day);
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Time currentTime = new Time();
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        currentTime.set(today);
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startDay = Time.getJulianDay(day, startTime.gmtoff);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int currentDay = Time.getJulianDay(today, currentTime.gmtoff);
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int days = Math.abs(currentDay - startDay);
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean past = (today > day);
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (days == 1) {
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return r.getString(com.android.internal.R.string.yesterday);
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return r.getString(com.android.internal.R.string.tomorrow);
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (days == 0) {
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return r.getString(com.android.internal.R.string.today);
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int resId;
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (past) {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resId = com.android.internal.R.plurals.num_days_ago;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resId = com.android.internal.R.plurals.in_num_days;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String format = r.getQuantityString(resId, days);
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String.format(format, days);
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void initFormatStrings() {
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (sLock) {
64525d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            initFormatStringsLocked();
64625d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        }
64725d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK    }
64825d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK
64925d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK    private static void initFormatStringsLocked() {
65025d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        Resources r = Resources.getSystem();
65125d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        Configuration cfg = r.getConfiguration();
65225d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        if (sLastConfig == null || !sLastConfig.equals(cfg)) {
65325d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            sLastConfig = cfg;
65425d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            sStatusTimeFormat = java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT);
65525d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss);
65625d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Format a time so it appears like it would in the status bar clock.
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link #DateFormat.getTimeFormat(Context)} instead.
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final CharSequence timeString(long millis) {
66625d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        synchronized (sLock) {
66725d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            initFormatStringsLocked();
66825d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            return sStatusTimeFormat.format(millis);
66925d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        }
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Formats an elapsed time in the form "MM:SS" or "H:MM:SS"
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for display on the call-in-progress screen.
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param elapsedSeconds the elapsed time in seconds.
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String formatElapsedTime(long elapsedSeconds) {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return formatElapsedTime(null, elapsedSeconds);
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Formats an elapsed time in the form "MM:SS" or "H:MM:SS"
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for display on the call-in-progress screen.
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param recycle {@link StringBuilder} to recycle, if possible
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param elapsedSeconds the elapsed time in seconds.
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String formatElapsedTime(StringBuilder recycle, long elapsedSeconds) {
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initFormatStrings();
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long hours = 0;
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minutes = 0;
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long seconds = 0;
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (elapsedSeconds >= 3600) {
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            hours = elapsedSeconds / 3600;
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            elapsedSeconds -= hours * 3600;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (elapsedSeconds >= 60) {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            minutes = elapsedSeconds / 60;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            elapsedSeconds -= minutes * 60;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        seconds = elapsedSeconds;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String result;
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hours > 0) {
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return formatElapsedTime(recycle, sElapsedFormatHMMSS, hours, minutes, seconds);
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return formatElapsedTime(recycle, sElapsedFormatMMSS, minutes, seconds);
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fast formatting of h:mm:ss
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String formatElapsedTime(StringBuilder recycle, String format, long hours,
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long minutes, long seconds) {
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (FAST_FORMAT_HMMSS.equals(format)) {
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            StringBuilder sb = recycle;
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sb == null) {
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb = new StringBuilder(8);
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.setLength(0);
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(hours);
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(TIME_SEPARATOR);
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (minutes < 10) {
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(TIME_PADDING);
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(toDigitChar(minutes / 10));
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(toDigitChar(minutes % 10));
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(TIME_SEPARATOR);
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (seconds < 10) {
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(TIME_PADDING);
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(toDigitChar(seconds / 10));
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(toDigitChar(seconds % 10));
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sb.toString();
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String.format(format, hours, minutes, seconds);
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fast formatting of m:ss
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String formatElapsedTime(StringBuilder recycle, String format, long minutes,
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long seconds) {
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (FAST_FORMAT_MMSS.equals(format)) {
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            StringBuilder sb = recycle;
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sb == null) {
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb = new StringBuilder(8);
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.setLength(0);
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (minutes < 10) {
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(TIME_PADDING);
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(toDigitChar(minutes / 10));
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(toDigitChar(minutes % 10));
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(TIME_SEPARATOR);
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (seconds < 10) {
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(TIME_PADDING);
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(toDigitChar(seconds / 10));
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(toDigitChar(seconds % 10));
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sb.toString();
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String.format(format, minutes, seconds);
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static char toDigitChar(long digit) {
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (char) (digit + '0');
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Format a date / time such that if the then is on the same day as now, it shows
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * just the time and if it's a different day, it shows just the date.
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The parameters dateFormat and timeFormat should each be one of
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#DEFAULT},
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#FULL},
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#LONG},
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#MEDIUM}
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#SHORT}
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param then the date to format
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param now the base time
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dateStyle how to format the date portion.
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param timeStyle how to format the time portion.
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final CharSequence formatSameDayTime(long then, long now,
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int dateStyle, int timeStyle) {
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Calendar thenCal = new GregorianCalendar();
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        thenCal.setTimeInMillis(then);
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Date thenDate = thenCal.getTime();
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Calendar nowCal = new GregorianCalendar();
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nowCal.setTimeInMillis(now);
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        java.text.DateFormat f;
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thenCal.get(Calendar.YEAR) == nowCal.get(Calendar.YEAR)
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && thenCal.get(Calendar.MONTH) == nowCal.get(Calendar.MONTH)
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && thenCal.get(Calendar.DAY_OF_MONTH) == nowCal.get(Calendar.DAY_OF_MONTH)) {
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f = java.text.DateFormat.getTimeInstance(timeStyle);
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f = java.text.DateFormat.getDateInstance(dateStyle);
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return f.format(thenDate);
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Calendar newCalendar(boolean zulu)
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (zulu)
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return Calendar.getInstance(TimeZone.getTimeZone("GMT"));
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Calendar.getInstance();
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the supplied when is today else false
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isToday(long when) {
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Time time = new Time();
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        time.set(when);
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int thenYear = time.year;
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int thenMonth = time.month;
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int thenMonthDay = time.monthDay;
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        time.set(System.currentTimeMillis());
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (thenYear == time.year)
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (thenMonth == time.month)
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (thenMonthDay == time.monthDay);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return true if this date string is local time
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isUTC(String s)
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (s.length() == 16 && s.charAt(15) == 'Z') {
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (s.length() == 9 && s.charAt(8) == 'Z') {
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // XXX not sure if this case possible/valid
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a string containing the date and time in RFC2445 format.
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Ensures that the time is written in UTC.  The Calendar class doesn't
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * really help out with this, so this is slower than it ought to be.
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cal the date and time to write
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String writeDateTime(Calendar cal)
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TimeZone tz = TimeZone.getTimeZone("GMT");
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        GregorianCalendar c = new GregorianCalendar(tz);
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.setTimeInMillis(cal.getTimeInMillis());
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return writeDateTime(c, true);
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a string containing the date and time in RFC2445 format.
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cal the date and time to write
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param zulu If the calendar is in UTC, pass true, and a Z will
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be written at the end as per RFC2445.  Otherwise, the time is
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * considered in localtime.
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String writeDateTime(Calendar cal, boolean zulu)
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder sb = new StringBuilder();
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.ensureCapacity(16);
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (zulu) {
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.setLength(16);
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.setCharAt(15, 'Z');
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.setLength(15);
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return writeDateTime(cal, sb);
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a string containing the date and time in RFC2445 format.
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cal the date and time to write
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sb a StringBuilder to use.  It is assumed that setLength
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *           has already been called on sb to the appropriate length
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *           which is sb.setLength(zulu ? 16 : 15)
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String writeDateTime(Calendar cal, StringBuilder sb)
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int n;
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.YEAR);
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(3, (char)('0'+n%10));
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(2, (char)('0'+n%10));
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(1, (char)('0'+n%10));
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(0, (char)('0'+n%10));
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.MONTH) + 1;
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(5, (char)('0'+n%10));
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(4, (char)('0'+n%10));
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.DAY_OF_MONTH);
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(7, (char)('0'+n%10));
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(6, (char)('0'+n%10));
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(8, 'T');
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.HOUR_OF_DAY);
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(10, (char)('0'+n%10));
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(9, (char)('0'+n%10));
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.MINUTE);
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(12, (char)('0'+n%10));
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(11, (char)('0'+n%10));
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.SECOND);
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(14, (char)('0'+n%10));
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(13, (char)('0'+n%10));
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sb.toString();
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void assign(Calendar lval, Calendar rval)
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // there should be a faster way.
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lval.clear();
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lval.setTimeInMillis(rval.getTimeInMillis());
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Formats a date or a time range according to the local conventions.
970becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * <p>
971becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * Note that this is a convenience method. Using it involves creating an
972becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * internal {@link java.util.Formatter} instance on-the-fly, which is
973becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * somewhat costly in terms of memory and time. This is probably acceptable
974becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * if you use the method only rarely, but if you rely on it for formatting a
975becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * large number of dates, consider creating and reusing your own
976becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * {@link java.util.Formatter} instance and use the version of
977becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * {@link #formatDateRange(Context, long, long, int) formatDateRange}
978becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * that takes a {@link java.util.Formatter}.
979577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     *
980becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param context the context is required only if the time is shown
981becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param startMillis the start time in UTC milliseconds
982becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param endMillis the end time in UTC milliseconds
983becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param flags a bit mask of options See
984577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
985becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @return a string containing the formatted date/time range.
986becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     */
987becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan    public static String formatDateRange(Context context, long startMillis,
988becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            long endMillis, int flags) {
989becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan        Formatter f = new Formatter(new StringBuilder(50), Locale.getDefault());
990becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan        return formatDateRange(context, f, startMillis, endMillis, flags).toString();
991becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan    }
992becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan
993becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan    /**
994becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * Formats a date or a time range according to the local conventions.
995577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * <p>
996577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * Note that this is a convenience method for formatting the date or
997577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * time range in the local time zone. If you want to specify the time
998577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * zone please use
999577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}.
1000577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     *
1001577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param context the context is required only if the time is shown
1002577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param formatter the Formatter used for formatting the date range.
1003577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * Note: be sure to call setLength(0) on StringBuilder passed to
1004577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * the Formatter constructor unless you want the results to accumulate.
1005577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param startMillis the start time in UTC milliseconds
1006577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param endMillis the end time in UTC milliseconds
1007577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param flags a bit mask of options See
1008577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
1009577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @return a string containing the formatted date/time range.
1010577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     */
1011577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
1012577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            long endMillis, int flags) {
1013577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        return formatDateRange(context, formatter, startMillis, endMillis, flags, null);
1014577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    }
1015577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik
1016577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    /**
1017577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * Formats a date or a time range according to the local conventions.
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example output strings (date formats in these examples are shown using
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the US date format convention but that may change depending on the
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * local settings):
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10:15am</li>
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3:00pm - 4:00pm</li>
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3pm - 4pm</li>
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3PM - 4PM</li>
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>08:00 - 17:00</li>
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 9</li>
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Tue, Oct 9</li>
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>October 9, 2007</li>
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 9 - 10</li>
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 9 - 10, 2007</li>
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 28 - Nov 3, 2007</li>
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Dec 31, 2007 - Jan 1, 2008</li>
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 9, 8:00am - Oct 10, 5:00pm</li>
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>12/31/2007 - 01/01/2008</li>
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The flags argument is a bitmask of options from the following list:
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_SHOW_TIME</li>
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_SHOW_WEEKDAY</li>
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_SHOW_YEAR</li>
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NO_YEAR</li>
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_SHOW_DATE</li>
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NO_MONTH_DAY</li>
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_12HOUR</li>
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_24HOUR</li>
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_CAP_AMPM</li>
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NO_NOON</li>
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_CAP_NOON</li>
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NO_MIDNIGHT</li>
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_CAP_MIDNIGHT</li>
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_UTC</li>
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_ABBREV_TIME</li>
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_ABBREV_WEEKDAY</li>
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_ABBREV_MONTH</li>
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_ABBREV_ALL</li>
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NUMERIC_DATE</li>
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_SHOW_TIME is set, the time is shown as part of the date range.
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the start and end time are the same, then just the start time is
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown.
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_SHOW_WEEKDAY is set, then the weekday is shown.
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_SHOW_YEAR is set, then the year is always shown.
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NO_YEAR is set, then the year is not shown.
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If neither FORMAT_SHOW_YEAR nor FORMAT_NO_YEAR are set, then the year
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is shown only if it is different from the current year, or if the start
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and end dates fall on different years.  If both are set,
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * FORMAT_SHOW_YEAR takes precedence.
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Normally the date is shown unless the start and end day are the same.
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_SHOW_DATE is set, then the date is always shown, even for
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same day ranges.
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NO_MONTH_DAY is set, then if the date is shown, just the
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * month name will be shown, not the day of the month.  For example,
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "January, 2008" instead of "January 6 - 12, 2008".
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_CAP_AMPM is set and 12-hour time is used, then the "AM"
109384c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * and "PM" are capitalized.  You should not use this flag
109484c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * because in some locales these terms cannot be capitalized, and in
109584c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * many others it doesn't make sense to do so even though it is possible.
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NO_NOON is set and 12-hour time is used, then "12pm" is
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown instead of "noon".
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_CAP_NOON is set and 12-hour time is used, then "Noon" is
110384c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * shown instead of "noon".  You should probably not use this flag
110484c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * because in many locales it will not make sense to capitalize
110584c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * the term.
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NO_MIDNIGHT is set and 12-hour time is used, then "12am" is
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown instead of "midnight".
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
111284c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * If FORMAT_CAP_MIDNIGHT is set and 12-hour time is used, then "Midnight"
111384c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * is shown instead of "midnight".  You should probably not use this
111484c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * flag because in many locales it will not make sense to capitalize
111584c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * the term.
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_12HOUR is set and the time is shown, then the time is
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown in the 12-hour time format. You should not normally set this.
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Instead, let the time format be chosen automatically according to the
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * FORMAT_24HOUR takes precedence.
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_24HOUR is set and the time is shown, then the time is
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown in the 24-hour time format. You should not normally set this.
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Instead, let the time format be chosen automatically according to the
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * FORMAT_24HOUR takes precedence.
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
1132577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * If FORMAT_UTC is set, then the UTC time zone is used for the start
1133577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * and end milliseconds unless a time zone is specified. If a time zone
1134577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * is specified it will be used regardless of the FORMAT_UTC flag.
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_ABBREV_TIME is set and 12-hour time format is used, then the
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * start and end times (if shown) are abbreviated by not showing the minutes
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if they are zero.  For example, instead of "3:00pm" the time would be
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * abbreviated to "3pm".
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_ABBREV_WEEKDAY is set, then the weekday (if shown) is
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * abbreviated to a 3-letter string.
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_ABBREV_MONTH is set, then the month (if shown) is abbreviated
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to a 3-letter string.
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_ABBREV_ALL is set, then the weekday and the month (if shown)
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * are abbreviated to 3-letter strings.
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NUMERIC_DATE is set, then the date is shown in numeric format
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of using the name of the month.  For example, "12/31/2008"
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of "December 31, 2008".
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context the context is required only if the time is shown
1160becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param formatter the Formatter used for formatting the date range.
1161becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * Note: be sure to call setLength(0) on StringBuilder passed to
1162becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * the Formatter constructor unless you want the results to accumulate.
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param startMillis the start time in UTC milliseconds
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param endMillis the end time in UTC milliseconds
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags a bit mask of options
1166577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param timeZone the time zone to compute the string in. Use null for local
1167577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * or if the FORMAT_UTC flag is being used.
1168577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     *
1169becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @return the formatter with the formatted date/time range appended to the string buffer.
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1171becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan    public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
1172577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            long endMillis, int flags, String timeZone) {
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources res = Resources.getSystem();
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showTime = (flags & FORMAT_SHOW_TIME) != 0;
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showWeekDay = (flags & FORMAT_SHOW_WEEKDAY) != 0;
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showYear = (flags & FORMAT_SHOW_YEAR) != 0;
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean noYear = (flags & FORMAT_NO_YEAR) != 0;
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean useUTC = (flags & FORMAT_UTC) != 0;
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean abbrevWeekDay = (flags & (FORMAT_ABBREV_WEEKDAY | FORMAT_ABBREV_ALL)) != 0;
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean abbrevMonth = (flags & (FORMAT_ABBREV_MONTH | FORMAT_ABBREV_ALL)) != 0;
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean noMonthDay = (flags & FORMAT_NO_MONTH_DAY) != 0;
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean numericDate = (flags & FORMAT_NUMERIC_DATE) != 0;
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If we're getting called with a single instant in time (from
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // e.g. formatDateTime(), below), then we can skip a lot of
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // computation below that'd otherwise be thrown out.
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isInstant = (startMillis == endMillis);
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1189577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        Time startDate;
1190577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        if (timeZone != null) {
1191577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            startDate = new Time(timeZone);
1192577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        } else if (useUTC) {
1193577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            startDate = new Time(Time.TIMEZONE_UTC);
1194577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        } else {
1195577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            startDate = new Time();
1196577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        }
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        startDate.set(startMillis);
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Time endDate;
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int dayDistance;
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isInstant) {
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endDate = startDate;
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dayDistance = 0;
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1205577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            if (timeZone != null) {
1206577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik                endDate = new Time(timeZone);
1207577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            } else if (useUTC) {
1208577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik                endDate = new Time(Time.TIMEZONE_UTC);
1209577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            } else {
1210577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik                endDate = new Time();
1211577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            }
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endDate.set(endMillis);
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int startJulianDay = Time.getJulianDay(startMillis, startDate.gmtoff);
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int endJulianDay = Time.getJulianDay(endMillis, endDate.gmtoff);
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dayDistance = endJulianDay - startJulianDay;
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the end date ends at 12am at the beginning of a day,
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // then modify it to make it look like it ends at midnight on
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the previous day.  This will allow us to display "8pm - midnight",
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // for example, instead of "Nov 10, 8pm - Nov 11, 12am". But we only do
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // this if it is midnight of the same day as the start date because
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // for multiple-day events, an end time of "midnight on Nov 11" is
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // ambiguous and confusing (is that midnight the start of Nov 11, or
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the end of Nov 11?).
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If we are not showing the time then also adjust the end date
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // for multiple-day events.  This is to allow us to display, for
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // example, "Nov 10 -11" for an event with a start date of Nov 10
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // and an end date of Nov 12 at 00:00.
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If the start and end time are the same, then skip this and don't
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // adjust the date.
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isInstant
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && (endDate.hour | endDate.minute | endDate.second) == 0
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && (!showTime || dayDistance <= 1)) {
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endDate.monthDay -= 1;
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endDate.normalize(true /* ignore isDst */);
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startDay = startDate.monthDay;
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startMonthNum = startDate.month;
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startYear = startDate.year;
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int endDay = endDate.monthDay;
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int endMonthNum = endDate.month;
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int endYear = endDate.year;
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startWeekDayString = "";
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endWeekDayString = "";
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showWeekDay) {
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String weekDayFormat = "";
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (abbrevWeekDay) {
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                weekDayFormat = ABBREV_WEEKDAY_FORMAT;
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                weekDayFormat = WEEKDAY_FORMAT;
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startWeekDayString = startDate.format(weekDayFormat);
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endWeekDayString = isInstant ? startWeekDayString : endDate.format(weekDayFormat);
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startTimeString = "";
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endTimeString = "";
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showTime) {
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String startTimeFormat = "";
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String endTimeFormat = "";
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean force24Hour = (flags & FORMAT_24HOUR) != 0;
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean force12Hour = (flags & FORMAT_12HOUR) != 0;
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean use24Hour;
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (force24Hour) {
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                use24Hour = true;
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (force12Hour) {
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                use24Hour = false;
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                use24Hour = DateFormat.is24HourFormat(context);
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (use24Hour) {
127684c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer                startTimeFormat = endTimeFormat =
127784c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer                    res.getString(com.android.internal.R.string.hour_minute_24);
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean abbrevTime = (flags & (FORMAT_ABBREV_TIME | FORMAT_ABBREV_ALL)) != 0;
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean capAMPM = (flags & FORMAT_CAP_AMPM) != 0;
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean noNoon = (flags & FORMAT_NO_NOON) != 0;
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean capNoon = (flags & FORMAT_CAP_NOON) != 0;
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean noMidnight = (flags & FORMAT_NO_MIDNIGHT) != 0;
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean capMidnight = (flags & FORMAT_CAP_MIDNIGHT) != 0;
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean startOnTheHour = startDate.minute == 0 && startDate.second == 0;
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean endOnTheHour = endDate.minute == 0 && endDate.second == 0;
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevTime && startOnTheHour) {
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (capAMPM) {
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.hour_cap_ampm);
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.hour_ampm);
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (capAMPM) {
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.hour_minute_ampm);
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't waste time on setting endTimeFormat when
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we're dealing with an instant, where we'll never
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // need the end point.  (It's the same as the start
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // point)
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!isInstant) {
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (abbrevTime && endOnTheHour) {
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (capAMPM) {
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.hour_cap_ampm);
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.hour_ampm);
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (capAMPM) {
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.hour_minute_ampm);
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (endDate.hour == 12 && endOnTheHour && !noNoon) {
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (capNoon) {
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.Noon);
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.noon);
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (endDate.hour == 0 && endOnTheHour && !noMidnight) {
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (capMidnight) {
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.Midnight);
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.midnight);
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (startDate.hour == 12 && startOnTheHour && !noNoon) {
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (capNoon) {
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.Noon);
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.noon);
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Don't show the start time starting at midnight.  Show
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // 12am instead.
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startTimeString = startDate.format(startTimeFormat);
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endTimeString = isInstant ? startTimeString : endDate.format(endTimeFormat);
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Show the year if the user specified FORMAT_SHOW_YEAR or if
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the starting and end years are different from each other
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // or from the current year.  But don't show the year if the
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // user specified FORMAT_NO_YEAR.
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showYear) {
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // No code... just a comment for clarity.  Keep showYear
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // on, as they enabled it with FORMAT_SHOW_YEAR.  This
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // takes precedence over them setting FORMAT_NO_YEAR.
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (noYear) {
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // They explicitly didn't want a year.
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            showYear = false;
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (startYear != endYear) {
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            showYear = true;
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Show the year if it's not equal to the current year.
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Time currentTime = new Time();
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            currentTime.setToNow();
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            showYear = startYear != currentTime.year;
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String defaultDateFormat, fullFormat, dateRange;
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numericDate) {
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            defaultDateFormat = res.getString(com.android.internal.R.string.numeric_date);
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (showYear) {
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (abbrevMonth) {
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (noMonthDay) {
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_year);
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_day_year);
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (noMonthDay) {
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.month_year);
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.month_day_year);
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (abbrevMonth) {
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (noMonthDay) {
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month);
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_day);
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (noMonthDay) {
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.month);
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.month_day);
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showWeekDay) {
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) {
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.wday1_date1_time1_wday2_date2_time2);
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.wday1_date1_wday2_date2);
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) {
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.date1_time1_date2_time2);
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.date1_date2);
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (noMonthDay && startMonthNum == endMonthNum) {
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Example: "January, 2008"
1420becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format("%s", startDate.format(defaultDateFormat));
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (startYear != endYear || noMonthDay) {
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Different year or we are not showing the month day number.
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Example: "December 31, 2007 - January 1, 2008"
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Or: "January - February, 2008"
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String startDateString = startDate.format(defaultDateFormat);
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String endDateString = endDate.format(defaultDateFormat);
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The values that are used in a fullFormat string are specified
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // by position.
1432becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format(fullFormat,
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startWeekDayString, startDateString, startTimeString,
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endWeekDayString, endDateString, endTimeString);
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get the month, day, and year strings for the start and end dates
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String monthFormat;
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numericDate) {
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            monthFormat = NUMERIC_MONTH_FORMAT;
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (abbrevMonth) {
14425669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer            monthFormat =
14435669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer                res.getString(com.android.internal.R.string.short_format_month);
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            monthFormat = MONTH_FORMAT;
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startMonthString = startDate.format(monthFormat);
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startMonthDayString = startDate.format(MONTH_DAY_FORMAT);
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startYearString = startDate.format(YEAR_FORMAT);
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endMonthString = isInstant ? null : endDate.format(monthFormat);
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endMonthDayString = isInstant ? null : endDate.format(MONTH_DAY_FORMAT);
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endYearString = isInstant ? null : endDate.format(YEAR_FORMAT);
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (startMonthNum != endMonthNum) {
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Same year, different month.
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Example: "October 28 - November 3"
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // or: "Wed, Oct 31 - Sat, Nov 3, 2007"
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // or: "Oct 31, 8am - Sat, Nov 3, 2007, 5pm"
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int index = 0;
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showWeekDay) index = 1;
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showYear) index += 2;
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) index += 4;
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (numericDate) index += 8;
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int resId = sameYearTable[index];
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fullFormat = res.getString(resId);
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The values that are used in a fullFormat string are specified
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // by position.
1471becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format(fullFormat,
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startWeekDayString, startMonthString, startMonthDayString,
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startYearString, startTimeString,
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endWeekDayString, endMonthString, endMonthDayString,
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endYearString, endTimeString);
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (startDay != endDay) {
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Same month, different day.
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int index = 0;
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showWeekDay) index = 1;
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showYear) index += 2;
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) index += 4;
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (numericDate) index += 8;
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int resId = sameMonthTable[index];
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fullFormat = res.getString(resId);
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The values that are used in a fullFormat string are specified
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // by position.
1490becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format(fullFormat,
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startWeekDayString, startMonthString, startMonthDayString,
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startYearString, startTimeString,
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endWeekDayString, endMonthString, endMonthDayString,
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endYearString, endTimeString);
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Same start and end day
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showDate = (flags & FORMAT_SHOW_DATE) != 0;
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If nothing was specified, then show the date.
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!showTime && !showDate && !showWeekDay) showDate = true;
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Compute the time string (example: "10:00 - 11:00 am")
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String timeString = "";
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showTime) {
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the start and end time are the same, then just show the
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // start time.
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isInstant) {
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Same start and end time.
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Example: "10:15 AM"
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                timeString = startTimeString;
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Example: "10:00 - 11:00 am"
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String timeFormat = res.getString(com.android.internal.R.string.time1_time2);
1515becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan                // Don't use the user supplied Formatter because the result will pollute the buffer.
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                timeString = String.format(timeFormat, startTimeString, endTimeString);
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Figure out which full format to use.
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fullFormat = "";
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String dateString = "";
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showDate) {
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dateString = startDate.format(defaultDateFormat);
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showWeekDay) {
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (showTime) {
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Example: "10:00 - 11:00 am, Tue, Oct 9"
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fullFormat = res.getString(com.android.internal.R.string.time_wday_date);
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Example: "Tue, Oct 9"
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fullFormat = res.getString(com.android.internal.R.string.wday_date);
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (showTime) {
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Example: "10:00 - 11:00 am, Oct 9"
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fullFormat = res.getString(com.android.internal.R.string.time_date);
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Example: "Oct 9"
1539becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan                    return formatter.format("%s", dateString);
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (showWeekDay) {
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) {
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Example: "10:00 - 11:00 am, Tue"
15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.time_wday);
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Example: "Tue"
1548becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan                return formatter.format("%s", startWeekDayString);
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (showTime) {
1551becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format("%s", timeString);
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The values that are used in a fullFormat string are specified
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // by position.
1556becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan        return formatter.format(fullFormat, timeString, startWeekDayString, dateString);
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Formats a date or a time according to the local conventions. There are
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * lots of options that allow the caller to control, for example, if the
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * time is shown, if the day of the week is shown, if the month name is
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * abbreviated, if noon is shown instead of 12pm, and so on. For the
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * complete list of options, see the documentation for
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #formatDateRange}.
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example output strings (date formats in these examples are shown using
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the US date format convention but that may change depending on the
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * local settings):
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10:15am</li>
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3:00pm</li>
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3pm</li>
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3PM</li>
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>08:00</li>
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>17:00</li>
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>noon</li>
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Noon</li>
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>midnight</li>
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Midnight</li>
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 31</li>
15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 31, 2007</li>
15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>October 31, 2007</li>
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10am, Oct 31</li>
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>17:00, Oct 31</li>
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wed</li>
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wednesday</li>
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10am, Wed, Oct 31</li>
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wed, Oct 31</li>
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wednesday, Oct 31</li>
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wed, Oct 31, 2007</li>
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wed, October 31</li>
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10/31/2007</li>
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context the context is required only if the time is shown
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param millis a point in time in UTC milliseconds
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags a bit mask of formatting options
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a string containing the formatted date/time.
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String formatDateTime(Context context, long millis, int flags) {
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return formatDateRange(context, millis, millis, flags);
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a relative time string to display the time expressed by millis.  Times
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * are counted starting at midnight, which means that assuming that the current
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * time is March 31st, 0:30:
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>"millis=0:10 today" will be displayed as "0:10"</li>
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>"millis=11:30pm the day before" will be displayed as "Mar 30"</li>
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the given millis is in a different year, then the full date is
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned in numeric format (e.g., "10/12/2008").
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param withPreposition If true, the string returned will include the correct
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * preposition ("at 9:20am", "on 10/12/2008" or "on May 29").
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(Context c, long millis,
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean withPreposition) {
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16226a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        String result;
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long now = System.currentTimeMillis();
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long span = now - millis;
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16266a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        synchronized (DateUtils.class) {
16276a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            if (sNowTime == null) {
16286a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                sNowTime = new Time();
16296a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            }
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16316a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            if (sThenTime == null) {
16326a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                sThenTime = new Time();
16336a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            }
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16356a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            sNowTime.set(now);
16366a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            sThenTime.set(millis);
16376a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques
16386a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            int prepositionId;
16396a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            if (span < DAY_IN_MILLIS && sNowTime.weekDay == sThenTime.weekDay) {
16406a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                // Same day
16416a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                int flags = FORMAT_SHOW_TIME;
16426a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                result = formatDateRange(c, millis, millis, flags);
16436a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                prepositionId = R.string.preposition_for_time;
16446a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            } else if (sNowTime.year != sThenTime.year) {
16456a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                // Different years
16466a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE;
16476a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                result = formatDateRange(c, millis, millis, flags);
16486a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques
16496a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                // This is a date (like "10/31/2008" so use the date preposition)
16506a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                prepositionId = R.string.preposition_for_date;
16516a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            } else {
16526a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                // Default
16536a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH;
16546a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                result = formatDateRange(c, millis, millis, flags);
16556a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                prepositionId = R.string.preposition_for_date;
16566a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            }
16576a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            if (withPreposition) {
16586a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                Resources res = c.getResources();
16596a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                result = res.getString(prepositionId, result);
16606a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            }
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convenience function to return relative time string without preposition.
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param c context for resources
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param millis time in milliseconds
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return {@link CharSequence} containing relative time.
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getRelativeTimeSpanString(Context, long, boolean)
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(Context c, long millis) {
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return getRelativeTimeSpanString(c, millis, false /* no preposition */);
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static Time sNowTime;
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static Time sThenTime;
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1679