DateUtils.java revision 08153ee01e6aa67061f628bc3fed66c6400dfd1c
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
324af85345e798c37ab026e93a1ae250d8bca4fc40Elliott Hughesimport libcore.icu.LocaleData;
334af85345e798c37ab026e93a1ae250d8bca4fc40Elliott Hughes
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class contains various date-related utilities for creating text for things like
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * elapsed time and date ranges, strings for days of the week and months, and AM/PM text etc.
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class DateUtils
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final Object sLock = new Object();
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static Configuration sLastConfig;
425bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer    private static java.text.DateFormat sStatusTimeFormat;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String sElapsedFormatMMSS;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String sElapsedFormatHMMSS;
4599a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String FAST_FORMAT_HMMSS = "%1$d:%2$02d:%3$02d";
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String FAST_FORMAT_MMSS = "%1$02d:%2$02d";
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final char TIME_PADDING = '0';
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final char TIME_SEPARATOR = ':';
5099a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long SECOND_IN_MILLIS = 1000;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
5784c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer    /**
5884c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * This constant is actually the length of 364 days, not of a year!
5984c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     */
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final long YEAR_IN_MILLIS = WEEK_IN_MILLIS * 52;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The following FORMAT_* symbols are used for specifying the format of
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // dates and times in the formatDateRange method.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_SHOW_TIME = 0x00001;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_SHOW_WEEKDAY = 0x00002;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_SHOW_YEAR = 0x00004;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_YEAR = 0x00008;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_SHOW_DATE = 0x00010;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_MONTH_DAY = 0x00020;
70d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_12HOUR = 0x00040;
72d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_24HOUR = 0x00080;
74d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_CAP_AMPM = 0x00100;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_NOON = 0x00200;
77d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_CAP_NOON = 0x00400;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_MIDNIGHT = 0x00800;
80d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_CAP_MIDNIGHT = 0x01000;
82577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    /**
83577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @deprecated Use
84577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
85577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * and pass in {@link Time#TIMEZONE_UTC Time.TIMEZONE_UTC} for the timeZone instead.
86577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     */
87577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    @Deprecated
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_UTC = 0x02000;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_TIME = 0x04000;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_WEEKDAY = 0x08000;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_MONTH = 0x10000;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NUMERIC_DATE = 0x20000;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_RELATIVE = 0x40000;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_ABBREV_ALL = 0x80000;
95d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_CAP_NOON_MIDNIGHT = (FORMAT_CAP_NOON | FORMAT_CAP_MIDNIGHT);
97d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int FORMAT_NO_NOON_MIDNIGHT = (FORMAT_NO_NOON | FORMAT_NO_MIDNIGHT);
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Date and time format strings that are constant and don't need to be
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // translated.
10284c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer    /**
10384c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * This is not actually the preferred 24-hour date format in all locales.
104d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
10584c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     */
106d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String HOUR_MINUTE_24 = "%H:%M";
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String MONTH_FORMAT = "%B";
1095669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer    /**
1105669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer     * This is not actually a useful month name in all locales.
111d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
1125669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer     */
113d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String ABBREV_MONTH_FORMAT = "%b";
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String NUMERIC_MONTH_FORMAT = "%m";
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String MONTH_DAY_FORMAT = "%-d";
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String YEAR_FORMAT = "%Y";
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String YEAR_FORMAT_TWO_DIGITS = "%g";
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String WEEKDAY_FORMAT = "%A";
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final String ABBREV_WEEKDAY_FORMAT = "%a";
12199a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This table is used to lookup the resource string id of a format string
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // used for formatting a start and end date that fall in the same year.
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The index is constructed from a bit-wise OR of the boolean values:
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // {showTime, showYear, showWeekDay}.  For example, if showYear and
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // showWeekDay are both true, then the index would be 3.
127d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    /** @deprecated do not use. */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int sameYearTable[] = {
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_md1_md2,
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_wday1_md1_wday2_md2,
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_mdy1_mdy2,
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_wday1_mdy1_wday2_mdy2,
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_md1_time1_md2_time2,
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_wday1_md1_time1_wday2_md2_time2,
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_mdy1_time1_mdy2_time2,
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_year_wday1_mdy1_time1_wday2_mdy2_time2,
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Numeric date strings
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_md1_md2,
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_md1_wday2_md2,
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_mdy1_mdy2,
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_mdy1_wday2_mdy2,
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_md1_time1_md2_time2,
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_md1_time1_wday2_md2_time2,
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_mdy1_time1_mdy2_time2,
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_mdy1_time1_wday2_mdy2_time2,
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
14899a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This table is used to lookup the resource string id of a format string
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // used for formatting a start and end date that fall in the same month.
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // The index is constructed from a bit-wise OR of the boolean values:
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // {showTime, showYear, showWeekDay}.  For example, if showYear and
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // showWeekDay are both true, then the index would be 3.
154d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    /** @deprecated do not use. */
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int sameMonthTable[] = {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_md1_md2,
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_wday1_md1_wday2_md2,
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_mdy1_mdy2,
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_wday1_mdy1_wday2_mdy2,
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_md1_time1_md2_time2,
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_wday1_md1_time1_wday2_md2_time2,
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_mdy1_time1_mdy2_time2,
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.same_month_wday1_mdy1_time1_wday2_mdy2_time2,
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_md1_md2,
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_md1_wday2_md2,
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_mdy1_mdy2,
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_mdy1_wday2_mdy2,
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_md1_time1_md2_time2,
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_md1_time1_wday2_md2_time2,
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_mdy1_time1_mdy2_time2,
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.string.numeric_wday1_mdy1_time1_wday2_mdy2_time2,
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request the full spelled-out name. For use with the 'abbrev' parameter of
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getDayOfWeekString} and {@link #getMonthString}.
17899a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @more <p>
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *       e.g. "Sunday" or "January"
181d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
183d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_LONG = 10;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request an abbreviated version of the name. For use with the 'abbrev'
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
18999a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @more <p>
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *       e.g. "Sun" or "Jan"
192d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
194d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_MEDIUM = 20;
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request a shorter abbreviated version of the name.
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @more
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>e.g. "Su" or "Jan"
2025bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * <p>In most languages, the results returned for LENGTH_SHORT will be the same as
2035bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * the results returned for {@link #LENGTH_MEDIUM}.
204d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
206d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_SHORT = 30;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request an even shorter abbreviated version of the name.
2115bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * Do not use this.  Currently this will always return the same result
2125bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * as {@link #LENGTH_SHORT}.
213d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
215d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_SHORTER = 40;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Request an even shorter abbreviated version of the name.
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * For use with the 'abbrev' parameter of {@link #getDayOfWeekString} and {@link #getMonthString}.
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @more
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>e.g. "S", "T", "T" or "J"
2235bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * <p>In some languages, the results returned for LENGTH_SHORTEST will be the same as
2245bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * the results returned for {@link #LENGTH_SHORT}.
225d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
227d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LENGTH_SHORTEST = 50;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a string for the day of the week.
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dayOfWeek One of {@link Calendar#SUNDAY Calendar.SUNDAY},
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               {@link Calendar#MONDAY Calendar.MONDAY}, etc.
2345bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_SHORT},
2355bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               {@link #LENGTH_MEDIUM}, or {@link #LENGTH_SHORTEST}.
2365bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               Note that in most languages, {@link #LENGTH_SHORT}
2375bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               will return the same as {@link #LENGTH_MEDIUM}.
2385bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               Undefined lengths will return {@link #LENGTH_MEDIUM}
2395bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               but may return something different in the future.
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IndexOutOfBoundsException if the dayOfWeek is out of bounds.
241d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
243d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String getDayOfWeekString(int dayOfWeek, int abbrev) {
24508153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        LocaleData d = LocaleData.get(Locale.getDefault());
24608153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        String[] names;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (abbrev) {
24808153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_LONG:       names = d.longWeekdayNames;  break;
24908153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_MEDIUM:     names = d.shortWeekdayNames; break;
25008153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_SHORT:      names = d.shortWeekdayNames; break; // TODO
25108153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_SHORTER:    names = d.shortWeekdayNames; break; // TODO
25208153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_SHORTEST:   names = d.tinyWeekdayNames;  break;
25308153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            default:                names = d.shortWeekdayNames; break;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25508153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        return names[dayOfWeek];
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a localized string for AM or PM.
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param ampm Either {@link Calendar#AM Calendar.AM} or {@link Calendar#PM Calendar.PM}.
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IndexOutOfBoundsException if the ampm is out of bounds.
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Localized version of "AM" or "PM".
263d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
265d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String getAMPMString(int ampm) {
2674af85345e798c37ab026e93a1ae250d8bca4fc40Elliott Hughes        return LocaleData.get(Locale.getDefault()).amPm[ampm - Calendar.AM];
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2715bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * Return a localized string for the month of the year.
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param month One of {@link Calendar#JANUARY Calendar.JANUARY},
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
2745bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_MEDIUM},
2755bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               or {@link #LENGTH_SHORTEST}.
2765bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               Undefined lengths will return {@link #LENGTH_MEDIUM}
2775bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               but may return something different in the future.
2785bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @return Localized month of the year.
279d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
281d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String getMonthString(int month, int abbrev) {
28308153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER.
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This is a shortcut to not spam the translators with too many variations
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // of the same string.  If we find that in a language the distinction
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // is necessary, we can can add more without changing this API.
28708153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        LocaleData d = LocaleData.get(Locale.getDefault());
28808153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        String[] names;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (abbrev) {
29008153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_LONG:       names = d.longMonthNames;  break;
29108153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_MEDIUM:     names = d.shortMonthNames; break;
29208153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_SHORT:      names = d.shortMonthNames; break;
29308153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_SHORTER:    names = d.shortMonthNames; break;
29408153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_SHORTEST:   names = d.tinyMonthNames;  break;
29508153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            default:                names = d.shortMonthNames; break;
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
29708153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        return names[month];
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3015bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * Return a localized string for the month of the year, for
3025bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * contexts where the month is not formatted together with
3035bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * a day of the month.
3045bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *
3055bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @param month One of {@link Calendar#JANUARY Calendar.JANUARY},
3065bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
3075bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_MEDIUM},
3085bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               or {@link #LENGTH_SHORTEST}.
3095bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               Undefined lengths will return {@link #LENGTH_MEDIUM}
3105bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     *               but may return something different in the future.
3115bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @return Localized month of the year.
3125bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     * @hide Pending API council approval
313d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes     * @deprecated use {@link java.text.SimpleDateFormat} instead.
3145bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer     */
315d3c01012d8d329e541214e8207272ab5cc9ca004Elliott Hughes    @Deprecated
3165bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer    public static String getStandaloneMonthString(int month, int abbrev) {
31708153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER.
3185bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        // This is a shortcut to not spam the translators with too many variations
3195bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        // of the same string.  If we find that in a language the distinction
3205bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        // is necessary, we can can add more without changing this API.
32108153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        LocaleData d = LocaleData.get(Locale.getDefault());
32208153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        String[] names;
3235bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        switch (abbrev) {
32408153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_LONG:       names = d.longStandAloneMonthNames;
3255bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer                                                            break;
32608153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_MEDIUM:     names = d.shortMonthNames; break;
32708153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_SHORT:      names = d.shortMonthNames; break;
32808153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_SHORTER:    names = d.shortMonthNames; break;
32908153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            case LENGTH_SHORTEST:   names = d.tinyMonthNames;  break;
33008153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes            default:                names = d.shortMonthNames; break;
3315bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer        }
33208153ee01e6aa67061f628bc3fed66c6400dfd1cElliott Hughes        return names[month];
3335bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer    }
3345bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer
3355bd644caf73e76750feef1a82b8817d32f5367fcEric Fischer    /**
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a string describing the elapsed time since startTime.
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param startTime some time in the past.
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a String object containing the elapsed time.
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getRelativeTimeSpanString(long, long, long)
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(long startTime) {
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return getRelativeTimeSpanString(startTime, System.currentTimeMillis(), MINUTE_IN_MILLIS);
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a string describing 'time' as a time relative to 'now'.
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time spans in the past are formatted like "42 minutes ago".
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time spans in the future are formatted like "in 42 minutes".
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param time the time to describe, in milliseconds
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param now the current time in milliseconds
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param minResolution the minimum timespan to report. For example, a time 3 seconds in the
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     past will be reported as "0 minutes ago" if this is set to MINUTE_IN_MILLIS. Pass one of
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *     0, MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS, WEEK_IN_MILLIS
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution) {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_ABBREV_MONTH;
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return getRelativeTimeSpanString(time, now, minResolution, flags);
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a string describing 'time' as a time relative to 'now'.
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time spans in the past are formatted like "42 minutes ago". Time spans in
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the future are formatted like "in 42 minutes".
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Can use {@link #FORMAT_ABBREV_RELATIVE} flag to use abbreviated relative
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * times, like "42 mins ago".
37099a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param time the time to describe, in milliseconds
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param now the current time in milliseconds
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param minResolution the minimum timespan to report. For example, a time
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            3 seconds in the past will be reported as "0 minutes ago" if
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            this is set to MINUTE_IN_MILLIS. Pass one of 0,
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            MINUTE_IN_MILLIS, HOUR_IN_MILLIS, DAY_IN_MILLIS,
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            WEEK_IN_MILLIS
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags a bit mask of formatting options, such as
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #FORMAT_NUMERIC_DATE} or
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #FORMAT_ABBREV_RELATIVE}
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(long time, long now, long minResolution,
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int flags) {
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources r = Resources.getSystem();
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean abbrevRelative = (flags & (FORMAT_ABBREV_RELATIVE | FORMAT_ABBREV_ALL)) != 0;
38699a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean past = (now >= time);
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long duration = Math.abs(now - time);
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int resId;
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long count;
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (duration < MINUTE_IN_MILLIS && minResolution < MINUTE_IN_MILLIS) {
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count = duration / SECOND_IN_MILLIS;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_num_seconds_ago;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.num_seconds_ago;
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_in_num_seconds;
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.in_num_seconds;
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (duration < HOUR_IN_MILLIS && minResolution < HOUR_IN_MILLIS) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count = duration / MINUTE_IN_MILLIS;
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_num_minutes_ago;
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.num_minutes_ago;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_in_num_minutes;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.in_num_minutes;
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (duration < DAY_IN_MILLIS && minResolution < DAY_IN_MILLIS) {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count = duration / HOUR_IN_MILLIS;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_num_hours_ago;
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.num_hours_ago;
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_in_num_hours;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.in_num_hours;
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) {
4386a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            count = getNumberOfDaysPassed(time, now);
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_num_days_ago;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.num_days_ago;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevRelative) {
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.abbrev_in_num_days;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    resId = com.android.internal.R.plurals.in_num_days;
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // We know that we won't be showing the time, so it is safe to pass
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // in a null context.
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return formatDateRange(null, time, time, flags);
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String format = r.getQuantityString(resId, (int) count);
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String.format(format, count);
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
46199a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4636a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     * Returns the number of days passed between two dates.
4646a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     *
4656a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     * @param date1 first date
4666a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     * @param date2 second date
4676a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     * @return number of days passed between to dates.
4686a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques     */
4696a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques    private synchronized static long getNumberOfDaysPassed(long date1, long date2) {
4706a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        if (sThenTime == null) {
4716a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            sThenTime = new Time();
4726a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        }
4736a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        sThenTime.set(date1);
4746a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        int day1 = Time.getJulianDay(date1, sThenTime.gmtoff);
4756a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        sThenTime.set(date2);
4766a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        int day2 = Time.getJulianDay(date2, sThenTime.gmtoff);
4776a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        return Math.abs(day2 - day1);
4786a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques    }
4796a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques
4806a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques    /**
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return string describing the elapsed time since startTime formatted like
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "[relative time/date], [time]".
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example output strings for the US date format.
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>3 mins ago, 10:15 AM</li>
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>yesterday, 12:20 PM</li>
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>Dec 12, 4:12 AM</li>
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <li>11/14/2007, 8:20 AM</li>
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
49199a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param time some time in the past.
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param minResolution the minimum elapsed time (in milliseconds) to report
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            when showing relative times. For example, a time 3 seconds in
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            the past will be reported as "0 minutes ago" if this is set to
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            {@link #MINUTE_IN_MILLIS}.
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param transitionResolution the elapsed time (in milliseconds) at which
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            to stop reporting relative measurements. Elapsed times greater
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            than this resolution will default to normal date formatting.
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            For example, will transition from "6 days ago" to "Dec 12"
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            when using {@link #WEEK_IN_MILLIS}.
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeDateTimeString(Context c, long time, long minResolution,
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long transitionResolution, int flags) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources r = Resources.getSystem();
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long now = System.currentTimeMillis();
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long duration = Math.abs(now - time);
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // getRelativeTimeSpanString() doesn't correctly format relative dates
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // above a week or exact dates below a day, so clamp
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // transitionResolution as needed.
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (transitionResolution > WEEK_IN_MILLIS) {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            transitionResolution = WEEK_IN_MILLIS;
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (transitionResolution < DAY_IN_MILLIS) {
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            transitionResolution = DAY_IN_MILLIS;
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CharSequence timeClause = formatDateRange(c, time, time, FORMAT_SHOW_TIME);
52099a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String result;
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (duration < transitionResolution) {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CharSequence relativeClause = getRelativeTimeSpanString(time, now, minResolution, flags);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = r.getString(com.android.internal.R.string.relative_time, relativeClause, timeClause);
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CharSequence dateClause = getRelativeTimeSpanString(c, time, false);
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = r.getString(com.android.internal.R.string.date_time, dateClause, timeClause);
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a string describing a day relative to the current day. For example if the day is
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * today this function returns "Today", if the day was a week ago it returns "7 days ago", and
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if the day is in 2 weeks it returns "in 14 days".
53799a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param r the resources to get the strings from
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param day the relative day to describe in UTC milliseconds
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param today the current time in UTC milliseconds
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a formatting string
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String getRelativeDayString(Resources r, long day, long today) {
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Time startTime = new Time();
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        startTime.set(day);
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Time currentTime = new Time();
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        currentTime.set(today);
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startDay = Time.getJulianDay(day, startTime.gmtoff);
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int currentDay = Time.getJulianDay(today, currentTime.gmtoff);
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int days = Math.abs(currentDay - startDay);
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean past = (today > day);
55499a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (days == 1) {
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (past) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return r.getString(com.android.internal.R.string.yesterday);
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return r.getString(com.android.internal.R.string.tomorrow);
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (days == 0) {
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return r.getString(com.android.internal.R.string.today);
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int resId;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (past) {
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resId = com.android.internal.R.plurals.num_days_ago;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resId = com.android.internal.R.plurals.in_num_days;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
57199a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String format = r.getQuantityString(resId, days);
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return String.format(format, days);
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void initFormatStrings() {
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (sLock) {
57825d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            initFormatStringsLocked();
57925d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        }
58025d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK    }
58125d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK
58225d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK    private static void initFormatStringsLocked() {
58325d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        Resources r = Resources.getSystem();
58425d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        Configuration cfg = r.getConfiguration();
58525d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        if (sLastConfig == null || !sLastConfig.equals(cfg)) {
58625d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            sLastConfig = cfg;
58725d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            sStatusTimeFormat = java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT);
58825d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss);
58925d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss);
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Format a time so it appears like it would in the status bar clock.
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link #DateFormat.getTimeFormat(Context)} instead.
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final CharSequence timeString(long millis) {
59925d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        synchronized (sLock) {
60025d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            initFormatStringsLocked();
60125d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK            return sStatusTimeFormat.format(millis);
60225d8b05fb77e8ee755aacd27c1c2d3b237537b7aJozef BABJAK        }
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Formats an elapsed time in the form "MM:SS" or "H:MM:SS"
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for display on the call-in-progress screen.
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param elapsedSeconds the elapsed time in seconds.
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String formatElapsedTime(long elapsedSeconds) {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return formatElapsedTime(null, elapsedSeconds);
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
61399a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Formats an elapsed time in the form "MM:SS" or "H:MM:SS"
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for display on the call-in-progress screen.
61799a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param recycle {@link StringBuilder} to recycle, if possible
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param elapsedSeconds the elapsed time in seconds.
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String formatElapsedTime(StringBuilder recycle, long elapsedSeconds) {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        initFormatStrings();
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long hours = 0;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long minutes = 0;
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long seconds = 0;
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (elapsedSeconds >= 3600) {
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            hours = elapsedSeconds / 3600;
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            elapsedSeconds -= hours * 3600;
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (elapsedSeconds >= 60) {
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            minutes = elapsedSeconds / 60;
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            elapsedSeconds -= minutes * 60;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        seconds = elapsedSeconds;
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String result;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hours > 0) {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return formatElapsedTime(recycle, sElapsedFormatHMMSS, hours, minutes, seconds);
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return formatElapsedTime(recycle, sElapsedFormatMMSS, minutes, seconds);
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fast formatting of h:mm:ss
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String formatElapsedTime(StringBuilder recycle, String format, long hours,
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long minutes, long seconds) {
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (FAST_FORMAT_HMMSS.equals(format)) {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            StringBuilder sb = recycle;
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sb == null) {
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb = new StringBuilder(8);
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.setLength(0);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(hours);
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(TIME_SEPARATOR);
66099a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson            if (minutes < 10) {
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(TIME_PADDING);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(toDigitChar(minutes / 10));
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(toDigitChar(minutes % 10));
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(TIME_SEPARATOR);
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (seconds < 10) {
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(TIME_PADDING);
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(toDigitChar(seconds / 10));
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(toDigitChar(seconds % 10));
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sb.toString();
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String.format(format, hours, minutes, seconds);
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fast formatting of m:ss
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static String formatElapsedTime(StringBuilder recycle, String format, long minutes,
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long seconds) {
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (FAST_FORMAT_MMSS.equals(format)) {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            StringBuilder sb = recycle;
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sb == null) {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb = new StringBuilder(8);
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.setLength(0);
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
69199a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson            if (minutes < 10) {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(TIME_PADDING);
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(toDigitChar(minutes / 10));
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(toDigitChar(minutes % 10));
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(TIME_SEPARATOR);
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (seconds < 10) {
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(TIME_PADDING);
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sb.append(toDigitChar(seconds / 10));
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.append(toDigitChar(seconds % 10));
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return sb.toString();
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return String.format(format, minutes, seconds);
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static char toDigitChar(long digit) {
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (char) (digit + '0');
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
71399a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Format a date / time such that if the then is on the same day as now, it shows
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * just the time and if it's a different day, it shows just the date.
71799a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The parameters dateFormat and timeFormat should each be one of
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#DEFAULT},
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#FULL},
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#LONG},
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#MEDIUM}
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link java.text.DateFormat#SHORT}
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param then the date to format
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param now the base time
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dateStyle how to format the date portion.
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param timeStyle how to format the time portion.
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final CharSequence formatSameDayTime(long then, long now,
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int dateStyle, int timeStyle) {
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Calendar thenCal = new GregorianCalendar();
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        thenCal.setTimeInMillis(then);
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Date thenDate = thenCal.getTime();
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Calendar nowCal = new GregorianCalendar();
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nowCal.setTimeInMillis(now);
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        java.text.DateFormat f;
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (thenCal.get(Calendar.YEAR) == nowCal.get(Calendar.YEAR)
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && thenCal.get(Calendar.MONTH) == nowCal.get(Calendar.MONTH)
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && thenCal.get(Calendar.DAY_OF_MONTH) == nowCal.get(Calendar.DAY_OF_MONTH)) {
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f = java.text.DateFormat.getTimeInstance(timeStyle);
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            f = java.text.DateFormat.getDateInstance(dateStyle);
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return f.format(thenDate);
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Calendar newCalendar(boolean zulu)
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (zulu)
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return Calendar.getInstance(TimeZone.getTimeZone("GMT"));
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Calendar.getInstance();
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the supplied when is today else false
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isToday(long when) {
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Time time = new Time();
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        time.set(when);
76999a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int thenYear = time.year;
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int thenMonth = time.month;
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int thenMonthDay = time.monthDay;
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        time.set(System.currentTimeMillis());
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (thenYear == time.year)
77699a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson                && (thenMonth == time.month)
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (thenMonthDay == time.monthDay);
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return true if this date string is local time
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isUTC(String s)
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (s.length() == 16 && s.charAt(15) == 'Z') {
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (s.length() == 9 && s.charAt(8) == 'Z') {
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // XXX not sure if this case possible/valid
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a string containing the date and time in RFC2445 format.
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Ensures that the time is written in UTC.  The Calendar class doesn't
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * really help out with this, so this is slower than it ought to be.
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cal the date and time to write
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String writeDateTime(Calendar cal)
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TimeZone tz = TimeZone.getTimeZone("GMT");
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        GregorianCalendar c = new GregorianCalendar(tz);
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        c.setTimeInMillis(cal.getTimeInMillis());
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return writeDateTime(c, true);
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a string containing the date and time in RFC2445 format.
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cal the date and time to write
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param zulu If the calendar is in UTC, pass true, and a Z will
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be written at the end as per RFC2445.  Otherwise, the time is
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * considered in localtime.
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String writeDateTime(Calendar cal, boolean zulu)
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        StringBuilder sb = new StringBuilder();
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.ensureCapacity(16);
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (zulu) {
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.setLength(16);
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.setCharAt(15, 'Z');
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sb.setLength(15);
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return writeDateTime(cal, sb);
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a string containing the date and time in RFC2445 format.
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cal the date and time to write
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sb a StringBuilder to use.  It is assumed that setLength
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *           has already been called on sb to the appropriate length
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *           which is sb.setLength(zulu ? 16 : 15)
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String writeDateTime(Calendar cal, StringBuilder sb)
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int n;
85099a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.YEAR);
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(3, (char)('0'+n%10));
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(2, (char)('0'+n%10));
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(1, (char)('0'+n%10));
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(0, (char)('0'+n%10));
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.MONTH) + 1;
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(5, (char)('0'+n%10));
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(4, (char)('0'+n%10));
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.DAY_OF_MONTH);
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(7, (char)('0'+n%10));
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(6, (char)('0'+n%10));
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(8, 'T');
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.HOUR_OF_DAY);
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(10, (char)('0'+n%10));
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(9, (char)('0'+n%10));
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.MINUTE);
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(12, (char)('0'+n%10));
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(11, (char)('0'+n%10));
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n = cal.get(Calendar.SECOND);
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(14, (char)('0'+n%10));
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        n /= 10;
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sb.setCharAt(13, (char)('0'+n%10));
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sb.toString();
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @deprecated use {@link android.text.format.Time}
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void assign(Calendar lval, Calendar rval)
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // there should be a faster way.
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lval.clear();
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lval.setTimeInMillis(rval.getTimeInMillis());
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Formats a date or a time range according to the local conventions.
903becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * <p>
904becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * Note that this is a convenience method. Using it involves creating an
905becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * internal {@link java.util.Formatter} instance on-the-fly, which is
906becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * somewhat costly in terms of memory and time. This is probably acceptable
907becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * if you use the method only rarely, but if you rely on it for formatting a
908becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * large number of dates, consider creating and reusing your own
909becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * {@link java.util.Formatter} instance and use the version of
910becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * {@link #formatDateRange(Context, long, long, int) formatDateRange}
911becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * that takes a {@link java.util.Formatter}.
912577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     *
913becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param context the context is required only if the time is shown
914becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param startMillis the start time in UTC milliseconds
915becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param endMillis the end time in UTC milliseconds
916becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param flags a bit mask of options See
917577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
918becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @return a string containing the formatted date/time range.
919becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     */
920becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan    public static String formatDateRange(Context context, long startMillis,
921becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            long endMillis, int flags) {
922becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan        Formatter f = new Formatter(new StringBuilder(50), Locale.getDefault());
923becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan        return formatDateRange(context, f, startMillis, endMillis, flags).toString();
924becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan    }
925becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan
926becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan    /**
927becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * Formats a date or a time range according to the local conventions.
928577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * <p>
929577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * Note that this is a convenience method for formatting the date or
930577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * time range in the local time zone. If you want to specify the time
931577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * zone please use
932577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}.
933577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     *
934577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param context the context is required only if the time is shown
935577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param formatter the Formatter used for formatting the date range.
936577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * Note: be sure to call setLength(0) on StringBuilder passed to
937577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * the Formatter constructor unless you want the results to accumulate.
938577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param startMillis the start time in UTC milliseconds
939577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param endMillis the end time in UTC milliseconds
940577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param flags a bit mask of options See
941577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * {@link #formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
942577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @return a string containing the formatted date/time range.
943577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     */
944577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
945577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            long endMillis, int flags) {
946577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        return formatDateRange(context, formatter, startMillis, endMillis, flags, null);
947577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    }
948577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik
949577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik    /**
950577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * Formats a date or a time range according to the local conventions.
95199a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example output strings (date formats in these examples are shown using
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the US date format convention but that may change depending on the
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * local settings):
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10:15am</li>
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3:00pm - 4:00pm</li>
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3pm - 4pm</li>
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3PM - 4PM</li>
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>08:00 - 17:00</li>
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 9</li>
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Tue, Oct 9</li>
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>October 9, 2007</li>
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 9 - 10</li>
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 9 - 10, 2007</li>
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 28 - Nov 3, 2007</li>
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Dec 31, 2007 - Jan 1, 2008</li>
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 9, 8:00am - Oct 10, 5:00pm</li>
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>12/31/2007 - 01/01/2008</li>
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
97299a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The flags argument is a bitmask of options from the following list:
97599a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_SHOW_TIME</li>
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_SHOW_WEEKDAY</li>
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_SHOW_YEAR</li>
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NO_YEAR</li>
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_SHOW_DATE</li>
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NO_MONTH_DAY</li>
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_12HOUR</li>
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_24HOUR</li>
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_CAP_AMPM</li>
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NO_NOON</li>
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_CAP_NOON</li>
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NO_MIDNIGHT</li>
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_CAP_MIDNIGHT</li>
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_UTC</li>
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_ABBREV_TIME</li>
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_ABBREV_WEEKDAY</li>
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_ABBREV_MONTH</li>
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_ABBREV_ALL</li>
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>FORMAT_NUMERIC_DATE</li>
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
99799a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_SHOW_TIME is set, the time is shown as part of the date range.
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the start and end time are the same, then just the start time is
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown.
100299a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_SHOW_WEEKDAY is set, then the weekday is shown.
100599a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_SHOW_YEAR is set, then the year is always shown.
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NO_YEAR is set, then the year is not shown.
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If neither FORMAT_SHOW_YEAR nor FORMAT_NO_YEAR are set, then the year
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is shown only if it is different from the current year, or if the start
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and end dates fall on different years.  If both are set,
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * FORMAT_SHOW_YEAR takes precedence.
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Normally the date is shown unless the start and end day are the same.
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_SHOW_DATE is set, then the date is always shown, even for
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same day ranges.
101899a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NO_MONTH_DAY is set, then if the date is shown, just the
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * month name will be shown, not the day of the month.  For example,
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * "January, 2008" instead of "January 6 - 12, 2008".
102399a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_CAP_AMPM is set and 12-hour time is used, then the "AM"
102684c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * and "PM" are capitalized.  You should not use this flag
102784c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * because in some locales these terms cannot be capitalized, and in
102884c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * many others it doesn't make sense to do so even though it is possible.
102999a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NO_NOON is set and 12-hour time is used, then "12pm" is
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown instead of "noon".
103399a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_CAP_NOON is set and 12-hour time is used, then "Noon" is
103684c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * shown instead of "noon".  You should probably not use this flag
103784c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * because in many locales it will not make sense to capitalize
103884c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * the term.
103999a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NO_MIDNIGHT is set and 12-hour time is used, then "12am" is
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown instead of "midnight".
104399a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
104584c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * If FORMAT_CAP_MIDNIGHT is set and 12-hour time is used, then "Midnight"
104684c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * is shown instead of "midnight".  You should probably not use this
104784c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * flag because in many locales it will not make sense to capitalize
104884c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer     * the term.
104999a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_12HOUR is set and the time is shown, then the time is
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown in the 12-hour time format. You should not normally set this.
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Instead, let the time format be chosen automatically according to the
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * FORMAT_24HOUR takes precedence.
105699a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_24HOUR is set and the time is shown, then the time is
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * shown in the 24-hour time format. You should not normally set this.
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Instead, let the time format be chosen automatically according to the
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * system settings. If both FORMAT_12HOUR and FORMAT_24HOUR are set, then
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * FORMAT_24HOUR takes precedence.
106399a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
1065577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * If FORMAT_UTC is set, then the UTC time zone is used for the start
1066577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * and end milliseconds unless a time zone is specified. If a time zone
1067577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * is specified it will be used regardless of the FORMAT_UTC flag.
106899a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_ABBREV_TIME is set and 12-hour time format is used, then the
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * start and end times (if shown) are abbreviated by not showing the minutes
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if they are zero.  For example, instead of "3:00pm" the time would be
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * abbreviated to "3pm".
107499a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_ABBREV_WEEKDAY is set, then the weekday (if shown) is
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * abbreviated to a 3-letter string.
107899a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_ABBREV_MONTH is set, then the month (if shown) is abbreviated
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to a 3-letter string.
108299a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_ABBREV_ALL is set, then the weekday and the month (if shown)
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * are abbreviated to 3-letter strings.
108699a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If FORMAT_NUMERIC_DATE is set, then the date is shown in numeric format
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of using the name of the month.  For example, "12/31/2008"
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * instead of "December 31, 2008".
109199a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
109299a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     * <p>
109399a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     * If the end date ends at 12:00am at the beginning of a day, it is
109499a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     * formatted as the end of the previous day in two scenarios:
109599a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     * <ul>
109699a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *   <li>For single day events. This results in "8pm - midnight" instead of
109799a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *       "Nov 10, 8pm - Nov 11, 12am".</li>
109899a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *   <li>When the time is not displayed. This results in "Nov 10 - 11" for
109999a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *       an event with a start date of Nov 10 and an end date of Nov 12 at
110099a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *       00:00.</li>
110199a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     * </ul>
110299a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context the context is required only if the time is shown
1104becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @param formatter the Formatter used for formatting the date range.
1105becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * Note: be sure to call setLength(0) on StringBuilder passed to
1106becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * the Formatter constructor unless you want the results to accumulate.
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param startMillis the start time in UTC milliseconds
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param endMillis the end time in UTC milliseconds
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags a bit mask of options
1110577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * @param timeZone the time zone to compute the string in. Use null for local
1111577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik     * or if the FORMAT_UTC flag is being used.
111299a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
1113becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan     * @return the formatter with the formatted date/time range appended to the string buffer.
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1115becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan    public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
1116577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            long endMillis, int flags, String timeZone) {
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Resources res = Resources.getSystem();
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showTime = (flags & FORMAT_SHOW_TIME) != 0;
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showWeekDay = (flags & FORMAT_SHOW_WEEKDAY) != 0;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showYear = (flags & FORMAT_SHOW_YEAR) != 0;
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean noYear = (flags & FORMAT_NO_YEAR) != 0;
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean useUTC = (flags & FORMAT_UTC) != 0;
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean abbrevWeekDay = (flags & (FORMAT_ABBREV_WEEKDAY | FORMAT_ABBREV_ALL)) != 0;
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean abbrevMonth = (flags & (FORMAT_ABBREV_MONTH | FORMAT_ABBREV_ALL)) != 0;
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean noMonthDay = (flags & FORMAT_NO_MONTH_DAY) != 0;
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean numericDate = (flags & FORMAT_NUMERIC_DATE) != 0;
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If we're getting called with a single instant in time (from
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // e.g. formatDateTime(), below), then we can skip a lot of
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // computation below that'd otherwise be thrown out.
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isInstant = (startMillis == endMillis);
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1133577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        Time startDate;
1134577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        if (timeZone != null) {
1135577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            startDate = new Time(timeZone);
1136577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        } else if (useUTC) {
1137577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            startDate = new Time(Time.TIMEZONE_UTC);
1138577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        } else {
1139577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            startDate = new Time();
1140577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik        }
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        startDate.set(startMillis);
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Time endDate;
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int dayDistance;
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isInstant) {
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endDate = startDate;
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dayDistance = 0;
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1149577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            if (timeZone != null) {
1150577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik                endDate = new Time(timeZone);
1151577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            } else if (useUTC) {
1152577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik                endDate = new Time(Time.TIMEZONE_UTC);
1153577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            } else {
1154577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik                endDate = new Time();
1155577ec9eb3a661de96a2cbe9ec918eda082fb7659Erik            }
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endDate.set(endMillis);
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int startJulianDay = Time.getJulianDay(startMillis, startDate.gmtoff);
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int endJulianDay = Time.getJulianDay(endMillis, endDate.gmtoff);
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dayDistance = endJulianDay - startJulianDay;
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isInstant
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && (endDate.hour | endDate.minute | endDate.second) == 0
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            && (!showTime || dayDistance <= 1)) {
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endDate.monthDay -= 1;
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endDate.normalize(true /* ignore isDst */);
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startDay = startDate.monthDay;
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startMonthNum = startDate.month;
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startYear = startDate.year;
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int endDay = endDate.monthDay;
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int endMonthNum = endDate.month;
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int endYear = endDate.year;
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startWeekDayString = "";
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endWeekDayString = "";
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showWeekDay) {
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String weekDayFormat = "";
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (abbrevWeekDay) {
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                weekDayFormat = ABBREV_WEEKDAY_FORMAT;
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                weekDayFormat = WEEKDAY_FORMAT;
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startWeekDayString = startDate.format(weekDayFormat);
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endWeekDayString = isInstant ? startWeekDayString : endDate.format(weekDayFormat);
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startTimeString = "";
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endTimeString = "";
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showTime) {
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String startTimeFormat = "";
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String endTimeFormat = "";
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean force24Hour = (flags & FORMAT_24HOUR) != 0;
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean force12Hour = (flags & FORMAT_12HOUR) != 0;
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean use24Hour;
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (force24Hour) {
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                use24Hour = true;
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (force12Hour) {
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                use24Hour = false;
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                use24Hour = DateFormat.is24HourFormat(context);
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (use24Hour) {
120684c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer                startTimeFormat = endTimeFormat =
120784c863d9af1270a2ccd2ccd2b8c1a753826dfe6dEric Fischer                    res.getString(com.android.internal.R.string.hour_minute_24);
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean abbrevTime = (flags & (FORMAT_ABBREV_TIME | FORMAT_ABBREV_ALL)) != 0;
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean capAMPM = (flags & FORMAT_CAP_AMPM) != 0;
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean noNoon = (flags & FORMAT_NO_NOON) != 0;
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean capNoon = (flags & FORMAT_CAP_NOON) != 0;
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean noMidnight = (flags & FORMAT_NO_MIDNIGHT) != 0;
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean capMidnight = (flags & FORMAT_CAP_MIDNIGHT) != 0;
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean startOnTheHour = startDate.minute == 0 && startDate.second == 0;
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean endOnTheHour = endDate.minute == 0 && endDate.second == 0;
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (abbrevTime && startOnTheHour) {
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (capAMPM) {
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.hour_cap_ampm);
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.hour_ampm);
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (capAMPM) {
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.hour_minute_ampm);
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Don't waste time on setting endTimeFormat when
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we're dealing with an instant, where we'll never
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // need the end point.  (It's the same as the start
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // point)
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!isInstant) {
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (abbrevTime && endOnTheHour) {
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (capAMPM) {
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.hour_cap_ampm);
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.hour_ampm);
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (capAMPM) {
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.hour_minute_cap_ampm);
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.hour_minute_ampm);
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (endDate.hour == 12 && endOnTheHour && !noNoon) {
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (capNoon) {
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.Noon);
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.noon);
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (endDate.hour == 0 && endOnTheHour && !noMidnight) {
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (capMidnight) {
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.Midnight);
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            endTimeFormat = res.getString(com.android.internal.R.string.midnight);
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (startDate.hour == 12 && startOnTheHour && !noNoon) {
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (capNoon) {
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.Noon);
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        startTimeFormat = res.getString(com.android.internal.R.string.noon);
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Don't show the start time starting at midnight.  Show
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // 12am instead.
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startTimeString = startDate.format(startTimeFormat);
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endTimeString = isInstant ? startTimeString : endDate.format(endTimeFormat);
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Show the year if the user specified FORMAT_SHOW_YEAR or if
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // the starting and end years are different from each other
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // or from the current year.  But don't show the year if the
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // user specified FORMAT_NO_YEAR.
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showYear) {
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // No code... just a comment for clarity.  Keep showYear
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // on, as they enabled it with FORMAT_SHOW_YEAR.  This
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // takes precedence over them setting FORMAT_NO_YEAR.
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (noYear) {
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // They explicitly didn't want a year.
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            showYear = false;
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (startYear != endYear) {
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            showYear = true;
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Show the year if it's not equal to the current year.
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Time currentTime = new Time();
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            currentTime.setToNow();
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            showYear = startYear != currentTime.year;
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String defaultDateFormat, fullFormat, dateRange;
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numericDate) {
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            defaultDateFormat = res.getString(com.android.internal.R.string.numeric_date);
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (showYear) {
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (abbrevMonth) {
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (noMonthDay) {
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_year);
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_day_year);
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (noMonthDay) {
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.month_year);
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.month_day_year);
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (abbrevMonth) {
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (noMonthDay) {
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month);
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.abbrev_month_day);
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (noMonthDay) {
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.month);
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    defaultDateFormat = res.getString(com.android.internal.R.string.month_day);
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showWeekDay) {
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) {
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.wday1_date1_time1_wday2_date2_time2);
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.wday1_date1_wday2_date2);
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) {
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.date1_time1_date2_time2);
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.date1_date2);
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1348b193e35ed131769e6c98b2752635065489198aebOwen Lin        if (noMonthDay && startMonthNum == endMonthNum && startYear == endYear) {
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Example: "January, 2008"
1350becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format("%s", startDate.format(defaultDateFormat));
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (startYear != endYear || noMonthDay) {
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Different year or we are not showing the month day number.
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Example: "December 31, 2007 - January 1, 2008"
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Or: "January - February, 2008"
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String startDateString = startDate.format(defaultDateFormat);
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String endDateString = endDate.format(defaultDateFormat);
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The values that are used in a fullFormat string are specified
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // by position.
1362becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format(fullFormat,
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startWeekDayString, startDateString, startTimeString,
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endWeekDayString, endDateString, endTimeString);
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get the month, day, and year strings for the start and end dates
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String monthFormat;
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numericDate) {
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            monthFormat = NUMERIC_MONTH_FORMAT;
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (abbrevMonth) {
13725669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer            monthFormat =
13735669ce59aad19f17e1e89913e7483fb93b8aa0cfEric Fischer                res.getString(com.android.internal.R.string.short_format_month);
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            monthFormat = MONTH_FORMAT;
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startMonthString = startDate.format(monthFormat);
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startMonthDayString = startDate.format(MONTH_DAY_FORMAT);
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String startYearString = startDate.format(YEAR_FORMAT);
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endMonthString = isInstant ? null : endDate.format(monthFormat);
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endMonthDayString = isInstant ? null : endDate.format(MONTH_DAY_FORMAT);
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String endYearString = isInstant ? null : endDate.format(YEAR_FORMAT);
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (startMonthNum != endMonthNum) {
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Same year, different month.
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Example: "October 28 - November 3"
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // or: "Wed, Oct 31 - Sat, Nov 3, 2007"
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // or: "Oct 31, 8am - Sat, Nov 3, 2007, 5pm"
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int index = 0;
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showWeekDay) index = 1;
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showYear) index += 2;
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) index += 4;
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (numericDate) index += 8;
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int resId = sameYearTable[index];
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fullFormat = res.getString(resId);
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The values that are used in a fullFormat string are specified
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // by position.
1401becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format(fullFormat,
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startWeekDayString, startMonthString, startMonthDayString,
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startYearString, startTimeString,
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endWeekDayString, endMonthString, endMonthDayString,
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endYearString, endTimeString);
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (startDay != endDay) {
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Same month, different day.
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int index = 0;
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showWeekDay) index = 1;
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showYear) index += 2;
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) index += 4;
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (numericDate) index += 8;
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int resId = sameMonthTable[index];
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fullFormat = res.getString(resId);
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The values that are used in a fullFormat string are specified
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // by position.
1420becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format(fullFormat,
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startWeekDayString, startMonthString, startMonthDayString,
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    startYearString, startTimeString,
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endWeekDayString, endMonthString, endMonthDayString,
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    endYearString, endTimeString);
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Same start and end day
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean showDate = (flags & FORMAT_SHOW_DATE) != 0;
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If nothing was specified, then show the date.
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!showTime && !showDate && !showWeekDay) showDate = true;
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Compute the time string (example: "10:00 - 11:00 am")
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String timeString = "";
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showTime) {
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the start and end time are the same, then just show the
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // start time.
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isInstant) {
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Same start and end time.
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Example: "10:15 AM"
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                timeString = startTimeString;
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Example: "10:00 - 11:00 am"
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String timeFormat = res.getString(com.android.internal.R.string.time1_time2);
1445becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan                // Don't use the user supplied Formatter because the result will pollute the buffer.
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                timeString = String.format(timeFormat, startTimeString, endTimeString);
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Figure out which full format to use.
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        fullFormat = "";
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        String dateString = "";
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (showDate) {
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            dateString = startDate.format(defaultDateFormat);
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showWeekDay) {
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (showTime) {
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Example: "10:00 - 11:00 am, Tue, Oct 9"
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fullFormat = res.getString(com.android.internal.R.string.time_wday_date);
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Example: "Tue, Oct 9"
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fullFormat = res.getString(com.android.internal.R.string.wday_date);
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (showTime) {
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Example: "10:00 - 11:00 am, Oct 9"
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fullFormat = res.getString(com.android.internal.R.string.time_date);
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Example: "Oct 9"
1469becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan                    return formatter.format("%s", dateString);
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (showWeekDay) {
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (showTime) {
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Example: "10:00 - 11:00 am, Tue"
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                fullFormat = res.getString(com.android.internal.R.string.time_wday);
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Example: "Tue"
1478becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan                return formatter.format("%s", startWeekDayString);
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (showTime) {
1481becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan            return formatter.format("%s", timeString);
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The values that are used in a fullFormat string are specified
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // by position.
1486becfc9de9e18ef216c2b537cd2829f1d2d55404fMichael Chan        return formatter.format(fullFormat, timeString, startWeekDayString, dateString);
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Formats a date or a time according to the local conventions. There are
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * lots of options that allow the caller to control, for example, if the
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * time is shown, if the day of the week is shown, if the month name is
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * abbreviated, if noon is shown instead of 12pm, and so on. For the
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * complete list of options, see the documentation for
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #formatDateRange}.
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Example output strings (date formats in these examples are shown using
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the US date format convention but that may change depending on the
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * local settings):
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10:15am</li>
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3:00pm</li>
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3pm</li>
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>3PM</li>
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>08:00</li>
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>17:00</li>
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>noon</li>
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Noon</li>
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>midnight</li>
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Midnight</li>
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 31</li>
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Oct 31, 2007</li>
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>October 31, 2007</li>
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10am, Oct 31</li>
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>17:00, Oct 31</li>
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wed</li>
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wednesday</li>
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10am, Wed, Oct 31</li>
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wed, Oct 31</li>
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wednesday, Oct 31</li>
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wed, Oct 31, 2007</li>
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>Wed, October 31</li>
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>10/31/2007</li>
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
152599a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param context the context is required only if the time is shown
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param millis a point in time in UTC milliseconds
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flags a bit mask of formatting options
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a string containing the formatted date/time.
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String formatDateTime(Context context, long millis, int flags) {
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return formatDateRange(context, millis, millis, flags);
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a relative time string to display the time expressed by millis.  Times
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * are counted starting at midnight, which means that assuming that the current
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * time is March 31st, 0:30:
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <ul>
154099a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *   <li>"millis=0:10 today" will be displayed as "0:10"</li>
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   <li>"millis=11:30pm the day before" will be displayed as "Mar 30"</li>
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </ul>
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the given millis is in a different year, then the full date is
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned in numeric format (e.g., "10/12/2008").
154599a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     *
154699a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     * @param withPreposition If true, the string returned will include the correct
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * preposition ("at 9:20am", "on 10/12/2008" or "on May 29").
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(Context c, long millis,
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean withPreposition) {
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15526a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        String result;
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long now = System.currentTimeMillis();
1554ca3363775e03e0f90bdf111d3e5c54b3ab16df57Steve Pomeroy        long span = Math.abs(now - millis);
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15566a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques        synchronized (DateUtils.class) {
15576a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            if (sNowTime == null) {
15586a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                sNowTime = new Time();
15596a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            }
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15616a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            if (sThenTime == null) {
15626a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                sThenTime = new Time();
15636a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            }
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15656a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            sNowTime.set(now);
15666a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            sThenTime.set(millis);
15676a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques
15686a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            int prepositionId;
15696a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            if (span < DAY_IN_MILLIS && sNowTime.weekDay == sThenTime.weekDay) {
15706a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                // Same day
15716a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                int flags = FORMAT_SHOW_TIME;
15726a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                result = formatDateRange(c, millis, millis, flags);
15736a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                prepositionId = R.string.preposition_for_time;
15746a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            } else if (sNowTime.year != sThenTime.year) {
15756a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                // Different years
15766a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                int flags = FORMAT_SHOW_DATE | FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE;
15776a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                result = formatDateRange(c, millis, millis, flags);
15786a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques
15796a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                // This is a date (like "10/31/2008" so use the date preposition)
15806a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                prepositionId = R.string.preposition_for_date;
15816a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            } else {
15826a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                // Default
15836a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH;
15846a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                result = formatDateRange(c, millis, millis, flags);
15856a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                prepositionId = R.string.preposition_for_date;
15866a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            }
15876a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            if (withPreposition) {
15886a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                Resources res = c.getResources();
15896a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques                result = res.getString(prepositionId, result);
15906a84af0949b341593b4b25ed9bb365bd60ff1254David Sobreira Marques            }
15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
159499a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
159699a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson     * Convenience function to return relative time string without preposition.
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param c context for resources
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param millis time in milliseconds
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return {@link CharSequence} containing relative time.
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getRelativeTimeSpanString(Context, long, boolean)
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static CharSequence getRelativeTimeSpanString(Context c, long millis) {
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return getRelativeTimeSpanString(c, millis, false /* no preposition */);
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
160599a64f4b1d2519b71558fdc62721686445865b60Jesse Wilson
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static Time sNowTime;
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static Time sThenTime;
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1609