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.MiniGson;
|
||||||
import com.google.gson.internal.bind.ObjectTypeAdapter;
|
import com.google.gson.internal.bind.ObjectTypeAdapter;
|
||||||
import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
|
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.TimeTypeAdapter;
|
||||||
import com.google.gson.internal.bind.TypeAdapter;
|
import com.google.gson.internal.bind.TypeAdapter;
|
||||||
import com.google.gson.internal.bind.TypeAdapters;
|
import com.google.gson.internal.bind.TypeAdapters;
|
||||||
@ -259,8 +260,8 @@ public final class Gson {
|
|||||||
.factory(DateTypeAdapter.FACTORY)
|
.factory(DateTypeAdapter.FACTORY)
|
||||||
.factory(TypeAdapters.CALENDAR_FACTORY)
|
.factory(TypeAdapters.CALENDAR_FACTORY)
|
||||||
.factory(TimeTypeAdapter.FACTORY)
|
.factory(TimeTypeAdapter.FACTORY)
|
||||||
.factory(TypeAdapters.SQL_DATE_FACTORY)
|
.factory(SqlDateTypeAdapter.FACTORY)
|
||||||
.factory(TypeAdapters.SQL_TIMESTAMP_FACTORY)
|
.factory(TypeAdapters.TIMESTAMP_FACTORY)
|
||||||
.factory(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization))
|
.factory(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization))
|
||||||
.factory(ArrayTypeAdapter.FACTORY)
|
.factory(ArrayTypeAdapter.FACTORY)
|
||||||
.factory(TypeAdapters.ENUM_FACTORY)
|
.factory(TypeAdapters.ENUM_FACTORY)
|
||||||
|
@ -29,7 +29,7 @@ import java.util.Locale;
|
|||||||
import java.util.TimeZone;
|
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
|
* 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
|
* this class state. DateFormat isn't thread safe either, so this class has
|
||||||
* to synchronize its read and write methods.
|
* 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.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -53,7 +50,7 @@ public final class TypeAdapters {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
JsonToken tokenType = reader.peek();
|
JsonToken tokenType = reader.peek();
|
||||||
while (tokenType != JsonToken.END_ARRAY) {
|
while (tokenType != JsonToken.END_ARRAY) {
|
||||||
boolean set = false;
|
boolean set;
|
||||||
switch (tokenType) {
|
switch (tokenType) {
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
set = reader.nextInt() != 0;
|
set = reader.nextInt() != 0;
|
||||||
@ -411,52 +408,27 @@ public final class TypeAdapters {
|
|||||||
|
|
||||||
public static final TypeAdapter.Factory UUID_FACTORY = newFactory(UUID.class, UUID);
|
public static final TypeAdapter.Factory UUID_FACTORY = newFactory(UUID.class, UUID);
|
||||||
|
|
||||||
private static final class TimestampTypeAdapter extends TypeAdapter<Timestamp> {
|
public static final TypeAdapter.Factory TIMESTAMP_FACTORY = new TypeAdapter.Factory() {
|
||||||
private final MiniGson context;
|
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
|
||||||
public TimestampTypeAdapter(MiniGson context) {
|
public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> typeToken) {
|
||||||
this.context = context;
|
if (typeToken.getRawType() != Timestamp.class) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public Timestamp read(JsonReader reader) throws IOException {
|
final TypeAdapter<Date> dateTypeAdapter = context.getAdapter(Date.class);
|
||||||
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);
|
Date date = dateTypeAdapter.read(reader);
|
||||||
return new java.sql.Timestamp(date.getTime());
|
return new Timestamp(date.getTime());
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public void write(JsonWriter writer, Timestamp value) throws IOException {
|
@Override public void write(JsonWriter writer, Timestamp value) throws IOException {
|
||||||
TypeAdapter<Date> dateTypeAdapter = context.getAdapter(Date.class);
|
|
||||||
dateTypeAdapter.write(writer, value);
|
dateTypeAdapter.write(writer, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
public static final TypeAdapter.Factory SQL_TIMESTAMP_FACTORY = new TypeAdapter.Factory() {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void write(JsonWriter writer, java.sql.Date value) throws IOException {
|
|
||||||
writer.value(format.format(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>() {
|
public static final TypeAdapter<Calendar> CALENDAR = new TypeAdapter<Calendar>() {
|
||||||
private static final String YEAR = "year";
|
private static final String YEAR = "year";
|
||||||
private static final String MONTH = "month";
|
private static final String MONTH = "month";
|
||||||
@ -633,4 +605,5 @@ public final class TypeAdapters {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user