1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.net.http;
18
19import java.text.DateFormat;
20import java.text.ParseException;
21import java.text.SimpleDateFormat;
22import java.util.Date;
23import java.util.Locale;
24import java.util.TimeZone;
25
26/**
27 * Best-effort parser for HTTP dates.
28 */
29public final class HttpDate {
30
31    /**
32     * Most websites serve cookies in the blessed format. Eagerly create the parser to ensure such
33     * cookies are on the fast path.
34     */
35    private static final ThreadLocal<DateFormat> STANDARD_DATE_FORMAT
36            = new ThreadLocal<DateFormat>() {
37        @Override protected DateFormat initialValue() {
38            DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
39            rfc1123.setTimeZone(TimeZone.getTimeZone("UTC"));
40            return rfc1123;
41        }
42    };
43
44    /**
45     * If we fail to parse a date in a non-standard format, try each of these formats in sequence.
46     */
47    private static final String[] BROWSER_COMPATIBLE_DATE_FORMATS = new String[] {
48            /* This list comes from  {@code org.apache.http.impl.cookie.BrowserCompatSpec}. */
49            "EEEE, dd-MMM-yy HH:mm:ss zzz", // RFC 1036
50            "EEE MMM d HH:mm:ss yyyy", // ANSI C asctime()
51            "EEE, dd-MMM-yyyy HH:mm:ss z",
52            "EEE, dd-MMM-yyyy HH-mm-ss z",
53            "EEE, dd MMM yy HH:mm:ss z",
54            "EEE dd-MMM-yyyy HH:mm:ss z",
55            "EEE dd MMM yyyy HH:mm:ss z",
56            "EEE dd-MMM-yyyy HH-mm-ss z",
57            "EEE dd-MMM-yy HH:mm:ss z",
58            "EEE dd MMM yy HH:mm:ss z",
59            "EEE,dd-MMM-yy HH:mm:ss z",
60            "EEE,dd-MMM-yyyy HH:mm:ss z",
61            "EEE, dd-MM-yyyy HH:mm:ss z",
62
63            /* RI bug 6641315 claims a cookie of this format was once served by www.yahoo.com */
64            "EEE MMM d yyyy HH:mm:ss z",
65    };
66
67    /**
68     * Returns the date for {@code value}. Returns null if the value couldn't be
69     * parsed.
70     */
71    public static Date parse(String value) {
72        try {
73            return STANDARD_DATE_FORMAT.get().parse(value);
74        } catch (ParseException ignore) {
75        }
76        for (String formatString : BROWSER_COMPATIBLE_DATE_FORMATS) {
77            try {
78                return new SimpleDateFormat(formatString, Locale.US).parse(value);
79            } catch (ParseException ignore) {
80            }
81        }
82        return null;
83    }
84
85    /**
86     * Returns the string for {@code value}.
87     */
88    public static String format(Date value) {
89        return STANDARD_DATE_FORMAT.get().format(value);
90    }
91}
92