DateUtils.java revision 2b3f95cc12b76523410782d4178562ce241410ef
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;
2545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
2645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov/**
2745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov * Utility methods for processing dates.
2845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov */
2945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikovpublic class DateUtils {
30392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public static final SimpleDateFormat NO_YEAR_DATE_FORMAT = new SimpleDateFormat("--MM-dd");
31392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public static final SimpleDateFormat FULL_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
32392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann    public static final SimpleDateFormat DATE_AND_TIME_FORMAT =
33392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann            new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
3445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
352b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    // Variations of ISO 8601 date format.  Do not change the order - it does affect the
362b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    // result in ambiguous cases.
3745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    private static final SimpleDateFormat[] DATE_FORMATS = {
38392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        FULL_DATE_FORMAT,
39392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann        DATE_AND_TIME_FORMAT,
402b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"),
412b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        new SimpleDateFormat("yyyyMMdd"),
422b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        new SimpleDateFormat("yyyyMMdd'T'HHmmssSSS'Z'"),
432b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'"),
442b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        new SimpleDateFormat("yyyyMMdd'T'HHmm'Z'"),
4545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    };
462b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
4745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    static {
4845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        for (SimpleDateFormat format : DATE_FORMATS) {
4945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            format.setLenient(true);
5045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        }
5145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    }
5245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
5345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    private static final java.text.DateFormat FORMAT_WITHOUT_YEAR_MONTH_FIRST =
5445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            new SimpleDateFormat("MMMM dd");
5545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
5645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    private static final java.text.DateFormat FORMAT_WITHOUT_YEAR_DATE_FIRST =
5745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            new SimpleDateFormat("dd MMMM");
5845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
5945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    /**
6045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov     * Parses the supplied string to see if it looks like a date. If so,
612b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov     * returns the date.  Otherwise, returns null.
622b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov     */
632b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    public static Date parseDate(String string) {
642b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        ParsePosition parsePosition = new ParsePosition(0);
652b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        for (int i = 0; i < DATE_FORMATS.length; i++) {
662b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            SimpleDateFormat f = DATE_FORMATS[i];
672b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            synchronized (f) {
682b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                parsePosition.setIndex(0);
692b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                Date date = f.parse(string, parsePosition);
702b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                if (parsePosition.getIndex() == string.length()) {
712b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                    return date;
722b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                }
732b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            }
742b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        }
752b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        return null;
762b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    }
772b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
782b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov    /**
792b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov     * Parses the supplied string to see if it looks like a date. If so,
8045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov     * returns the same date in a cleaned-up format.  Otherwise, returns
8145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov     * the supplied string unchanged.
8245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov     */
8345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    public static String formatDate(Context context, String string) {
8445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        if (string == null) {
8545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            return null;
8645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        }
8745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
8845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        string = string.trim();
8945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        if (string.length() == 0) {
9045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            return string;
9145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        }
9245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
9345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        ParsePosition parsePosition = new ParsePosition(0);
9445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
952b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        Date date;
962b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
972b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        synchronized (NO_YEAR_DATE_FORMAT) {
982b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            date = NO_YEAR_DATE_FORMAT.parse(string, parsePosition);
992b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        }
1002b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
1012b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        if (parsePosition.getIndex() == string.length()) {
1022b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            java.text.DateFormat outFormat = isMonthBeforeDate(context)
1032b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                    ? FORMAT_WITHOUT_YEAR_MONTH_FIRST
1042b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                    : FORMAT_WITHOUT_YEAR_DATE_FIRST;
1052b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            synchronized (outFormat) {
1062b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                return outFormat.format(date);
1072b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov            }
1082b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov        }
1092b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov
11045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        for (int i = 0; i < DATE_FORMATS.length; i++) {
11145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            SimpleDateFormat f = DATE_FORMATS[i];
11245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            synchronized (f) {
11345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                parsePosition.setIndex(0);
1142b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                date = f.parse(string, parsePosition);
11545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                if (parsePosition.getIndex() == string.length()) {
1162b3f95cc12b76523410782d4178562ce241410efDmitri Plotnikov                    java.text.DateFormat outFormat = DateFormat.getDateFormat(context);
11745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                    synchronized (outFormat) {
11845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                        return outFormat.format(date);
11945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                    }
12045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                }
12145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            }
12245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        }
12345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        return string;
12445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    }
12545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov
12645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    private static boolean isMonthBeforeDate(Context context) {
12745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        char[] dateFormatOrder = DateFormat.getDateFormatOrder(context);
12845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        for (int i = 0; i < dateFormatOrder.length; i++) {
12945b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            if (dateFormatOrder[i] == DateFormat.DATE) {
13045b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                return false;
13145b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            }
13245b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            if (dateFormatOrder[i] == DateFormat.MONTH) {
13345b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov                return true;
13445b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov            }
13545b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        }
13645b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov        return false;
13745b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov    }
13845b4402f0c05b21312dd8d647ae549d43057537dDmitri Plotnikov}
139