Mega Code Archive

 
Categories / Java / Email
 

Convert date information contained in Date into RFC2822 and UTC (Zulu) strings

/*  * 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".  */ import java.util.Calendar; import java.util.Date; import java.util.Hashtable; /**  * 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(Date date) {                  Calendar deviceTime = Calendar.getInstance();         deviceTime.setTime(date);             String dayweek = "";         int dayOfWeek = deviceTime.get(deviceTime.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;         }                  int dayOfMonth = deviceTime.get(deviceTime.DAY_OF_MONTH);                  String monthInYear = getMonthName(deviceTime.get(deviceTime.MONTH));                  int year = deviceTime.get(deviceTime.YEAR);         int hourOfDay = deviceTime.get(deviceTime.HOUR_OF_DAY);         int minutes = deviceTime.get(deviceTime.MINUTE);         int seconds = deviceTime.get(deviceTime.SECOND);                  String rfc = dayweek + ", " +                                   // Tue                 dayOfMonth + " " +                                      // 7                 monthInYear + " " +                                     // Nov                 year + " " +                                            // 2006                 hourOfDay + ":" + minutes + ":" + seconds + " " +       // 14:13:26                 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(Date d) {         StringBuffer date = new StringBuffer();         Calendar cal = Calendar.getInstance();         cal.setTime(d);                  date.append(cal.get(Calendar.YEAR));                  date.append(printTwoDigits(cal.get(Calendar.MONTH) + 1))             .append(printTwoDigits(cal.get(Calendar.DATE)))             .append("T");                  date.append(printTwoDigits(cal.get(Calendar.HOUR_OF_DAY)))             .append(printTwoDigits(cal.get(Calendar.MINUTE)))             .append(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(             Date date, int format, String separator) {                  Calendar cal=Calendar.getInstance();         cal.setTime(date);         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(printTwoDigits(cal.get(Calendar.MINUTE)))                     .append(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(printTwoDigits(cal.get(Calendar.MINUTE)))                     .append(separator)                     .append(cal.get(Calendar.SECOND))                     .append(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(Date d) {         int dateFormat = FORMAT_MONTH_DAY_YEAR;         int timeFormat = FORMAT_HOURS_MINUTES;                  if(!System.getProperty("microedition.locale").equals("en")) {             dateFormat = FORMAT_DAY_MONTH_YEAR;         }         return getFormattedStringFromDate(d,FORMAT_MONTH_DAY_YEAR,"/")                 +" "+getFormattedStringFromDate(d,FORMAT_HOURS_MINUTES,":");     }               /**      * 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;         Calendar cal = Calendar.getInstance();                  try {                          // We use the ' ' as separator and we expect only one space. We             // clean the string to remove extra spaces             StringBuffer cleanedDate = new StringBuffer();             char previous = 'a';             for(int i=0;i<stringDate.length();++i) {                 char ch = stringDate.charAt(i);                 if (ch != ' ' || previous != ' ') {                     cleanedDate.append(ch);                 }                 previous = ch;             }             stringDate = cleanedDate.toString();            // Log.debug("Cleaned date: " + 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);                         //4  Nov 2008 10:30:05 -0400                          int day =1;             try {                day = Integer.parseInt(stringDate.substring(start, end));              } catch (NumberFormatException ex) {                 day = Integer.parseInt(stringDate.substring(start+3, end));             }                          cal.set(Calendar.DAY_OF_MONTH,day);                          // Get month             start = end + 1;             end = stringDate.indexOf(' ', start);             cal.set(Calendar.MONTH, 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";             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);                             }             long millisOffset = (hourOffset * 3600000) + (minOffset * 60000);                   Date gmtDate = cal.getTime();             long millisDate = gmtDate.getTime();                          millisDate -= millisOffset;                          gmtDate.setTime(millisDate);             return gmtDate;                      } catch (Exception e) {                    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 (Date gmtDate){         if (null != gmtDate){             /*long dateInMillis = gmtDate.getTime();             Date deviceDate = new Date();             deviceDate.setTime(dateInMillis+millisDeviceOffset);             return deviceDate;              **/             gmtDate.setTime(gmtDate.getTime()+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(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);                           Date date = calendar.getTime();         long dateInMillis = date.getTime();                      date.setTime(dateInMillis+millisDeviceOffset);                      return date;     }          public static void setTimeZone(String timeZone){                  if (timeZone == null || timeZone.length() < 5) {            // Log.error("setTimeZone: invalid timezone " + timeZone);         }         try {             deviceOffset = timeZone;             String hstmz = deviceOffset.substring(1, 3);             String mstmz = deviceOffset.substring(3, 5);                          long hhtmz = Long.parseLong(hstmz);             long mmtmz = Long.parseLong(mstmz);             millisDeviceOffset = (hhtmz * 3600000) + (mmtmz * 60000);             if(deviceOffset.charAt(0)=='-') {                 millisDeviceOffset *= -1;             }            } catch(Exception e) {             e.printStackTrace();         }     }          /**      * returns a date with string representation of the month      * @param date input date in the format MM/DD/YYYY HH:MMp/a      * @return a representation of the date in the format <MonthName> DD, YYYY HH:MM      */     public static String getReplyDateString(String date) {         StringBuffer ret = new StringBuffer();         //Replace the month number with the month name         String monthName = getMonthName(                 Integer.parseInt(date.substring(0, date.indexOf('/')))-1                 );         String day = date.substring(date.indexOf('/')+1, date.lastIndexOf('/'));         String yearAndTime = date.substring(date.lastIndexOf('/')+1);                  ret.append(monthName).append(" ").append(day).append(", ").append(yearAndTime);         //Replace the slash char between DD and YYYY with ", "         return ret.toString();     }           //------------------------------------------------------------- Private methods     /**      * Get the number of the month, given the name.      */     private static int getMonthNumber(String name) {         for(int i=0, l=monthNames.length; i<l; i++) {             if(monthNames[i].equals(name)) {                 return i;             }         }         return -1;     }     /**      * Get the name of the month, given the number.      */     private static String getMonthName(int number) {         if(number>=0 && number<monthNames.length) {             return monthNames[number];         }         else return null;     }     private static String getAMPM(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(int number) {         if (number>9) {             return String.valueOf(number);         } else {             return "0"+number;         }     } }