org.appcelerator.util.DateUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.appcelerator.util.DateUtil.java

Source

/*
 * Copyright 2006-2008 Appcelerator, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */

package org.appcelerator.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * DateUtil is a utility class to help with various date manipulation tasks.
 *
 * @author <a href="mailto:jhaynie@appcelerator.com">Jeff Haynie</a>
 */
public class DateUtil {
    private static final Log LOG = LogFactory.getLog(DateUtil.class);

    public static final String MONTHS[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
            "Nov", "Dec" };

    /**
     * gets the 3 character month string from the given calendar
     *
     * @param c calendar
     * @return 3 character month
     */
    public static String getMonth(Calendar c) {
        return MONTHS[c.get(Calendar.MONTH)];
    }

    /**
     * SimpleDateFormat in ATOM format.
     */
    public static final SimpleDateFormat ATOM_DATE_FORMAT = new SimpleDateFormat(
            "EEE' 'MMM' 'dd' 'HH:mm:ss' 'Z' 'yyyy");
    /**
     * SimpleDateFormat in ISO 8601 format.
     */
    public static final SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    /**
     * SimpleDateFormat in RFC 822 format.
     */
    public static final SimpleDateFormat RFC822_DATE_FORMAT = new SimpleDateFormat(
            "EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z", Locale.US);
    /**
     * SimpleDateFormat in Java date format.
     */
    public static final SimpleDateFormat JAVA_DATE_FORMAT = new SimpleDateFormat(
            "EEE' 'MMM' 'dd' 'HH:mm:ss' 'zzz' 'yyyy");
    /**
     * SimpleDateFormat in appcelerator format.
     */
    public static final SimpleDateFormat APP_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd' 'HH:mm:ss.SSS");
    /**
     * SimpleDateFormat in HH:mm:ss time only format.
     */
    public static final SimpleDateFormat TIME_DATE_FORMAT = new SimpleDateFormat("HH:mm:ss");
    /**
     * Greenwich mean time timezone (GMT).
     */
    public static final TimeZone GMT_TZ = TimeZone.getTimeZone("GMT");

    static {
        ISO8601_DATE_FORMAT.setTimeZone(GMT_TZ);
        RFC822_DATE_FORMAT.setTimeZone(GMT_TZ);
        JAVA_DATE_FORMAT.setTimeZone(TimeZone.getDefault());
        APP_DATE_FORMAT.setTimeZone(TimeZone.getDefault());
    }

    /**
     * get the specified date as a string in appcelerator date format
     *
     * @param date date to get
     * @return string date in appcelerator date format.
     * @see DateUtil#APPCELERATOR_DATE_FORMAT
     */
    public static String getDateAsAppFormat(Date date) {
        if (null == date) {
            return null;
        }

        synchronized (APP_DATE_FORMAT) {
            return APP_DATE_FORMAT.format(date);
        }
    }

    /**
     * get the specified date as a string in simple time date format
     *
     * @param date date to get
     * @return string date in simple time date format.
     * @see DateUtil#TIME_DATE_FORMAT
     */
    public static String getDateAsTimeFormat(Date date) {
        if (null == date) {
            return null;
        }

        synchronized (TIME_DATE_FORMAT) {
            return TIME_DATE_FORMAT.format(date);
        }
    }

    /**
     * get the specified date as a string in RFC 822 date format
     *
     * @param date date to get
     * @return string date in RFC 822 date format.
     * @see DateUtil#RFC822_DATE_FORMAT
     */
    public static String getDateAsRFC822(Date date) {
        if (null == date) {
            return null;
        }

        synchronized (RFC822_DATE_FORMAT) {
            return RFC822_DATE_FORMAT.format(date);
        }
    }

    /**
     * get the specified date as a string in java date format
     *
     * @param date date to get
     * @return string date in java date format.
     * @see DateUtil#JAVA_DATE_FORMAT
     */
    public static String getDateAsJavaDate(Date date) {
        if (null == date) {
            return null;
        }

        synchronized (JAVA_DATE_FORMAT) {
            return JAVA_DATE_FORMAT.format(date);
        }
    }

    /**
     * get the specified date as a string in ISO 8601 date format
     *
     * @param date date to get
     * @return string date in IOS 8601 date format.
     * @see DateUtil#ISO8601_DATE_FORMAT
     */
    public static String getDateAsISO8601(Date date) {
        if (null == date) {
            return null;
        }

        synchronized (ISO8601_DATE_FORMAT) {
            String result = ISO8601_DATE_FORMAT.format(date);
            //convert YYYYMMDDTHH:mm:ss+HH00 into YYYYMMDDTHH:mm:ss+HH:00
            //- note the added colon for the Timezone
            result = result.substring(0, result.length() - 2) + ":" + result.substring(result.length() - 2);
            return result;
        }
    }

    /**
     * attempts to parse the string date in known formats
     *
     * @param str date string to parse
     * @return calendar for parsed date or <code>null</code> if not successful
     */
    public static Calendar parseDate(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        Date date;
        Calendar cal = null;
        try {
            synchronized (ISO8601_DATE_FORMAT) {
                date = ISO8601_DATE_FORMAT.parse(str);
            }
        } catch (Exception ex) {
            try {
                synchronized (RFC822_DATE_FORMAT) {
                    date = RFC822_DATE_FORMAT.parse(str);
                }
            } catch (Exception ex2) {
                try {
                    synchronized (ATOM_DATE_FORMAT) {
                        date = ATOM_DATE_FORMAT.parse(str);
                    }
                } catch (Exception ex3) {
                    try {
                        synchronized (APP_DATE_FORMAT) {
                            date = APP_DATE_FORMAT.parse(str);
                        }
                    } catch (ParseException ex1) {
                        // last resort, try our common date formats
                        date = parseUsingCommonDateFormats(str);
                    }
                }
            }
        }
        if (date != null) {
            cal = new GregorianCalendar();
            cal.setTime(date);
            cal.setTimeZone(GMT_TZ);
        } else {
            LOG.error("couldn't parse date: " + str, new Exception());
        }
        return cal;
    }

    /**
     * array of common date formats
     */
    private static final SimpleDateFormat COMMON_DATE_FORMATS[] = {
            new SimpleDateFormat("EEE' 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'ZZZZ"),
            new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy"), new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy zzz"),
            new SimpleDateFormat("EEE, MMM dd HH:mm:ss yyyy zzz"),
            new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"),
            new SimpleDateFormat("EEE,dd MMM yyyy HH:mm:ss zzz"),
            new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:sszzz"), new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss"),
            new SimpleDateFormat("EEE, dd-MMM-yy HH:mm:ss zzz"),
            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS zzz"), new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS"),
            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss zzz"), new SimpleDateFormat("yyyy/MM/dd"),
            new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"), new SimpleDateFormat("yyyy-MM-dd HH:mm"),
            new SimpleDateFormat("MM/dd/yyyy"), new SimpleDateFormat("MMM dd yyyy HH:mm:ss. zzz"),
            new SimpleDateFormat("MMM dd yyyy HH:mm:ss zzz"), new SimpleDateFormat("dd.MM.yyyy HH:mm:ss zzz"),
            new SimpleDateFormat("dd MM yyyy HH:mm:ss zzz"), new SimpleDateFormat("dd.MM.yyyy; HH:mm:ss"),
            new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"), new SimpleDateFormat("dd.MM.yyyy zzz") };

    /**
     * attempt to parse using common date formats
     *
     * @param d string date to parse
     * @return date or <code>null</code> if unable to parse
     * @see DateUtil#COMMON_DATE_FORMATS
     */
    public static java.util.Date parseUsingCommonDateFormats(String d) {
        for (SimpleDateFormat f : COMMON_DATE_FORMATS) {
            try {
                synchronized (f) {
                    return f.parse(d);
                }
            } catch (Exception ex) {
                if (LOG.isDebugEnabled())
                    LOG.debug("incompatible common date format " + f + " for date " + d);
            }
        }
        // sometimes, the timezone causes a problem such as 
        // -800 instead of -0800 - try to check for that
        // Apple's ITune RSS feed is a good example of bad dates/timezones
        int idx = d.lastIndexOf('-');
        if (idx > 0) {
            String tz = d.substring(idx + 1);
            if (tz.length() < 4) {
                // pad with a the 0 to correct the timezone
                String newDate = d.substring(0, idx) + "-0" + tz;
                return parseUsingCommonDateFormats(newDate);
            }
        }
        return null;
    }

    /**
     * compares two datess down to the second
     *
     * @param date1 first date
     * @param date2 second date
     * @return <code>true</code> if the dates equal to the second, <code>false</code> otherwise
     */
    public static boolean datesEqualToSecond(Date date1, Date date2) {
        Calendar calendar1 = new GregorianCalendar(GMT_TZ);
        calendar1.setTime(date1);
        Calendar calendar2 = new GregorianCalendar(GMT_TZ);
        calendar2.setTime(date2);

        if (calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR)) {
            if (calendar1.get(Calendar.DAY_OF_YEAR) == calendar2.get(Calendar.DAY_OF_YEAR)) {
                if (calendar1.get(Calendar.HOUR) == calendar2.get(Calendar.HOUR)) {
                    if (calendar1.get(Calendar.MINUTE) == calendar2.get(Calendar.MINUTE)) {
                        if (calendar1.get(Calendar.SECOND) == calendar2.get(Calendar.SECOND)) {
                            return true;
                        }
                    }
                }
            }
        }

        return false;
    }

    /**
     * given a date, return the beginning hour/minute/second of the day (basically, just after midnight)
     *
     * @param date date to determine beginning of day
     * @return beginning of day as date
     */
    public static Date getBeginningOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * given a date and an hour (+/-) return the exact hour with minute/second/ms at 0.  pass in a negative
     * number of go back a number of hours from date or positive to go forward.
     *
     * @param date  date to determine beginning of day
     * @param hours hours to adjust (plus or minus)
     * @return beginning of day as date (plus or minus specified hours)
     */
    public static Date getBeginningHourOfDay(Date date, int hours) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + hours);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * creates a date for sql with ms always at 0.
     *
     * @param date date to create sql date from.
     * @return sql date
     */
    public static Date createSqlDate(Date date) {
        if (null == date) {
            return date;
        }

        long timeInMillis = date.getTime();
        timeInMillis -= timeInMillis % 1000;
        return new Date(timeInMillis);
    }

    /**
     * returns true if the date passed in is today (regardless of time)
     * 
     * @param date
     * @return
     */
    public static boolean isToday(Date date) {
        Calendar now = Calendar.getInstance();
        Calendar then = Calendar.getInstance();
        then.setTime(date);
        return now.get(Calendar.DATE) == then.get(Calendar.DATE)
                && now.get(Calendar.YEAR) == then.get(Calendar.YEAR)
                && now.get(Calendar.MONTH) == then.get(Calendar.MONTH);
    }

    /**
     * gets today as a date
     *
     * @return today as date
     */
    public static Date today() {
        Calendar calendar = new GregorianCalendar(GMT_TZ);
        calendar.setTime(new Date());

        Calendar today = new GregorianCalendar(GMT_TZ);
        today.clear();
        today.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE));
        return today.getTime();
    }

    /**
     * gets tomorrow as a date
     *
     * @return tomorrow
     */
    public static Date tommorow() {
        Calendar calendar = new GregorianCalendar(GMT_TZ);
        calendar.setTime(new Date());

        Calendar tommorow = new GregorianCalendar(GMT_TZ);
        tommorow.clear();
        tommorow.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE));
        tommorow.add(Calendar.DATE, 1);
        return tommorow.getTime();
    }

    /**
     * gets now as a date
     *
     * @return now
     */
    public static Date now() {
        return createSqlDate(new Date());
    }
}