com.funambol.exchange.util.DateTools.java Source code

Java tutorial

Introduction

Here is the source code for com.funambol.exchange.util.DateTools.java

Source

/*
 * 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;
    }
}