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