]>
Commit | Line | Data |
---|---|---|
cfd903b6 MG |
1 | /* |
2 | * Copyright (C) 2011 Google Inc. | |
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 | ||
17 | package com.google.gson.internal.bind; | |
18 | ||
19 | import com.google.gson.Gson; | |
20 | import com.google.gson.JsonSyntaxException; | |
21 | import com.google.gson.TypeAdapter; | |
22 | import com.google.gson.TypeAdapterFactory; | |
23 | import com.google.gson.reflect.TypeToken; | |
24 | import com.google.gson.stream.JsonReader; | |
25 | import com.google.gson.stream.JsonToken; | |
26 | import com.google.gson.stream.JsonWriter; | |
27 | import java.io.IOException; | |
28 | import java.text.DateFormat; | |
29 | import java.text.ParseException; | |
30 | import java.text.SimpleDateFormat; | |
31 | import java.util.Date; | |
32 | import java.util.Locale; | |
33 | import java.util.TimeZone; | |
34 | ||
35 | /** | |
36 | * Adapter for Date. Although this class appears stateless, it is not. | |
37 | * DateFormat captures its time zone and locale when it is created, which gives | |
38 | * this class state. DateFormat isn't thread safe either, so this class has | |
39 | * to synchronize its read and write methods. | |
40 | */ | |
41 | public final class DateTypeAdapter extends TypeAdapter<Date> { | |
42 | public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { | |
43 | @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal | |
44 | public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { | |
45 | return typeToken.getRawType() == Date.class ? (TypeAdapter<T>) new DateTypeAdapter() : null; | |
46 | } | |
47 | }; | |
48 | ||
49 | private final DateFormat enUsFormat | |
50 | = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US); | |
51 | private final DateFormat localFormat | |
52 | = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT); | |
53 | private final DateFormat iso8601Format = buildIso8601Format(); | |
54 | ||
55 | private static DateFormat buildIso8601Format() { | |
56 | DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); | |
57 | iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); | |
58 | return iso8601Format; | |
59 | } | |
60 | ||
61 | @Override public Date read(JsonReader in) throws IOException { | |
62 | if (in.peek() == JsonToken.NULL) { | |
63 | in.nextNull(); | |
64 | return null; | |
65 | } | |
66 | return deserializeToDate(in.nextString()); | |
67 | } | |
68 | ||
69 | private synchronized Date deserializeToDate(String json) { | |
70 | try { | |
71 | return localFormat.parse(json); | |
72 | } catch (ParseException ignored) { | |
73 | } | |
74 | try { | |
75 | return enUsFormat.parse(json); | |
76 | } catch (ParseException ignored) { | |
77 | } | |
78 | try { | |
79 | return iso8601Format.parse(json); | |
80 | } catch (ParseException e) { | |
81 | throw new JsonSyntaxException(json, e); | |
82 | } | |
83 | } | |
84 | ||
85 | @Override public synchronized void write(JsonWriter out, Date value) throws IOException { | |
86 | if (value == null) { | |
87 | out.nullValue(); | |
88 | return; | |
89 | } | |
90 | String dateFormatAsString = enUsFormat.format(value); | |
91 | out.value(dateFormatAsString); | |
92 | } | |
93 | } |