Java tutorial
/* * Funambol is a mobile platform developed by Funambol, Inc. * Copyright (C) 2008 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.exchange.util; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import com.funambol.exchange.exception.DataAccessException; import com.funambol.exchange.xml.XmlParseException; import javax.xml.datatype.XMLGregorianCalendar; import org.apache.commons.lang.time.DateUtils; /** * Utility class that groups dates manipulation functions. * * @version $Id$ */ public class DateTools { // ---------------------------------------------------------------- Contants private static final String DATE_FORMAT_WEBDAV = "yyyy-MM-dd'T'HH:mm:ss'.000Z'"; public static final String DATE_FORMAT_PDI = "yyyyMMdd'T'HHmmss'Z'"; private static final String ANNIVERSARY_FORMAT_PDI = "yyyy-MM-dd"; private static final String ANNIVERSARY_FORMAT_WEBDAV = "yyyy-MM-dd'T'HH:mm:ss'.000Z'"; private static final String DATETIME_FORMAT_CLIENT_UTC = "yyyyMMdd'T'HHmmss'Z'"; public static final String DATETIME_FORMAT_CLIENT_NO_UTC = "yyyyMMdd'T'HHmmss"; private static final String DATE_FORMAT_WEBDAV_FROM_EXCHANGE = "yyyy-MM-dd HH:mm:ss.SSS"; protected static final int MAX_YEAR = 4000; /** * Make a webdav tag date from a date * * @param date * date * @param timeZone * @return webdav tag date * @throws XmlParseException */ public static String dateToWebDavTag(String date, TimeZone timeZone) throws Exception { SimpleDateFormat formatter; String webDavDate; Date dt; if (date != null) { String format = DATETIME_FORMAT_CLIENT_UTC; if (date.indexOf("Z") == -1) { // // for nokia phone utc bug // format = DATETIME_FORMAT_CLIENT_NO_UTC; } formatter = new SimpleDateFormat(format); if (timeZone != null) { formatter.setTimeZone(timeZone); } dt = formatter.parse(date); webDavDate = dateToWebDavTag(dt); } else { webDavDate = ""; } return webDavDate; } /** * Make a webdav tag date from a date * * @param date * date * @return webdav tag date */ public static String dateToWebDavTag(Date date) { SimpleDateFormat formatter; String webDavDate; if (date != null) { formatter = new SimpleDateFormat(DATE_FORMAT_WEBDAV); formatter.setTimeZone(TimeZone.getTimeZone("GMT")); webDavDate = formatter.format(date); if (webDavDate.length() > 4) { String year = webDavDate.substring(0, 4); if (Integer.parseInt(year) > MAX_YEAR) { webDavDate = ""; } } } else { webDavDate = ""; } return webDavDate; } /** * Make a date from a webdav tag date * * @param date * webdav tag content * @return a Date * @throws XmlParseException */ public static Date pdiToDate(String date) throws XmlParseException { SimpleDateFormat formatter; Date dt; try { if (date != null) { formatter = new SimpleDateFormat(DATE_FORMAT_PDI); dt = formatter.parse(date); } else { dt = null; } } catch (ParseException e) { throw new XmlParseException(e.toString()); } return dt; } public static Date pdiToGmtDate(String date) throws XmlParseException { SimpleDateFormat formatter; Date dt; try { if (date != null) { formatter = new SimpleDateFormat(DATE_FORMAT_PDI); formatter.setTimeZone(TimeZone.getTimeZone("GMT")); dt = formatter.parse(date); } else { dt = null; } } catch (ParseException e) { throw new XmlParseException(e.toString()); } return dt; } /** * Make a date from a webdav tag date * * @param date * webdav tag content * @return a Date * @throws XmlParseException */ public static Date webDavTagToDate(String date) throws XmlParseException { SimpleDateFormat formatter; String value; Date timestamp; try { if (date != null && date.length() > 23) { value = date.substring(0, 10) + " " + date.substring(11, 23); formatter = new SimpleDateFormat(DATE_FORMAT_WEBDAV_FROM_EXCHANGE); formatter.setTimeZone(TimeZone.getTimeZone("GMT")); timestamp = formatter.parse(value); } else { timestamp = null; } } catch (ParseException e) { throw new XmlParseException(e.toString()); } return timestamp; } /** * Make a date from a webdav tag date to client date * * @param date * webdav tag content * @return a Date * @throws XmlParseException */ public static String toClientDate(Date date) throws XmlParseException { SimpleDateFormat formatter; try { if (date != null) { formatter = new SimpleDateFormat(DATETIME_FORMAT_CLIENT_UTC); formatter.setTimeZone(TimeZone.getTimeZone("GMT")); return formatter.format(date); } else { return null; } } catch (Exception e) { throw new XmlParseException(e.toString()); } } /** * Make a date from a client date to webdav date * * @param date * client date * @return a Date * @throws XmlParseException */ public static Date clientDateToDate(String date) throws XmlParseException { SimpleDateFormat formatter; Date timestamp; String format; try { if (date != null) { if (date.indexOf("Z") != -1) { format = DATETIME_FORMAT_CLIENT_UTC; } else { // // for nokia phone utc bug // format = DATETIME_FORMAT_CLIENT_NO_UTC; } formatter = new SimpleDateFormat(format); formatter.setTimeZone(TimeZone.getTimeZone("GMT")); timestamp = formatter.parse(date); return timestamp; } else { return null; } } catch (ParseException e) { throw new XmlParseException(e.toString()); } } /** * Make a date from a webdav tag date * * @param date * webdav tag content * @param timeZone * @return a Date * @throws XmlParseException */ public static String webDavTagToPDIDate(String date, TimeZone timeZone) throws XmlParseException { SimpleDateFormat formatter; if (timeZone == null) { timeZone = TimeZone.getTimeZone("GMT"); } Date dt; String pdiDate; if (date != null && date.length() > 0) { dt = webDavTagToDate(date); formatter = new SimpleDateFormat(DATE_FORMAT_PDI); formatter.setTimeZone(timeZone); pdiDate = formatter.format(dt); } else { pdiDate = null; } return pdiDate; } /* * Make a date from pdi format to webdav * @param date webdav tag content * @param timeZone * @return a Date * @throws XmlParseException */ public static String PDItowebDavTag(String date) throws XmlParseException { SimpleDateFormat formatter; Date dt; String pdiDate; if (date != null && date.length() > 0) { dt = pdiToDate(date); formatter = new SimpleDateFormat(DATE_FORMAT_WEBDAV); pdiDate = formatter.format(dt); } else { pdiDate = null; } return pdiDate; } /** * Make a date from a webdav tag date * * @param date * webdav tag content * @return a Date */ public static String dateToPDIDate(Date date) { SimpleDateFormat formatter; String pdiDate; if (date != null) { formatter = new SimpleDateFormat(DATE_FORMAT_PDI); pdiDate = formatter.format(date); } else { pdiDate = null; } return pdiDate; } /** * Converts a all day Funambol date to an allday ExchangeDate * * @param date * @param timezone * @param isAStartDate * @return * @throws com.funambol.exchange.xml.XmlParseException */ public static String convertDayToWebDavDate(String date, String timezone) throws XmlParseException { SimpleDateFormat formatter; Date dt; String wedDavDate, value; String timePart = null; if (date != null && date.length() > 0) { if (date.length() != 8) { date = date.replaceAll("-", ""); } timePart = "T000000Z"; value = date + timePart; formatter = new SimpleDateFormat(DATE_FORMAT_PDI); try { formatter.setTimeZone(TimeZone.getTimeZone("GMT")); dt = formatter.parse(value); long time = dt.getTime(); long offset = TimeZone.getTimeZone(timezone).getOffset(time); dt = new Date(time - offset); } catch (ParseException e) { throw new XmlParseException("Error converting date", e); } formatter.applyPattern(DATE_FORMAT_WEBDAV); wedDavDate = formatter.format(dt); } else { wedDavDate = null; } return wedDavDate; } /** * <p> * Convert a date in WebDav format ("yyyy-MM-dd'T'KK:mm:ss.fff'Z'") in day * format ("yyyy-MM-dd") * </p> * * @param date * @param timezone * @param isAStartDate * flag that tells if the input String represents a start date * @return the date in day format * @throws XmlParseException */ public static String convertWebDavDateToDay(String date, String timezone) throws XmlParseException { SimpleDateFormat formatter; Date dt; String funambolDate; if (date != null && date.length() > 0) { formatter = new SimpleDateFormat(DATE_FORMAT_WEBDAV); try { formatter.setTimeZone(TimeZone.getTimeZone("GMT")); dt = formatter.parse(date); long time = dt.getTime(); long offset = TimeZone.getTimeZone(timezone).getOffset(time); dt = new Date(time + offset); } catch (ParseException e) { throw new XmlParseException("Error converting date", e); } formatter.applyPattern(DateTools.ANNIVERSARY_FORMAT_PDI); funambolDate = formatter.format(dt); } else { funambolDate = null; } return funambolDate; } public static String convertEwsCalToDateTime(XMLGregorianCalendar xmlCal) { return xmlCal.toString().replaceAll("-", "").replaceAll(":", ""); } /** * Converts a date in exchange task webdav format to funambol * * @param date * @return * @throws com.funambol.exchange.xml.XmlParseException */ public static String exchangeTaskDateToFunambolTaskDate(String date) throws XmlParseException { SimpleDateFormat formatter; Date dt; String value; if (date != null && date.length() > 0) { value = date; formatter = new SimpleDateFormat(DATE_FORMAT_WEBDAV); try { dt = formatter.parse(value); } catch (ParseException e) { throw new XmlParseException("Error converting date", e); } formatter.applyPattern(ANNIVERSARY_FORMAT_PDI); return formatter.format(dt); } else { return null; } } /** * <p> * Converts a date in day format("yyyy-MM-dd") to WebDAV format * ("yyyy-MM-dd'T'KK:mm:ss'.000Z'"). * </p> * <p> * If the timezone parameter is <i>null</i> the timezone of the output date * is considered GMT. * </p> * <p> * If the isAStartDate is true then the time in GMT of the output date will * be 00:00:00 else 24:00:00. * </p> * * @param date * @param timezone * @param isAStartDate * @return the date in WebDav format * @throws XmlParseException */ public static String convertDayInWebDavDateFormat(String date, TimeZone timezone, boolean isAStartDate) throws XmlParseException { SimpleDateFormat formatter; Date dt; String wedDavDate, value; String timePart = null; if (date != null && date.length() > 0) { if (isAStartDate) { timePart = "T00:00:00.000Z"; } else { timePart = "T24:00:00.000Z"; } date = date.replace("-", ""); value = date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + timePart; formatter = new SimpleDateFormat(DATE_FORMAT_WEBDAV); if (timezone == null) { timezone = TimeZone.getTimeZone("GMT"); } formatter.setTimeZone(timezone); try { dt = formatter.parse(value); } catch (ParseException e) { throw new XmlParseException("Error converting date", e); } formatter.setTimeZone(TimeZone.getTimeZone("GMT")); wedDavDate = formatter.format(dt); } else { wedDavDate = null; } return wedDavDate; } /** * Make a date from a webdav tag date * * @param date * webdav tag content * @return a Date * @throws XmlParseException */ public static String webDavToPDIAnniversary(String date) throws Exception { SimpleDateFormat formatter; Date dt; String pdiDate; if (date != null && date.length() > 0) { formatter = new SimpleDateFormat(ANNIVERSARY_FORMAT_WEBDAV); dt = formatter.parse(date); formatter = new SimpleDateFormat(ANNIVERSARY_FORMAT_PDI); pdiDate = formatter.format(dt); } else { pdiDate = null; } return pdiDate; } public static String addOneDay(String date) throws ParseException { SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT_WEBDAV); String retval; formatter.setTimeZone(TimeZone.getTimeZone("GMT")); Date dt = formatter.parse(date); retval = formatter.format(new Date(dt.getTime() + 24 * 60 * 60 * 1000)); return retval; } public static String subtractOneDay(String date) throws ParseException { SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT_WEBDAV); String retval; formatter.setTimeZone(TimeZone.getTimeZone("GMT")); Date dt = formatter.parse(date); retval = formatter.format(new Date(dt.getTime() - 24 * 60 * 60 * 1000)); return retval; } public static String addToPdi(String dateString, long millis) throws XmlParseException { SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT_PDI); Date date = pdiToDate(dateString); String newDateString = formatter.format(new Date(date.getTime() + millis)); return newDateString; } /** * This fix is for task due-date times to be sent in such a way that when * converted to a date will always point to the same date in any timezone. * This is accomplished by setting the time part to 12 noon. * * @param The * old wedav date-time string of format DATE_FORMAT_WEBDAV * @param timepart * The timepart with format THH:MM:SS.000Z * * @return the new webdav date-time string with the new timepart. */ public static String changeWebDavTimePart(String old, String timepart) { return old.substring(0, old.indexOf('T')) + timepart; } public static String roundPdiDateToNearestDay(String dateTime) throws DataAccessException { Date date = null; try { date = DateTools.pdiToDate(dateTime); } catch (XmlParseException e) { throw new DataAccessException("Unable to parse date when rounding: " + dateTime, e); } date = DateUtils.round(date, Calendar.DATE); String roundedDateTime = DateTools.dateToPDIDate(date); return roundedDateTime; } /** * Add a time part to a pdi date. If a time part is already present, no * changes are made. This function handles the 'T' separator and therefore * should not be included in the given time part. * * @param dateTime * The date time to add a time part to * @param timepart * The time part to add * @return A pdi datetime with the given time part added or the original * datetime if a time part was already present */ public static String addPdiTimePart(final String dateTime, final String timepart) { String newDateTime = dateTime; if (dateTime.indexOf('T') == -1) { newDateTime += 'T' + timepart; } return newDateTime; } }