DateUtils.java revision 11812c59ee140d62eaf3a8d826d2018767d490c5
145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov/*
245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project
345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov *
445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License");
545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * you may not use this file except in compliance with the License.
645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * You may obtain a copy of the License at
745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov *
845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov *      http://www.apache.org/licenses/LICENSE-2.0
945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov *
1045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software
1145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS,
1245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * See the License for the specific language governing permissions and
1445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * limitations under the License.
1545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov */
1645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
1745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikovpackage com.android.contacts.util;
1845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
1945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikovimport android.content.Context;
2045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikovimport android.text.format.DateFormat;
2145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
2245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikovimport java.text.ParsePosition;
2345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikovimport java.text.SimpleDateFormat;
2445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikovimport java.util.Date;
254b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmannimport java.util.Locale;
264b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmannimport java.util.TimeZone;
2745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
2845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov/**
2945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * Utility methods for processing dates.
3045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov */
3145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikovpublic class DateUtils {
324b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann    public static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("UTC");
334b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann
344b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann    // All the SimpleDateFormats in this class use the UTC timezone
354b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann    public static final SimpleDateFormat NO_YEAR_DATE_FORMAT =
364b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann            new SimpleDateFormat("--MM-dd", Locale.US);
374b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann    public static final SimpleDateFormat FULL_DATE_FORMAT =
384b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann            new SimpleDateFormat("yyyy-MM-dd", Locale.US);
39392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public static final SimpleDateFormat DATE_AND_TIME_FORMAT =
404b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
41dcf751d75ad5d31620a4216d8c53fd59525e8bd8Makoto Onuki    public static final SimpleDateFormat NO_YEAR_DATE_AND_TIME_FORMAT =
42dcf751d75ad5d31620a4216d8c53fd59525e8bd8Makoto Onuki            new SimpleDateFormat("--MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
4345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
442b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    // Variations of ISO 8601 date format.  Do not change the order - it does affect the
452b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    // result in ambiguous cases.
4645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    private static final SimpleDateFormat[] DATE_FORMATS = {
47392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        FULL_DATE_FORMAT,
48392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        DATE_AND_TIME_FORMAT,
494b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US),
504b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann        new SimpleDateFormat("yyyyMMdd", Locale.US),
514b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann        new SimpleDateFormat("yyyyMMdd'T'HHmmssSSS'Z'", Locale.US),
524b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann        new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.US),
534b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann        new SimpleDateFormat("yyyyMMdd'T'HHmm'Z'", Locale.US),
5445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    };
552b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
5645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    private static final java.text.DateFormat FORMAT_WITHOUT_YEAR_MONTH_FIRST =
5745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            new SimpleDateFormat("MMMM dd");
5845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
5911812c59ee140d62eaf3a8d826d2018767d490c5Daniel Lehmann    private static final java.text.DateFormat FORMAT_WITHOUT_YEAR_DAY_FIRST =
6045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            new SimpleDateFormat("dd MMMM");
6145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
624b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann    static {
634b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann        for (SimpleDateFormat format : DATE_FORMATS) {
644b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann            format.setLenient(true);
654b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann            format.setTimeZone(UTC_TIMEZONE);
664b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann        }
674b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann        NO_YEAR_DATE_FORMAT.setTimeZone(UTC_TIMEZONE);
684b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann        FORMAT_WITHOUT_YEAR_MONTH_FIRST.setTimeZone(UTC_TIMEZONE);
6911812c59ee140d62eaf3a8d826d2018767d490c5Daniel Lehmann        FORMAT_WITHOUT_YEAR_DAY_FIRST.setTimeZone(UTC_TIMEZONE);
704b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann    }
714b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann
7245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    /**
7345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov     * Parses the supplied string to see if it looks like a date. If so,
742b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov     * returns the date.  Otherwise, returns null.
752b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov     */
762b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    public static Date parseDate(String string) {
772b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        ParsePosition parsePosition = new ParsePosition(0);
782b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        for (int i = 0; i < DATE_FORMATS.length; i++) {
792b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            SimpleDateFormat f = DATE_FORMATS[i];
802b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            synchronized (f) {
812b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                parsePosition.setIndex(0);
822b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                Date date = f.parse(string, parsePosition);
832b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                if (parsePosition.getIndex() == string.length()) {
842b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                    return date;
852b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                }
862b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            }
872b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        }
882b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        return null;
892b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    }
902b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
912b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    /**
922b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov     * Parses the supplied string to see if it looks like a date. If so,
934b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann     * returns the same date in a cleaned-up format for the user.  Otherwise, returns
9445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov     * the supplied string unchanged.
9545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov     */
9645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    public static String formatDate(Context context, String string) {
9745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        if (string == null) {
9845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            return null;
9945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        }
10045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
10145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        string = string.trim();
10245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        if (string.length() == 0) {
10345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            return string;
10445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        }
10545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
10645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        ParsePosition parsePosition = new ParsePosition(0);
10745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
1082b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        Date date;
1092b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
1102b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        synchronized (NO_YEAR_DATE_FORMAT) {
1112b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            date = NO_YEAR_DATE_FORMAT.parse(string, parsePosition);
1122b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        }
1132b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
1142b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        if (parsePosition.getIndex() == string.length()) {
11511812c59ee140d62eaf3a8d826d2018767d490c5Daniel Lehmann            java.text.DateFormat outFormat = isMonthBeforeDay(context)
1162b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                    ? FORMAT_WITHOUT_YEAR_MONTH_FIRST
11711812c59ee140d62eaf3a8d826d2018767d490c5Daniel Lehmann                    : FORMAT_WITHOUT_YEAR_DAY_FIRST;
1182b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            synchronized (outFormat) {
1192b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                return outFormat.format(date);
1202b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            }
1212b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        }
1222b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
12345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        for (int i = 0; i < DATE_FORMATS.length; i++) {
12445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            SimpleDateFormat f = DATE_FORMATS[i];
12545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            synchronized (f) {
12645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                parsePosition.setIndex(0);
1272b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                date = f.parse(string, parsePosition);
12845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                if (parsePosition.getIndex() == string.length()) {
1292b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                    java.text.DateFormat outFormat = DateFormat.getDateFormat(context);
1304b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann                    outFormat.setTimeZone(UTC_TIMEZONE);
1314b648485346462dc26c3a469caeae8589f5fbd58Daniel Lehmann                    return outFormat.format(date);
13245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                }
13345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            }
13445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        }
13545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        return string;
13645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    }
13745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
13811812c59ee140d62eaf3a8d826d2018767d490c5Daniel Lehmann    public static boolean isMonthBeforeDay(Context context) {
13945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        char[] dateFormatOrder = DateFormat.getDateFormatOrder(context);
14045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        for (int i = 0; i < dateFormatOrder.length; i++) {
14145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            if (dateFormatOrder[i] == DateFormat.DATE) {
14245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                return false;
14345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            }
14445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            if (dateFormatOrder[i] == DateFormat.MONTH) {
14545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                return true;
14645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            }
14745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        }
14845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        return false;
14945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    }
15045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov}
151