Fix date adapters to work when run in any time zone.
This commit is contained in:
parent
cebda2b119
commit
3f26144165
@ -30,6 +30,7 @@ import com.google.gson.internal.bind.MapTypeAdapterFactory;
|
||||
import com.google.gson.internal.bind.MiniGson;
|
||||
import com.google.gson.internal.bind.ObjectTypeAdapter;
|
||||
import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
|
||||
import com.google.gson.internal.bind.SqlDateTypeAdapter;
|
||||
import com.google.gson.internal.bind.TimeTypeAdapter;
|
||||
import com.google.gson.internal.bind.TypeAdapter;
|
||||
import com.google.gson.internal.bind.TypeAdapters;
|
||||
@ -259,8 +260,8 @@ public final class Gson {
|
||||
.factory(DateTypeAdapter.FACTORY)
|
||||
.factory(TypeAdapters.CALENDAR_FACTORY)
|
||||
.factory(TimeTypeAdapter.FACTORY)
|
||||
.factory(TypeAdapters.SQL_DATE_FACTORY)
|
||||
.factory(TypeAdapters.SQL_TIMESTAMP_FACTORY)
|
||||
.factory(SqlDateTypeAdapter.FACTORY)
|
||||
.factory(TypeAdapters.TIMESTAMP_FACTORY)
|
||||
.factory(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization))
|
||||
.factory(ArrayTypeAdapter.FACTORY)
|
||||
.factory(TypeAdapters.ENUM_FACTORY)
|
||||
|
@ -29,7 +29,7 @@ import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Adapter for Time. Although this class appears stateless, it is not.
|
||||
* Adapter for Date. Although this class appears stateless, it is not.
|
||||
* DateFormat captures its time zone and locale when it is created, which gives
|
||||
* this class state. DateFormat isn't thread safe either, so this class has
|
||||
* to synchronize its read and write methods.
|
||||
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.gson.internal.bind;
|
||||
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* Adapter for java.sql.Date. Although this class appears stateless, it is not.
|
||||
* DateFormat captures its time zone and locale when it is created, which gives
|
||||
* this class state. DateFormat isn't thread safe either, so this class has
|
||||
* to synchronize its read and write methods.
|
||||
*/
|
||||
public final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
|
||||
public static final Factory FACTORY = new Factory() {
|
||||
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
|
||||
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
|
||||
return typeToken.getRawType() == java.sql.Date.class
|
||||
? (TypeAdapter<T>) new SqlDateTypeAdapter() : null;
|
||||
}
|
||||
};
|
||||
|
||||
private final DateFormat format = new SimpleDateFormat("MMM d, yyyy");
|
||||
|
||||
@Override
|
||||
public synchronized java.sql.Date read(JsonReader reader) throws IOException {
|
||||
try {
|
||||
final long utilDate = format.parse(reader.nextString()).getTime();
|
||||
return new java.sql.Date(utilDate);
|
||||
} catch (ParseException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(JsonWriter writer, java.sql.Date value) throws IOException {
|
||||
writer.value(format.format(value));
|
||||
}
|
||||
}
|
@ -29,9 +29,6 @@ import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.BitSet;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
@ -53,7 +50,7 @@ public final class TypeAdapters {
|
||||
int i = 0;
|
||||
JsonToken tokenType = reader.peek();
|
||||
while (tokenType != JsonToken.END_ARRAY) {
|
||||
boolean set = false;
|
||||
boolean set;
|
||||
switch (tokenType) {
|
||||
case NUMBER:
|
||||
set = reader.nextInt() != 0;
|
||||
@ -411,52 +408,27 @@ public final class TypeAdapters {
|
||||
|
||||
public static final TypeAdapter.Factory UUID_FACTORY = newFactory(UUID.class, UUID);
|
||||
|
||||
private static final class TimestampTypeAdapter extends TypeAdapter<Timestamp> {
|
||||
private final MiniGson context;
|
||||
public TimestampTypeAdapter(MiniGson context) {
|
||||
this.context = context;
|
||||
}
|
||||
@Override
|
||||
public Timestamp read(JsonReader reader) throws IOException {
|
||||
TypeAdapter<Date> dateTypeAdapter = context.getAdapter(Date.class);
|
||||
Date date = dateTypeAdapter.read(reader);
|
||||
return new java.sql.Timestamp(date.getTime());
|
||||
}
|
||||
@Override
|
||||
public void write(JsonWriter writer, Timestamp value) throws IOException {
|
||||
TypeAdapter<Date> dateTypeAdapter = context.getAdapter(Date.class);
|
||||
dateTypeAdapter.write(writer, value);
|
||||
}
|
||||
};
|
||||
public static final TypeAdapter.Factory SQL_TIMESTAMP_FACTORY = new TypeAdapter.Factory() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final TypeAdapter.Factory TIMESTAMP_FACTORY = new TypeAdapter.Factory() {
|
||||
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
|
||||
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
|
||||
return typeToken.getRawType() == Timestamp.class
|
||||
? (TypeAdapter<T>) new TimestampTypeAdapter(context) : null;
|
||||
}
|
||||
};
|
||||
|
||||
public static final TypeAdapter<java.sql.Date> SQL_DATE = new TypeAdapter<java.sql.Date>() {
|
||||
private final DateFormat format = new SimpleDateFormat("MMM d, yyyy");
|
||||
@Override
|
||||
public java.sql.Date read(JsonReader reader) throws IOException {
|
||||
try {
|
||||
synchronized (format) {
|
||||
Date date = format.parse(reader.nextString());
|
||||
return new java.sql.Date(date.getTime());
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
if (typeToken.getRawType() != Timestamp.class) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void write(JsonWriter writer, java.sql.Date value) throws IOException {
|
||||
writer.value(format.format(value));
|
||||
|
||||
final TypeAdapter<Date> dateTypeAdapter = context.getAdapter(Date.class);
|
||||
return (TypeAdapter<T>) new TypeAdapter<Timestamp>() {
|
||||
@Override public Timestamp read(JsonReader reader) throws IOException {
|
||||
Date date = dateTypeAdapter.read(reader);
|
||||
return new Timestamp(date.getTime());
|
||||
}
|
||||
|
||||
@Override public void write(JsonWriter writer, Timestamp value) throws IOException {
|
||||
dateTypeAdapter.write(writer, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
public static final TypeAdapter.Factory SQL_DATE_FACTORY = newFactory(java.sql.Date.class, SQL_DATE);
|
||||
|
||||
public static final TypeAdapter<Calendar> CALENDAR = new TypeAdapter<Calendar>() {
|
||||
private static final String YEAR = "year";
|
||||
private static final String MONTH = "month";
|
||||
@ -633,4 +605,5 @@ public final class TypeAdapters {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user