Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.contacts.util;
     18 
     19 import android.content.Context;
     20 import android.text.format.DateFormat;
     21 
     22 import java.text.ParsePosition;
     23 import java.text.SimpleDateFormat;
     24 import java.util.Date;
     25 import java.util.Locale;
     26 import java.util.TimeZone;
     27 
     28 /**
     29  * Utility methods for processing dates.
     30  */
     31 public class DateUtils {
     32     public static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("UTC");
     33 
     34     // All the SimpleDateFormats in this class use the UTC timezone
     35     public static final SimpleDateFormat NO_YEAR_DATE_FORMAT =
     36             new SimpleDateFormat("--MM-dd", Locale.US);
     37     public static final SimpleDateFormat FULL_DATE_FORMAT =
     38             new SimpleDateFormat("yyyy-MM-dd", Locale.US);
     39     public static final SimpleDateFormat DATE_AND_TIME_FORMAT =
     40             new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
     41 
     42     // Variations of ISO 8601 date format.  Do not change the order - it does affect the
     43     // result in ambiguous cases.
     44     private static final SimpleDateFormat[] DATE_FORMATS = {
     45         FULL_DATE_FORMAT,
     46         DATE_AND_TIME_FORMAT,
     47         new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.US),
     48         new SimpleDateFormat("yyyyMMdd", Locale.US),
     49         new SimpleDateFormat("yyyyMMdd'T'HHmmssSSS'Z'", Locale.US),
     50         new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.US),
     51         new SimpleDateFormat("yyyyMMdd'T'HHmm'Z'", Locale.US),
     52     };
     53 
     54     private static final java.text.DateFormat FORMAT_WITHOUT_YEAR_MONTH_FIRST =
     55             new SimpleDateFormat("MMMM dd");
     56 
     57     private static final java.text.DateFormat FORMAT_WITHOUT_YEAR_DATE_FIRST =
     58             new SimpleDateFormat("dd MMMM");
     59 
     60     static {
     61         for (SimpleDateFormat format : DATE_FORMATS) {
     62             format.setLenient(true);
     63             format.setTimeZone(UTC_TIMEZONE);
     64         }
     65         NO_YEAR_DATE_FORMAT.setTimeZone(UTC_TIMEZONE);
     66         FORMAT_WITHOUT_YEAR_MONTH_FIRST.setTimeZone(UTC_TIMEZONE);
     67         FORMAT_WITHOUT_YEAR_DATE_FIRST.setTimeZone(UTC_TIMEZONE);
     68     }
     69 
     70     /**
     71      * Parses the supplied string to see if it looks like a date. If so,
     72      * returns the date.  Otherwise, returns null.
     73      */
     74     public static Date parseDate(String string) {
     75         ParsePosition parsePosition = new ParsePosition(0);
     76         for (int i = 0; i < DATE_FORMATS.length; i++) {
     77             SimpleDateFormat f = DATE_FORMATS[i];
     78             synchronized (f) {
     79                 parsePosition.setIndex(0);
     80                 Date date = f.parse(string, parsePosition);
     81                 if (parsePosition.getIndex() == string.length()) {
     82                     return date;
     83                 }
     84             }
     85         }
     86         return null;
     87     }
     88 
     89     /**
     90      * Parses the supplied string to see if it looks like a date. If so,
     91      * returns the same date in a cleaned-up format for the user.  Otherwise, returns
     92      * the supplied string unchanged.
     93      */
     94     public static String formatDate(Context context, String string) {
     95         if (string == null) {
     96             return null;
     97         }
     98 
     99         string = string.trim();
    100         if (string.length() == 0) {
    101             return string;
    102         }
    103 
    104         ParsePosition parsePosition = new ParsePosition(0);
    105 
    106         Date date;
    107 
    108         synchronized (NO_YEAR_DATE_FORMAT) {
    109             date = NO_YEAR_DATE_FORMAT.parse(string, parsePosition);
    110         }
    111 
    112         if (parsePosition.getIndex() == string.length()) {
    113             java.text.DateFormat outFormat = isMonthBeforeDate(context)
    114                     ? FORMAT_WITHOUT_YEAR_MONTH_FIRST
    115                     : FORMAT_WITHOUT_YEAR_DATE_FIRST;
    116             synchronized (outFormat) {
    117                 return outFormat.format(date);
    118             }
    119         }
    120 
    121         for (int i = 0; i < DATE_FORMATS.length; i++) {
    122             SimpleDateFormat f = DATE_FORMATS[i];
    123             synchronized (f) {
    124                 parsePosition.setIndex(0);
    125                 date = f.parse(string, parsePosition);
    126                 if (parsePosition.getIndex() == string.length()) {
    127                     java.text.DateFormat outFormat = DateFormat.getDateFormat(context);
    128                     outFormat.setTimeZone(UTC_TIMEZONE);
    129                     return outFormat.format(date);
    130                 }
    131             }
    132         }
    133         return string;
    134     }
    135 
    136     private static boolean isMonthBeforeDate(Context context) {
    137         char[] dateFormatOrder = DateFormat.getDateFormatOrder(context);
    138         for (int i = 0; i < dateFormatOrder.length; i++) {
    139             if (dateFormatOrder[i] == DateFormat.DATE) {
    140                 return false;
    141             }
    142             if (dateFormatOrder[i] == DateFormat.MONTH) {
    143                 return true;
    144             }
    145         }
    146         return false;
    147     }
    148 }
    149