Mega Code Archive

 
Categories / Android / Date Type
 

Convert date in RFC2822 and UTC strings, and to build Date from string of dates in RFC2822 and UTC format

/*  * Funambol is a mobile platform developed by Funambol, Inc.   * Copyright (C) 2003 - 2007 Funambol, Inc.  *   * This program is free software; you can redistribute it and/or modify it under  * the terms of the GNU Affero General Public License version 3 as published by  * the Free Software Foundation with the addition of the following permission   * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED  * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE   * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.  *   * This program is distributed in the hope that it will be useful, but WITHOUT  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more  * details.  *   * You should have received a copy of the GNU Affero General Public License   * along with this program; if not, see http://www.gnu.org/licenses or write to  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,  * MA 02110-1301 USA.  *   * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite   * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.  *   * The interactive user interfaces in modified source and object code versions  * of this program must display Appropriate Legal Notices, as required under  * Section 5 of the GNU Affero General Public License version 3.  *   * In accordance with Section 7(b) of the GNU Affero General Public License  * version 3, these Appropriate Legal Notices must retain the display of the  * "Powered by Funambol" logo. If the display of the logo is not reasonably   * feasible for technical reasons, the Appropriate Legal Notices must display  * the words "Powered by Funambol".  */ //package com.funambol.util; import java.util.Calendar; import java.util.Date; /**  * A utility class providing methods to convert date information contained in  * <code>Date</code> objects into RFC2822 and UTC ('Zulu') strings, and to build  * <code>Date</code> objects starting from string representations of dates in  * RFC2822 and UTC format  */ public class MailDateFormatter {   /** Format date as: MM/DD */   public static final int FORMAT_MONTH_DAY = 0;   /** Format date as: MM/DD/YYYY */   public static final int FORMAT_MONTH_DAY_YEAR = 1;   /** Format date as: hh:mm */   public static final int FORMAT_HOURS_MINUTES = 2;   /** Format date as: hh:mm:ss */   public static final int FORMAT_HOURS_MINUTES_SECONDS = 3;   /** Format date as: DD/MM */   public static final int FORMAT_DAY_MONTH = 4;   /** Format date as: DD/MM/YYYY */   public static final int FORMAT_DAY_MONTH_YEAR = 5;   /** Device offset, as string */   private static String deviceOffset = "+0000";   /** Device offset, in millis */   private static long millisDeviceOffset = 0;   /** Names of the months */   private static String[] monthNames = new String[] { "Jan", "Feb", "Mar",       "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };   /**    * Transforms data contained in a <code>Date</code> object (expressed in    * UTC) in a string formatted as per RFC2822 in local time (par. 3.3)    *     * @return A string representing the date contained in the passed    *         <code>Date</code> object formatted as per RFC 2822 and in local    *         time    */   public static String dateToRfc2822(final Date date) {     final Calendar deviceTime = Calendar.getInstance();     deviceTime.setTime(date);     String dayweek = "";     final int dayOfWeek = deviceTime.get(Calendar.DAY_OF_WEEK);     switch (dayOfWeek) {     case 1:       dayweek = "Sun";       break;     case 2:       dayweek = "Mon";       break;     case 3:       dayweek = "Tue";       break;     case 4:       dayweek = "Wed";       break;     case 5:       dayweek = "Thu";       break;     case 6:       dayweek = "Fri";       break;     case 7:       dayweek = "Sat";       break;     }     final int dayOfMonth = deviceTime.get(Calendar.DAY_OF_MONTH);     final String monthInYear = MailDateFormatter.getMonthName(deviceTime         .get(Calendar.MONTH));     final int year = deviceTime.get(Calendar.YEAR);     final int hourOfDay = deviceTime.get(Calendar.HOUR_OF_DAY);     final int minutes = deviceTime.get(Calendar.MINUTE);     final int seconds = deviceTime.get(Calendar.SECOND);     final String rfc = dayweek + ", " + // Tue         dayOfMonth + " " + // 7         monthInYear + " " + // Nov         year + " " + // 2006         hourOfDay + ":" + minutes + ":" + seconds + " " + // 14:13:26         MailDateFormatter.deviceOffset; // +0200     return rfc;   }   /**    * Converts a <code>Date</code> object into a string in 'Zulu' format    *     * @param d    *            A <code>Date</code> object to be converted into a string in    *            'Zulu' format    * @return A string representing the date contained in the passed    *         <code>Date</code> object in 'Zulu' format (e.g. yyyyMMDDThhmmssZ)    */   public static String dateToUTC(final Date d) {     final StringBuffer date = new StringBuffer();     final Calendar cal = Calendar.getInstance();     cal.setTime(d);     date.append(cal.get(Calendar.YEAR));     date.append(         MailDateFormatter.printTwoDigits(cal.get(Calendar.MONTH) + 1))         .append(             MailDateFormatter                 .printTwoDigits(cal.get(Calendar.DATE)))         .append("T");     date         .append(             MailDateFormatter.printTwoDigits(cal                 .get(Calendar.HOUR_OF_DAY))).append(             MailDateFormatter.printTwoDigits(cal                 .get(Calendar.MINUTE))).append(             MailDateFormatter.printTwoDigits(cal                 .get(Calendar.SECOND))).append("Z");     return date.toString();   }   /**    * A method that returns a string rapresenting a date.    *     * @param date    *            the date    *     * @param format    *            the format as one of FORMAT_MONTH_DAY, FORMAT_MONTH_DAY_YEAR,    *            FORMAT_HOURS_MINUTES, FORMAT_HOURS_MINUTES_SECONDS    *            FORMAT_DAY_MONTH FORMAT_DAY_MONTH_YEAR constants    *     * @param separator    *            the separator to be used    */   public static String getFormattedStringFromDate(final Date date,       final int format, final String separator) {     final Calendar cal = Calendar.getInstance();     cal.setTime(date);     final StringBuffer ret = new StringBuffer();     switch (format) {     case FORMAT_HOURS_MINUTES:       // if pm and hour == 0 we want to write 12, not 0       if (cal.get(Calendar.AM_PM) == Calendar.PM           && cal.get(Calendar.HOUR) == 0)         ret.append("12");       else         ret.append(cal.get(Calendar.HOUR));       ret.append(separator).append(           MailDateFormatter.printTwoDigits(cal.get(Calendar.MINUTE)))           .append(MailDateFormatter.getAMPM(cal));       break;     case FORMAT_HOURS_MINUTES_SECONDS:       // if pm and hour == 0 we want to write 12, not 0       if (cal.get(Calendar.AM_PM) == Calendar.PM           && cal.get(Calendar.HOUR) == 0)         ret.append("12");       else         ret.append(cal.get(Calendar.HOUR));       ret.append(separator).append(           MailDateFormatter.printTwoDigits(cal.get(Calendar.MINUTE)))           .append(separator).append(cal.get(Calendar.SECOND)).append(               MailDateFormatter.getAMPM(cal));       break;     case FORMAT_MONTH_DAY:       ret.append(cal.get(Calendar.MONTH) + 1).append(separator).append(           cal.get(Calendar.DAY_OF_MONTH));       break;     case FORMAT_DAY_MONTH:       ret.append(cal.get(Calendar.DAY_OF_MONTH)).append(separator)           .append(cal.get(Calendar.MONTH) + 1);       break;     case FORMAT_MONTH_DAY_YEAR:       ret.append(cal.get(Calendar.MONTH) + 1).append(separator).append(           cal.get(Calendar.DAY_OF_MONTH)).append(separator).append(           cal.get(Calendar.YEAR));       break;     case FORMAT_DAY_MONTH_YEAR:       ret.append(cal.get(Calendar.DAY_OF_MONTH)).append(separator)           .append(cal.get(Calendar.MONTH) + 1).append(separator)           .append(cal.get(Calendar.YEAR));       break;     default:     //  Log.error("getFormattedStringFromDate: invalid format (" + format     //      + ")");     }     return ret.toString();   }   /**    * Returns a localized string representation of Date.    */   public static String formatLocalTime(final Date d) {     int dateFormat = MailDateFormatter.FORMAT_MONTH_DAY_YEAR;     final int timeFormat = MailDateFormatter.FORMAT_HOURS_MINUTES;     if (!System.getProperty("microedition.locale").equals("en"))       dateFormat = MailDateFormatter.FORMAT_DAY_MONTH_YEAR;     return MailDateFormatter.getFormattedStringFromDate(d, dateFormat, "/")         + " "         + MailDateFormatter.getFormattedStringFromDate(d, timeFormat,             ":");   }   /**    * Parses the string in RFC 2822 format and return a <code>Date</code>    * object.    * <p>    * Parse strings like: Thu, 03 May 2007 14:45:38 GMT Thu, 03 May 2007    * 14:45:38 GMT+0200 Thu, 1 Feb 2007 03:57:01 -0800 Fri, 04 May 2007    * 13:40:17 PDT    *     * @param d    *            the date representation to parse    * @return a date, if valid, or null on error    *     */   public static Date parseRfc2822Date(String stringDate) {     if (stringDate == null)       return null;     long hourOffset = 0;     long minOffset = 0;     final Calendar cal = Calendar.getInstance();     try {     //  Log.info("Date original: " + stringDate);       // Just skip the weekday if present       int start = stringDate.indexOf(',');       // put start after ", "       start = (start == -1) ? 0 : start + 2;       stringDate = stringDate.substring(start).trim();       start = 0;       // Get day of month       int end = stringDate.indexOf(' ', start);       int day = 1;       try {         day = Integer.parseInt(stringDate.substring(start, end));       } catch (final NumberFormatException ex) {         // some phones (Nokia 6111) have a invalid date format,         // something like Tue10 Jul... instead of Tue, 10         // so we try to strip (again) the weekday         day = Integer.parseInt(stringDate.substring(start + 3, end));       //  Log.info("Nokia 6111 patch applied.");       }       cal.set(Calendar.DAY_OF_MONTH, day);       // Get month       start = end + 1;       end = stringDate.indexOf(' ', start);       cal.set(Calendar.MONTH, MailDateFormatter.getMonthNumber(stringDate           .substring(start, end)));       // Get year       start = end + 1;       end = stringDate.indexOf(' ', start);       cal.set(Calendar.YEAR, Integer.parseInt(stringDate.substring(start,           end)));       // Get hour       start = end + 1;       end = stringDate.indexOf(':', start);       cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(stringDate           .substring(start, end).trim()));       // Get min       start = end + 1;       end = stringDate.indexOf(':', start);       cal.set(Calendar.MINUTE, Integer.parseInt(stringDate.substring(           start, end)));       // Get sec       start = end + 1;       end = stringDate.indexOf(' ', start);       cal.set(Calendar.SECOND, Integer.parseInt(stringDate.substring(           start, end)));       // Get OFFSET       start = end + 1;       end = stringDate.indexOf('\r', start);       // Process Timezone, checking first for the actual RFC2822 format,       // and then for nthe obsolete syntax.       char sign = '+';       String hourDiff = "0";       String minDiff = "0";       final String offset = stringDate.substring(start).trim();       if (offset.startsWith("+") || offset.startsWith("-")) {         if (offset.length() >= 5) {           sign = offset.charAt(0);           hourDiff = offset.substring(1, 3);           minDiff = offset.substring(3, 5);         } else if (offset.length() == 3) {           sign = offset.charAt(0);           hourDiff = offset.substring(1);           minDiff = "00";         }         // Convert offset to int         hourOffset = Long.parseLong(hourDiff);         minOffset = Long.parseLong(minDiff);         if (sign == '-')           hourOffset = -hourOffset;       } else if (offset.equals("EDT"))         hourOffset = -4;       else if (offset.equals("EST") || offset.equals("CDT"))         hourOffset = -5;       else if (offset.equals("CST") || offset.equals("MDT"))         hourOffset = -6;       else if (offset.equals("PDT") || offset.equals("MST"))         hourOffset = -7;       else if (offset.equals("PST"))         hourOffset = -8;       else if (offset.equals("GMT") || offset.equals("UT"))         hourOffset = 0;       else if (offset.substring(0, 3).equals("GMT")           && offset.length() > 3) {         sign = offset.charAt(3);         hourDiff = offset.substring(4, 6);         minDiff = offset.substring(6, 8);       }       final long millisOffset = (hourOffset * 3600000)           + (minOffset * 60000);       final Date gmtDate = cal.getTime();       long millisDate = gmtDate.getTime();       millisDate -= millisOffset;       gmtDate.setTime(millisDate);       return gmtDate;     } catch (final Exception e) {     //  Log.error("Exception in parseRfc2822Date: " + e.toString()     //      + " parsing " + stringDate);       e.printStackTrace();       return null;     }   }   /**    * Convert the given date (GMT) into the local date. NOTE: changes the    * original date too! Should we change it to a void toLocalDate(Date) that    * changes the input date only?    */   public static Date getDeviceLocalDate(final Date gmtDate) {     if (null != gmtDate) {       /*        * long dateInMillis = gmtDate.getTime(); Date deviceDate = new        * Date(); deviceDate.setTime(dateInMillis+millisDeviceOffset);        * return deviceDate;        */       gmtDate.setTime(gmtDate.getTime()           + MailDateFormatter.millisDeviceOffset);       return gmtDate;     } else       return null;   }   /**    * Gets a <code>Date</code> object from a string representing a date in    * 'Zulu' format (yyyyMMddTHHmmssZ)    *     * @param utc    *            date in 'Zulu' format (yyyyMMddTHHmmssZ)    * @return A <code>Date</code> object obtained starting from a time in    *         milliseconds from the Epoch    */   public static Date parseUTCDate(final String utc) {     int day = 0;     int month = 0;     int year = 0;     int hour = 0;     int minute = 0;     int second = 0;     Calendar calendar = null;     day = Integer.parseInt(utc.substring(6, 8));     month = Integer.parseInt(utc.substring(4, 6));     year = Integer.parseInt(utc.substring(0, 4));     hour = Integer.parseInt(utc.substring(9, 11));     minute = Integer.parseInt(utc.substring(11, 13));     second = Integer.parseInt(utc.substring(13, 15));     calendar = Calendar.getInstance();     calendar.set(Calendar.DAY_OF_MONTH, day);     calendar.set(Calendar.MONTH, month - 1);     calendar.set(Calendar.YEAR, year);     calendar.set(Calendar.HOUR_OF_DAY, hour);     calendar.set(Calendar.MINUTE, minute);     calendar.set(Calendar.SECOND, second);     final Date date = calendar.getTime();     final long dateInMillis = date.getTime();     date.setTime(dateInMillis + MailDateFormatter.millisDeviceOffset);     return date;   }   public static void setTimeZone(final String timeZone) {     if (timeZone == null || timeZone.length() < 5)       //Log.error("setTimeZone: invalid timezone " + timeZone);     try {       MailDateFormatter.deviceOffset = timeZone;       final String hstmz = MailDateFormatter.deviceOffset.substring(1, 3);       final String mstmz = MailDateFormatter.deviceOffset.substring(3, 5);       final long hhtmz = Long.parseLong(hstmz);       final long mmtmz = Long.parseLong(mstmz);       MailDateFormatter.millisDeviceOffset = (hhtmz * 3600000)           + (mmtmz * 60000);       if (MailDateFormatter.deviceOffset.charAt(0) == '-')         MailDateFormatter.millisDeviceOffset *= -1;     } catch (final Exception e) {       //Log.error("setTimeZone: " + e.toString());       e.printStackTrace();     }   }   // ------------------------------------------------------------- Private   // methods   /**    * Get the number of the month, given the name.    */   private static int getMonthNumber(final String name) {     for (int i = 0, l = MailDateFormatter.monthNames.length; i < l; i++)       if (MailDateFormatter.monthNames[i].equals(name))         return i;     return -1;   }   /**    * Get the name of the month, given the number.    */   private static String getMonthName(final int number) {     if (number > 0 && number < MailDateFormatter.monthNames.length)       return MailDateFormatter.monthNames[number];     else       return null;   }   private static String getAMPM(final Calendar cal) {     return (cal.get(Calendar.AM_PM) == Calendar.AM) ? "a" : "p";   }   /**    * Returns a string representation of number with at least 2 digits    */   private static String printTwoDigits(final int number) {     if (number > 9)       return String.valueOf(number);     else       return "0" + number;   } }