View Javadoc

    1   /*
    2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/util/DateUtil.java,v 1.2 2004/12/24 20:36:13 olegk Exp $
    3    * $Revision: 480424 $
    4    * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
    5    *
    6    * ====================================================================
    7    *
    8    *  Licensed to the Apache Software Foundation (ASF) under one or more
    9    *  contributor license agreements.  See the NOTICE file distributed with
    10   *  this work for additional information regarding copyright ownership.
    11   *  The ASF licenses this file to You under the Apache License, Version 2.0
    12   *  (the "License"); you may not use this file except in compliance with
    13   *  the License.  You may obtain a copy of the License at
    14   *
    15   *      http://www.apache.org/licenses/LICENSE-2.0
    16   *
    17   *  Unless required by applicable law or agreed to in writing, software
    18   *  distributed under the License is distributed on an "AS IS" BASIS,
    19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    20   *  See the License for the specific language governing permissions and
    21   *  limitations under the License.
    22   * ====================================================================
    23   *
    24   * This software consists of voluntary contributions made by many
    25   * individuals on behalf of the Apache Software Foundation.  For more
    26   * information on the Apache Software Foundation, please see
    27   * <http://www.apache.org/>.
    28   *
    29   */
    30
    31  package org.apache.commons.httpclient.util;
    32
    33  import java.text.ParseException;
    34  import java.text.SimpleDateFormat;
    35  import java.util.Arrays;
    36  import java.util.Calendar;
    37  import java.util.Collection;
    38  import java.util.Date;
    39  import java.util.Iterator;
    40  import java.util.Locale;
    41  import java.util.TimeZone;
    42
    43  /**
    44   * A utility class for parsing and formatting HTTP dates as used in cookies and
    45   * other headers.  This class handles dates as defined by RFC 2616 section
    46   * 3.3.1 as well as some other common non-standard formats.
    47   *
    48   * @author Christopher Brown
    49   * @author Michael Becke
    50   */
    51  public class DateUtil {
    52
    53      /**
    54       * Date format pattern used to parse HTTP date headers in RFC 1123 format.
    55       */
    56      public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
    57
    58      /**
    59       * Date format pattern used to parse HTTP date headers in RFC 1036 format.
    60       */
    61      public static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
    62
    63      /**
    64       * Date format pattern used to parse HTTP date headers in ANSI C
    65       * <code>asctime()</code> format.
    66       */
    67      public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
    68
    69      private static final Collection DEFAULT_PATTERNS = Arrays.asList(
    70      		new String[] { PATTERN_ASCTIME, PATTERN_RFC1036, PATTERN_RFC1123 } );
    71
    72      private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
    73
    74      static {
    75          Calendar calendar = Calendar.getInstance();
    76          calendar.set(2000, Calendar.JANUARY, 1, 0, 0);
    77          DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
    78      }
    79
    80      private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
    81
    82      /**
    83       * Parses a date value.  The formats used for parsing the date value are retrieved from
    84       * the default http params.
    85       *
    86       * @param dateValue the date value to parse
    87       *
    88       * @return the parsed date
    89       *
    90       * @throws DateParseException if the value could not be parsed using any of the
    91       * supported date formats
    92       */
    93      public static Date parseDate(String dateValue) throws DateParseException {
    94          return parseDate(dateValue, null, null);
    95      }
    96
    97      /**
    98       * Parses the date value using the given date formats.
    99       *
    100      * @param dateValue the date value to parse
    101      * @param dateFormats the date formats to use
    102      *
    103      * @return the parsed date
    104      *
    105      * @throws DateParseException if none of the dataFormats could parse the dateValue
    106      */
    107     public static Date parseDate(String dateValue, Collection dateFormats)
    108         throws DateParseException {
    109         return parseDate(dateValue, dateFormats, null);
    110     }
    111
    112     /**
    113      * Parses the date value using the given date formats.
    114      *
    115      * @param dateValue the date value to parse
    116      * @param dateFormats the date formats to use
    117      * @param startDate During parsing, two digit years will be placed in the range
    118      * <code>startDate</code> to <code>startDate + 100 years</code>. This value may
    119      * be <code>null</code>. When <code>null</code> is given as a parameter, year
    120      * <code>2000</code> will be used.
    121      *
    122      * @return the parsed date
    123      *
    124      * @throws DateParseException if none of the dataFormats could parse the dateValue
    125      */
    126     public static Date parseDate(
    127         String dateValue,
    128         Collection dateFormats,
    129         Date startDate
    130     ) throws DateParseException {
    131
    132         if (dateValue == null) {
    133             throw new IllegalArgumentException("dateValue is null");
    134         }
    135         if (dateFormats == null) {
    136         	dateFormats = DEFAULT_PATTERNS;
    137         }
    138         if (startDate == null) {
    139             startDate = DEFAULT_TWO_DIGIT_YEAR_START;
    140         }
    141         // trim single quotes around date if present
    142         // see issue #5279
    143         if (dateValue.length() > 1
    144             && dateValue.startsWith("'")
    145             && dateValue.endsWith("'")
    146         ) {
    147             dateValue = dateValue.substring (1, dateValue.length() - 1);
    148         }
    149
    150         SimpleDateFormat dateParser = null;
    151         Iterator formatIter = dateFormats.iterator();
    152
    153         while (formatIter.hasNext()) {
    154             String format = (String) formatIter.next();
    155             if (dateParser == null) {
    156                 dateParser = new SimpleDateFormat(format, Locale.US);
    157                 dateParser.setTimeZone(TimeZone.getTimeZone("GMT"));
    158                 dateParser.set2DigitYearStart(startDate);
    159             } else {
    160                 dateParser.applyPattern(format);
    161             }
    162             try {
    163                 return dateParser.parse(dateValue);
    164             } catch (ParseException pe) {
    165                 // ignore this exception, we will try the next format
    166             }
    167         }
    168
    169         // we were unable to parse the date
    170         throw new DateParseException("Unable to parse the date " + dateValue);
    171     }
    172
    173     /**
    174      * Formats the given date according to the RFC 1123 pattern.
    175      *
    176      * @param date The date to format.
    177      * @return An RFC 1123 formatted date string.
    178      *
    179      * @see #PATTERN_RFC1123
    180      */
    181     public static String formatDate(Date date) {
    182         return formatDate(date, PATTERN_RFC1123);
    183     }
    184
    185     /**
    186      * Formats the given date according to the specified pattern.  The pattern
    187      * must conform to that used by the {@link SimpleDateFormat simple date
    188      * format} class.
    189      *
    190      * @param date The date to format.
    191      * @param pattern The pattern to use for formatting the date.
    192      * @return A formatted date string.
    193      *
    194      * @throws IllegalArgumentException If the given date pattern is invalid.
    195      *
    196      * @see SimpleDateFormat
    197      */
    198     public static String formatDate(Date date, String pattern) {
    199         if (date == null) throw new IllegalArgumentException("date is null");
    200         if (pattern == null) throw new IllegalArgumentException("pattern is null");
    201
    202         SimpleDateFormat formatter = new SimpleDateFormat(pattern, Locale.US);
    203         formatter.setTimeZone(GMT);
    204         return formatter.format(date);
    205     }
    206
    207     /** This class should not be instantiated. */
    208     private DateUtil() { }
    209
    210 }