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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/DateUtils.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,259 @@
     1.4 +/*
     1.5 + * ====================================================================
     1.6 + * Licensed to the Apache Software Foundation (ASF) under one
     1.7 + * or more contributor license agreements.  See the NOTICE file
     1.8 + * distributed with this work for additional information
     1.9 + * regarding copyright ownership.  The ASF licenses this file
    1.10 + * to you under the Apache License, Version 2.0 (the
    1.11 + * "License"); you may not use this file except in compliance
    1.12 + * with the License.  You may obtain a copy of the License at
    1.13 + *
    1.14 + *   http://www.apache.org/licenses/LICENSE-2.0
    1.15 + *
    1.16 + * Unless required by applicable law or agreed to in writing,
    1.17 + * software distributed under the License is distributed on an
    1.18 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    1.19 + * KIND, either express or implied.  See the License for the
    1.20 + * specific language governing permissions and limitations
    1.21 + * under the License.
    1.22 + * ====================================================================
    1.23 + *
    1.24 + * This software consists of voluntary contributions made by many
    1.25 + * individuals on behalf of the Apache Software Foundation.  For more
    1.26 + * information on the Apache Software Foundation, please see
    1.27 + * <http://www.apache.org/>.
    1.28 + *
    1.29 + */
    1.30 +
    1.31 +package ch.boye.httpclientandroidlib.impl.cookie;
    1.32 +
    1.33 +import java.lang.ref.SoftReference;
    1.34 +import java.text.ParseException;
    1.35 +import java.text.SimpleDateFormat;
    1.36 +import java.util.Calendar;
    1.37 +import java.util.Date;
    1.38 +import java.util.HashMap;
    1.39 +import java.util.Locale;
    1.40 +import java.util.Map;
    1.41 +import java.util.TimeZone;
    1.42 +
    1.43 +import ch.boye.httpclientandroidlib.annotation.Immutable;
    1.44 +
    1.45 +/**
    1.46 + * A utility class for parsing and formatting HTTP dates as used in cookies and
    1.47 + * other headers.  This class handles dates as defined by RFC 2616 section
    1.48 + * 3.3.1 as well as some other common non-standard formats.
    1.49 + *
    1.50 + *
    1.51 + * @since 4.0
    1.52 + */
    1.53 +@Immutable
    1.54 +public final class DateUtils {
    1.55 +
    1.56 +    /**
    1.57 +     * Date format pattern used to parse HTTP date headers in RFC 1123 format.
    1.58 +     */
    1.59 +    public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
    1.60 +
    1.61 +    /**
    1.62 +     * Date format pattern used to parse HTTP date headers in RFC 1036 format.
    1.63 +     */
    1.64 +    public static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
    1.65 +
    1.66 +    /**
    1.67 +     * Date format pattern used to parse HTTP date headers in ANSI C
    1.68 +     * <code>asctime()</code> format.
    1.69 +     */
    1.70 +    public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
    1.71 +
    1.72 +    private static final String[] DEFAULT_PATTERNS = new String[] {
    1.73 +        PATTERN_RFC1036,
    1.74 +        PATTERN_RFC1123,
    1.75 +        PATTERN_ASCTIME
    1.76 +    };
    1.77 +
    1.78 +    private static final Date DEFAULT_TWO_DIGIT_YEAR_START;
    1.79 +
    1.80 +    public static final TimeZone GMT = TimeZone.getTimeZone("GMT");
    1.81 +
    1.82 +    static {
    1.83 +        Calendar calendar = Calendar.getInstance();
    1.84 +        calendar.setTimeZone(GMT);
    1.85 +        calendar.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
    1.86 +        calendar.set(Calendar.MILLISECOND, 0);
    1.87 +        DEFAULT_TWO_DIGIT_YEAR_START = calendar.getTime();
    1.88 +    }
    1.89 +
    1.90 +    /**
    1.91 +     * Parses a date value.  The formats used for parsing the date value are retrieved from
    1.92 +     * the default http params.
    1.93 +     *
    1.94 +     * @param dateValue the date value to parse
    1.95 +     *
    1.96 +     * @return the parsed date
    1.97 +     *
    1.98 +     * @throws DateParseException if the value could not be parsed using any of the
    1.99 +     * supported date formats
   1.100 +     */
   1.101 +    public static Date parseDate(String dateValue) throws DateParseException {
   1.102 +        return parseDate(dateValue, null, null);
   1.103 +    }
   1.104 +
   1.105 +    /**
   1.106 +     * Parses the date value using the given date formats.
   1.107 +     *
   1.108 +     * @param dateValue the date value to parse
   1.109 +     * @param dateFormats the date formats to use
   1.110 +     *
   1.111 +     * @return the parsed date
   1.112 +     *
   1.113 +     * @throws DateParseException if none of the dataFormats could parse the dateValue
   1.114 +     */
   1.115 +    public static Date parseDate(final String dateValue, String[] dateFormats)
   1.116 +        throws DateParseException {
   1.117 +        return parseDate(dateValue, dateFormats, null);
   1.118 +    }
   1.119 +
   1.120 +    /**
   1.121 +     * Parses the date value using the given date formats.
   1.122 +     *
   1.123 +     * @param dateValue the date value to parse
   1.124 +     * @param dateFormats the date formats to use
   1.125 +     * @param startDate During parsing, two digit years will be placed in the range
   1.126 +     * <code>startDate</code> to <code>startDate + 100 years</code>. This value may
   1.127 +     * be <code>null</code>. When <code>null</code> is given as a parameter, year
   1.128 +     * <code>2000</code> will be used.
   1.129 +     *
   1.130 +     * @return the parsed date
   1.131 +     *
   1.132 +     * @throws DateParseException if none of the dataFormats could parse the dateValue
   1.133 +     */
   1.134 +    public static Date parseDate(
   1.135 +        String dateValue,
   1.136 +        String[] dateFormats,
   1.137 +        Date startDate
   1.138 +    ) throws DateParseException {
   1.139 +
   1.140 +        if (dateValue == null) {
   1.141 +            throw new IllegalArgumentException("dateValue is null");
   1.142 +        }
   1.143 +        if (dateFormats == null) {
   1.144 +            dateFormats = DEFAULT_PATTERNS;
   1.145 +        }
   1.146 +        if (startDate == null) {
   1.147 +            startDate = DEFAULT_TWO_DIGIT_YEAR_START;
   1.148 +        }
   1.149 +        // trim single quotes around date if present
   1.150 +        // see issue #5279
   1.151 +        if (dateValue.length() > 1
   1.152 +            && dateValue.startsWith("'")
   1.153 +            && dateValue.endsWith("'")
   1.154 +        ) {
   1.155 +            dateValue = dateValue.substring (1, dateValue.length() - 1);
   1.156 +        }
   1.157 +
   1.158 +        for (String dateFormat : dateFormats) {
   1.159 +            SimpleDateFormat dateParser = DateFormatHolder.formatFor(dateFormat);
   1.160 +            dateParser.set2DigitYearStart(startDate);
   1.161 +
   1.162 +            try {
   1.163 +                return dateParser.parse(dateValue);
   1.164 +            } catch (ParseException pe) {
   1.165 +                // ignore this exception, we will try the next format
   1.166 +            }
   1.167 +        }
   1.168 +
   1.169 +        // we were unable to parse the date
   1.170 +        throw new DateParseException("Unable to parse the date " + dateValue);
   1.171 +    }
   1.172 +
   1.173 +    /**
   1.174 +     * Formats the given date according to the RFC 1123 pattern.
   1.175 +     *
   1.176 +     * @param date The date to format.
   1.177 +     * @return An RFC 1123 formatted date string.
   1.178 +     *
   1.179 +     * @see #PATTERN_RFC1123
   1.180 +     */
   1.181 +    public static String formatDate(Date date) {
   1.182 +        return formatDate(date, PATTERN_RFC1123);
   1.183 +    }
   1.184 +
   1.185 +    /**
   1.186 +     * Formats the given date according to the specified pattern.  The pattern
   1.187 +     * must conform to that used by the {@link SimpleDateFormat simple date
   1.188 +     * format} class.
   1.189 +     *
   1.190 +     * @param date The date to format.
   1.191 +     * @param pattern The pattern to use for formatting the date.
   1.192 +     * @return A formatted date string.
   1.193 +     *
   1.194 +     * @throws IllegalArgumentException If the given date pattern is invalid.
   1.195 +     *
   1.196 +     * @see SimpleDateFormat
   1.197 +     */
   1.198 +    public static String formatDate(Date date, String pattern) {
   1.199 +        if (date == null) throw new IllegalArgumentException("date is null");
   1.200 +        if (pattern == null) throw new IllegalArgumentException("pattern is null");
   1.201 +
   1.202 +        SimpleDateFormat formatter = DateFormatHolder.formatFor(pattern);
   1.203 +        return formatter.format(date);
   1.204 +    }
   1.205 +
   1.206 +    /** This class should not be instantiated. */
   1.207 +    private DateUtils() {
   1.208 +    }
   1.209 +
   1.210 +    /**
   1.211 +     * A factory for {@link SimpleDateFormat}s. The instances are stored in a
   1.212 +     * threadlocal way because SimpleDateFormat is not threadsafe as noted in
   1.213 +     * {@link SimpleDateFormat its javadoc}.
   1.214 +     *
   1.215 +     */
   1.216 +    final static class DateFormatHolder {
   1.217 +
   1.218 +        private static final ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>
   1.219 +            THREADLOCAL_FORMATS = new ThreadLocal<SoftReference<Map<String, SimpleDateFormat>>>() {
   1.220 +
   1.221 +            @Override
   1.222 +            protected SoftReference<Map<String, SimpleDateFormat>> initialValue() {
   1.223 +                return new SoftReference<Map<String, SimpleDateFormat>>(
   1.224 +                        new HashMap<String, SimpleDateFormat>());
   1.225 +            }
   1.226 +
   1.227 +        };
   1.228 +
   1.229 +        /**
   1.230 +         * creates a {@link SimpleDateFormat} for the requested format string.
   1.231 +         *
   1.232 +         * @param pattern
   1.233 +         *            a non-<code>null</code> format String according to
   1.234 +         *            {@link SimpleDateFormat}. The format is not checked against
   1.235 +         *            <code>null</code> since all paths go through
   1.236 +         *            {@link DateUtils}.
   1.237 +         * @return the requested format. This simple dateformat should not be used
   1.238 +         *         to {@link SimpleDateFormat#applyPattern(String) apply} to a
   1.239 +         *         different pattern.
   1.240 +         */
   1.241 +        public static SimpleDateFormat formatFor(String pattern) {
   1.242 +            SoftReference<Map<String, SimpleDateFormat>> ref = THREADLOCAL_FORMATS.get();
   1.243 +            Map<String, SimpleDateFormat> formats = ref.get();
   1.244 +            if (formats == null) {
   1.245 +                formats = new HashMap<String, SimpleDateFormat>();
   1.246 +                THREADLOCAL_FORMATS.set(
   1.247 +                        new SoftReference<Map<String, SimpleDateFormat>>(formats));
   1.248 +            }
   1.249 +
   1.250 +            SimpleDateFormat format = formats.get(pattern);
   1.251 +            if (format == null) {
   1.252 +                format = new SimpleDateFormat(pattern, Locale.US);
   1.253 +                format.setTimeZone(TimeZone.getTimeZone("GMT"));
   1.254 +                formats.put(pattern, format);
   1.255 +            }
   1.256 +
   1.257 +            return format;
   1.258 +        }
   1.259 +
   1.260 +    }
   1.261 +
   1.262 +}

mercurial