mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateUtils.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2  * ====================================================================
     3  * Licensed to the Apache Software Foundation (ASF) under one
     4  * or more contributor license agreements.  See the NOTICE file
     5  * distributed with this work for additional information
     6  * regarding copyright ownership.  The ASF licenses this file
     7  * to you under the Apache License, Version 2.0 (the
     8  * "License"); you may not use this file except in compliance
     9  * with the License.  You may obtain a copy of the License at
    10  *
    11  *   http://www.apache.org/licenses/LICENSE-2.0
    12  *
    13  * Unless required by applicable law or agreed to in writing,
    14  * software distributed under the License is distributed on an
    15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    16  * KIND, either express or implied.  See the License for the
    17  * specific language governing permissions and limitations
    18  * under the License.
    19  * ====================================================================
    20  *
    21  * This software consists of voluntary contributions made by many
    22  * individuals on behalf of the Apache Software Foundation.  For more
    23  * information on the Apache Software Foundation, please see
    24  * <http://www.apache.org/>.
    25  *
    26  */
    28 package ch.boye.httpclientandroidlib.impl.cookie;
    30 import java.lang.ref.SoftReference;
    31 import java.text.ParseException;
    32 import java.text.SimpleDateFormat;
    33 import java.util.Calendar;
    34 import java.util.Date;
    35 import java.util.HashMap;
    36 import java.util.Locale;
    37 import java.util.Map;
    38 import java.util.TimeZone;
    40 import ch.boye.httpclientandroidlib.annotation.Immutable;
    42 /**
    43  * A utility class for parsing and formatting HTTP dates as used in cookies and
    44  * other headers.  This class handles dates as defined by RFC 2616 section
    45  * 3.3.1 as well as some other common non-standard formats.
    46  *
    47  *
    48  * @since 4.0
    49  */
    50 @Immutable
    51 public final class DateUtils {
    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";
    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";
    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";
    69     private static final String[] DEFAULT_PATTERNS = new String[] {
    70         PATTERN_RFC1036,
    71         PATTERN_RFC1123,
    72         PATTERN_ASCTIME
    73     };
    75     private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
    77     public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
    79     static {
    80         Calendar calendar = Calendar.getInstance();
    81         calendar.setTimeZone(GMT);
    82         calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
    83         calendar.set(Calendar.MILLISECOND, 0);
    84         DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
    85     }
    87     /**
    88      * Parses a date value.  The formats used for parsing the date value are retrieved from
    89      * the default http params.
    90      *
    91      * @param dateValue the date value to parse
    92      *
    93      * @return the parsed date
    94      *
    95      * @throws DateParseException if the value could not be parsed using any of the
    96      * supported date formats
    97      */
    98     public static Date parseDate(String dateValue) throws DateParseException {
    99         return parseDate(dateValue, null, null);
   100     }
   102     /**
   103      * Parses the date value using the given date formats.
   104      *
   105      * @param dateValue the date value to parse
   106      * @param dateFormats the date formats to use
   107      *
   108      * @return the parsed date
   109      *
   110      * @throws DateParseException if none of the dataFormats could parse the dateValue
   111      */
   112     public static Date parseDate(final String dateValue, String[] dateFormats)
   113         throws DateParseException {
   114         return parseDate(dateValue, dateFormats, null);
   115     }
   117     /**
   118      * Parses the date value using the given date formats.
   119      *
   120      * @param dateValue the date value to parse
   121      * @param dateFormats the date formats to use
   122      * @param startDate During parsing, two digit years will be placed in the range
   123      * <code>startDate</code> to <code>startDate + 100 years</code>. This value may
   124      * be <code>null</code>. When <code>null</code> is given as a parameter, year
   125      * <code>2000</code> will be used.
   126      *
   127      * @return the parsed date
   128      *
   129      * @throws DateParseException if none of the dataFormats could parse the dateValue
   130      */
   131     public static Date parseDate(
   132         String dateValue,
   133         String[] dateFormats,
   134         Date startDate
   135     ) throws DateParseException {
   137         if (dateValue == null) {
   138             throw new IllegalArgumentException("dateValue is null");
   139         }
   140         if (dateFormats == null) {
   141             dateFormats = DEFAULT_PATTERNS;
   142         }
   143         if (startDate == null) {
   144             startDate = DEFAULT_TWO_DIGIT_YEAR_START;
   145         }
   146         // trim single quotes around date if present
   147         // see issue #5279
   148         if (dateValue.length() > 1
   149             && dateValue.startsWith("'")
   150             && dateValue.endsWith("'")
   151         ) {
   152             dateValue = dateValue.substring (1, dateValue.length() - 1);
   153         }
   155         for (String dateFormat : dateFormats) {
   156             SimpleDateFormat dateParser = DateFormatHolder.formatFor(dateFormat);
   157             dateParser.set2DigitYearStart(startDate);
   159             try {
   160                 return dateParser.parse(dateValue);
   161             } catch (ParseException pe) {
   162                 // ignore this exception, we will try the next format
   163             }
   164         }
   166         // we were unable to parse the date
   167         throw new DateParseException("Unable to parse the date " + dateValue);
   168     }
   170     /**
   171      * Formats the given date according to the RFC 1123 pattern.
   172      *
   173      * @param date The date to format.
   174      * @return An RFC 1123 formatted date string.
   175      *
   176      * @see #PATTERN_RFC1123
   177      */
   178     public static String formatDate(Date date) {
   179         return formatDate(date, PATTERN_RFC1123);
   180     }
   182     /**
   183      * Formats the given date according to the specified pattern.  The pattern
   184      * must conform to that used by the {@link SimpleDateFormat simple date
   185      * format} class.
   186      *
   187      * @param date The date to format.
   188      * @param pattern The pattern to use for formatting the date.
   189      * @return A formatted date string.
   190      *
   191      * @throws IllegalArgumentException If the given date pattern is invalid.
   192      *
   193      * @see SimpleDateFormat
   194      */
   195     public static String formatDate(Date date, String pattern) {
   196         if (date == null) throw new IllegalArgumentException("date is null");
   197         if (pattern == null) throw new IllegalArgumentException("pattern is null");
   199         SimpleDateFormat formatter = DateFormatHolder.formatFor(pattern);
   200         return formatter.format(date);
   201     }
   203     /** This class should not be instantiated. */
   204     private DateUtils() {
   205     }
   207     /**
   208      * A factory for {@link SimpleDateFormat}s. The instances are stored in a
   209      * threadlocal way because SimpleDateFormat is not threadsafe as noted in
   210      * {@link SimpleDateFormat its javadoc}.
   211      *
   212      */
   213     final static class DateFormatHolder {
   215         private static final ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>
   216             THREADLOCAL_FORMATS = new ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>() {
   218             @Override
   219             protected SoftReference<Map<String, SimpleDateFormat>> initialValue() {
   220                 return new SoftReference<Map<String, SimpleDateFormat>>(
   221                         new HashMap<String, SimpleDateFormat>());
   222             }
   224         };
   226         /**
   227          * creates a {@link SimpleDateFormat} for the requested format string.
   228          *
   229          * @param pattern
   230          *            a non-<code>null</code> format String according to
   231          *            {@link SimpleDateFormat}. The format is not checked against
   232          *            <code>null</code> since all paths go through
   233          *            {@link DateUtils}.
   234          * @return the requested format. This simple dateformat should not be used
   235          *         to {@link SimpleDateFormat#applyPattern(String) apply} to a
   236          *         different pattern.
   237          */
   238         public static SimpleDateFormat formatFor(String pattern) {
   239             SoftReference<Map<String, SimpleDateFormat>> ref = THREADLOCAL_FORMATS.get();
   240             Map<String, SimpleDateFormat> formats = ref.get();
   241             if (formats == null) {
   242                 formats = new HashMap<String, SimpleDateFormat>();
   243                 THREADLOCAL_FORMATS.set(
   244                         new SoftReference<Map<String, SimpleDateFormat>>(formats));
   245             }
   247             SimpleDateFormat format = formats.get(pattern);
   248             if (format == null) {
   249                 format = new SimpleDateFormat(pattern, Locale.US);
   250                 format.setTimeZone(TimeZone.getTimeZone("GMT"));
   251                 formats.put(pattern, format);
   252             }
   254             return format;
   255         }
   257     }
   259 }

mercurial