Make dependency on java.sql optional

This commit is contained in:
Marcono1234 2020-05-09 17:37:21 +02:00
parent 361292f1c1
commit 380c4ec12c
11 changed files with 273 additions and 134 deletions

View File

@ -49,9 +49,8 @@ import com.google.gson.internal.bind.JsonTreeWriter;
import com.google.gson.internal.bind.MapTypeAdapterFactory;
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.TypeAdapters;
import com.google.gson.internal.sql.SqlTypesSupport;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
@ -262,9 +261,13 @@ public final class Gson {
factories.add(TypeAdapters.BIT_SET_FACTORY);
factories.add(DateTypeAdapter.FACTORY);
factories.add(TypeAdapters.CALENDAR_FACTORY);
factories.add(TimeTypeAdapter.FACTORY);
factories.add(SqlDateTypeAdapter.FACTORY);
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
if (SqlTypesSupport.SUPPORTS_SQL_TYPES) {
factories.add(SqlTypesSupport.TIME_FACTORY);
factories.add(SqlTypesSupport.DATE_FACTORY);
factories.add(SqlTypesSupport.TIMESTAMP_FACTORY);
}
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);

View File

@ -17,7 +17,6 @@
package com.google.gson;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
@ -28,8 +27,10 @@ import java.util.Map;
import com.google.gson.internal.$Gson$Preconditions;
import com.google.gson.internal.Excluder;
import com.google.gson.internal.bind.DefaultDateTypeAdapter;
import com.google.gson.internal.bind.TreeTypeAdapter;
import com.google.gson.internal.bind.TypeAdapters;
import com.google.gson.internal.sql.SqlTypesSupport;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
@ -417,8 +418,8 @@ public final class GsonBuilder {
* call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
* will be used to decide the serialization format.
*
* <p>The date format will be used to serialize and deserialize {@link java.util.Date}, {@link
* java.sql.Timestamp} and {@link java.sql.Date}.
* <p>The date format will be used to serialize and deserialize {@link java.util.Date} and in case
* the {@code java.sql} module is present, also {@link java.sql.Timestamp} and {@link java.sql.Date}.
*
* <p>Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
* class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
@ -604,23 +605,33 @@ public final class GsonBuilder {
private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
List<TypeAdapterFactory> factories) {
DefaultDateTypeAdapter<Date> dateTypeAdapter;
TypeAdapter<Timestamp> timestampTypeAdapter;
TypeAdapter<java.sql.Date> javaSqlDateTypeAdapter;
if (datePattern != null && !"".equals(datePattern.trim())) {
dateTypeAdapter = DefaultDateTypeAdapter.DateType.DATE.createAdapter(datePattern);
timestampTypeAdapter = DefaultDateTypeAdapter.DateType.SQL_TIMESTAMP.createAdapter(datePattern);
javaSqlDateTypeAdapter = DefaultDateTypeAdapter.DateType.SQL_DATE.createAdapter(datePattern);
TypeAdapterFactory dateAdapterFactory;
boolean sqlTypesSupported = SqlTypesSupport.SUPPORTS_SQL_TYPES;
TypeAdapterFactory sqlTimestampAdapterFactory = null;
TypeAdapterFactory sqlDateAdapterFactory = null;
if (datePattern != null && !datePattern.trim().isEmpty()) {
dateAdapterFactory = DefaultDateTypeAdapter.DateType.DATE.createAdapterFactory(datePattern);
if (sqlTypesSupported) {
sqlTimestampAdapterFactory = SqlTypesSupport.TIMESTAMP_DATE_TYPE.createAdapterFactory(datePattern);
sqlDateAdapterFactory = SqlTypesSupport.DATE_DATE_TYPE.createAdapterFactory(datePattern);
}
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
dateTypeAdapter = DefaultDateTypeAdapter.DateType.DATE.createAdapter(dateStyle, timeStyle);
timestampTypeAdapter = DefaultDateTypeAdapter.DateType.SQL_TIMESTAMP.createAdapter(dateStyle, timeStyle);
javaSqlDateTypeAdapter = DefaultDateTypeAdapter.DateType.SQL_DATE.createAdapter(dateStyle, timeStyle);
dateAdapterFactory = DefaultDateTypeAdapter.DateType.DATE.createAdapterFactory(dateStyle, timeStyle);
if (sqlTypesSupported) {
sqlTimestampAdapterFactory = SqlTypesSupport.TIMESTAMP_DATE_TYPE.createAdapterFactory(dateStyle, timeStyle);
sqlDateAdapterFactory = SqlTypesSupport.DATE_DATE_TYPE.createAdapterFactory(dateStyle, timeStyle);
}
} else {
return;
}
factories.add(TypeAdapters.newFactory(Date.class, dateTypeAdapter));
factories.add(TypeAdapters.newFactory(Timestamp.class, timestampTypeAdapter));
factories.add(TypeAdapters.newFactory(java.sql.Date.class, javaSqlDateTypeAdapter));
factories.add(dateAdapterFactory);
if (sqlTypesSupported) {
factories.add(sqlTimestampAdapterFactory);
factories.add(sqlDateAdapterFactory);
}
}
}

View File

@ -14,10 +14,9 @@
* limitations under the License.
*/
package com.google.gson;
package com.google.gson.internal.bind;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
@ -27,6 +26,9 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.JavaVersion;
import com.google.gson.internal.PreJava9DateFormatProvider;
import com.google.gson.internal.bind.util.ISO8601Utils;
@ -35,54 +37,49 @@ import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
/**
* This type adapter supports three subclasses of date: Date, Timestamp, and
* java.sql.Date.
* This type adapter supports subclasses of date by defining a
* {@link DefaultDateTypeAdapter.DateType} and then using its {@code createAdapterFactory}
* methods.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class DefaultDateTypeAdapter<T extends Date> extends TypeAdapter<T> {
public final class DefaultDateTypeAdapter<T extends Date> extends TypeAdapter<T> {
private static final String SIMPLE_NAME = "DefaultDateTypeAdapter";
static abstract class DateType<T extends Date> {
private DateType() {
}
public static final DateType<Date> DATE = new DateType<Date>() {
@Override
protected Date deserialize(Date date) {
public static abstract class DateType<T extends Date> {
public static final DateType<Date> DATE = new DateType<Date>(Date.class) {
@Override protected Date deserialize(Date date) {
return date;
}
};
public static final DateType<java.sql.Date> SQL_DATE = new DateType<java.sql.Date>() {
@Override
protected java.sql.Date deserialize(Date date) {
return new java.sql.Date(date.getTime());
}
};
public static final DateType<Timestamp> SQL_TIMESTAMP = new DateType<Timestamp>() {
@Override
protected Timestamp deserialize(Date date) {
return new Timestamp(date.getTime());
}
};
private final Class<T> dateClass;
protected DateType(Class<T> dateClass) {
this.dateClass = dateClass;
}
protected abstract T deserialize(Date date);
public DefaultDateTypeAdapter<T> createAdapter(String datePattern) {
return new DefaultDateTypeAdapter<T>(this, datePattern);
private final TypeAdapterFactory createFactory(DefaultDateTypeAdapter<T> adapter) {
return TypeAdapters.newFactory(dateClass, adapter);
}
public DefaultDateTypeAdapter<T> createAdapter(int style) {
return new DefaultDateTypeAdapter<T>(this, style);
public final TypeAdapterFactory createAdapterFactory(String datePattern) {
return createFactory(new DefaultDateTypeAdapter<T>(this, datePattern));
}
public DefaultDateTypeAdapter<T> createAdapter(int dateStyle, int timeStyle) {
return new DefaultDateTypeAdapter<T>(this, dateStyle, timeStyle);
public final TypeAdapterFactory createAdapterFactory(int style) {
return createFactory(new DefaultDateTypeAdapter<T>(this, style));
}
public DefaultDateTypeAdapter<T> createDefaultsAdapter() {
return new DefaultDateTypeAdapter<T>(this, DateFormat.DEFAULT, DateFormat.DEFAULT);
public final TypeAdapterFactory createAdapterFactory(int dateStyle, int timeStyle) {
return createFactory(new DefaultDateTypeAdapter<T>(this, dateStyle, timeStyle));
}
public final TypeAdapterFactory createDefaultsAdapterFactory() {
return createFactory(new DefaultDateTypeAdapter<T>(this, DateFormat.DEFAULT, DateFormat.DEFAULT));
}
}
@ -162,11 +159,12 @@ final class DefaultDateTypeAdapter<T extends Date> extends TypeAdapter<T> {
return dateFormat.parse(s);
} catch (ParseException ignored) {}
}
try {
return ISO8601Utils.parse(s, new ParsePosition(0));
} catch (ParseException e) {
throw new JsonSyntaxException(s, e);
}
}
try {
return ISO8601Utils.parse(s, new ParsePosition(0));
} catch (ParseException e) {
throw new JsonSyntaxException(s, e);
}
}

View File

@ -23,12 +23,10 @@ import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Calendar;
import java.util.Currency;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
@ -406,7 +404,7 @@ public final class TypeAdapters {
out.value(value);
}
};
public static final TypeAdapter<BigDecimal> BIG_DECIMAL = new TypeAdapter<BigDecimal>() {
@Override public BigDecimal read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
@ -424,7 +422,7 @@ public final class TypeAdapters {
out.value(value);
}
};
public static final TypeAdapter<BigInteger> BIG_INTEGER = new TypeAdapter<BigInteger>() {
@Override public BigInteger read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
@ -569,27 +567,6 @@ public final class TypeAdapters {
}.nullSafe();
public static final TypeAdapterFactory CURRENCY_FACTORY = newFactory(Currency.class, CURRENCY);
public static final TypeAdapterFactory TIMESTAMP_FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
if (typeToken.getRawType() != Timestamp.class) {
return null;
}
final TypeAdapter<Date> dateTypeAdapter = gson.getAdapter(Date.class);
return (TypeAdapter<T>) new TypeAdapter<Timestamp>() {
@Override public Timestamp read(JsonReader in) throws IOException {
Date date = dateTypeAdapter.read(in);
return date != null ? new Timestamp(date.getTime()) : null;
}
@Override public void write(JsonWriter out, Timestamp value) throws IOException {
dateTypeAdapter.write(out, value);
}
};
}
};
public static final TypeAdapter<Calendar> CALENDAR = new TypeAdapter<Calendar>() {
private static final String YEAR = "year";
private static final String MONTH = "month";

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.gson.internal.bind;
package com.google.gson.internal.sql;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
@ -35,8 +35,8 @@ import java.text.SimpleDateFormat;
* 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 TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == java.sql.Date.class
@ -46,6 +46,9 @@ public final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
private final DateFormat format = new SimpleDateFormat("MMM d, yyyy");
private SqlDateTypeAdapter() {
}
@Override
public synchronized java.sql.Date read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.gson.internal.bind;
package com.google.gson.internal.sql;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
@ -32,21 +32,24 @@ import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Adapter for Time. Although this class appears stateless, it is not.
* Adapter for java.sql.Time. 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 TimeTypeAdapter extends TypeAdapter<Time> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
final class SqlTimeTypeAdapter extends TypeAdapter<Time> {
static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == Time.class ? (TypeAdapter<T>) new TimeTypeAdapter() : null;
return typeToken.getRawType() == Time.class ? (TypeAdapter<T>) new SqlTimeTypeAdapter() : null;
}
};
private final DateFormat format = new SimpleDateFormat("hh:mm:ss a");
private SqlTimeTypeAdapter() {
}
@Override public synchronized Time read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();

View File

@ -0,0 +1,43 @@
package com.google.gson.internal.sql;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Date;
class SqlTimestampTypeAdapter extends TypeAdapter<Timestamp> {
static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
if (typeToken.getRawType() == Timestamp.class) {
final TypeAdapter<Date> dateTypeAdapter = gson.getAdapter(Date.class);
return (TypeAdapter<T>) new SqlTimestampTypeAdapter(dateTypeAdapter);
} else {
return null;
}
}
};
private final TypeAdapter<Date> dateTypeAdapter;
private SqlTimestampTypeAdapter(TypeAdapter<Date> dateTypeAdapter) {
this.dateTypeAdapter = dateTypeAdapter;
}
@Override
public Timestamp read(JsonReader in) throws IOException {
Date date = dateTypeAdapter.read(in);
return date != null ? new Timestamp(date.getTime()) : null;
}
@Override
public void write(JsonWriter out, Timestamp value) throws IOException {
dateTypeAdapter.write(out, value);
}
}

View File

@ -0,0 +1,71 @@
package com.google.gson.internal.sql;
import java.sql.Timestamp;
import java.util.Date;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.bind.DefaultDateTypeAdapter.DateType;
/**
* Encapsulates access to {@code java.sql} types, to allow Gson to
* work without the {@code java.sql} module being present.
* No {@link ClassNotFoundException}s will be thrown in case
* the {@code java.sql} module is not present.
*
* <p>If {@link #SUPPORTS_SQL_TYPES} is {@code true}, all other
* constants of this class will be non-{@code null}. However, if
* it is {@code false} all other constants will be {@code null} and
* there will be no support for {@code java.sql} types.
*/
public final class SqlTypesSupport {
/**
* {@code true} if {@code java.sql} types are supported,
* {@code false} otherwise
*/
public static final boolean SUPPORTS_SQL_TYPES;
public static final DateType<? extends Date> DATE_DATE_TYPE;
public static final DateType<? extends Date> TIMESTAMP_DATE_TYPE;
public static final TypeAdapterFactory DATE_FACTORY;
public static final TypeAdapterFactory TIME_FACTORY;
public static final TypeAdapterFactory TIMESTAMP_FACTORY;
static {
boolean sqlTypesSupport;
try {
Class.forName("java.sql.Date");
sqlTypesSupport = true;
} catch (ClassNotFoundException classNotFoundException) {
sqlTypesSupport = false;
}
SUPPORTS_SQL_TYPES = sqlTypesSupport;
if (SUPPORTS_SQL_TYPES) {
DATE_DATE_TYPE = new DateType<java.sql.Date>(java.sql.Date.class) {
@Override protected java.sql.Date deserialize(Date date) {
return new java.sql.Date(date.getTime());
}
};
TIMESTAMP_DATE_TYPE = new DateType<Timestamp>(Timestamp.class) {
@Override protected Timestamp deserialize(Date date) {
return new Timestamp(date.getTime());
}
};
DATE_FACTORY = SqlDateTypeAdapter.FACTORY;
TIME_FACTORY = SqlTimeTypeAdapter.FACTORY;
TIMESTAMP_FACTORY = SqlTimestampTypeAdapter.FACTORY;
} else {
DATE_DATE_TYPE = null;
TIMESTAMP_DATE_TYPE = null;
DATE_FACTORY = null;
TIME_FACTORY = null;
TIMESTAMP_FACTORY = null;
}
}
private SqlTypesSupport() {
}
}

View File

@ -8,5 +8,6 @@ module com.google.gson {
exports com.google.gson.reflect;
exports com.google.gson.stream;
requires transitive java.sql;
// Optional dependency on java.sql
requires static java.sql;
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.google.gson;
package com.google.gson.internal.bind;
import java.io.IOException;
import java.text.DateFormat;
@ -23,8 +23,13 @@ import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import com.google.gson.DefaultDateTypeAdapter.DateType;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.JavaVersion;
import com.google.gson.internal.bind.DefaultDateTypeAdapter;
import com.google.gson.internal.bind.DefaultDateTypeAdapter.DateType;
import com.google.gson.reflect.TypeToken;
import junit.framework.TestCase;
@ -53,18 +58,18 @@ public class DefaultDateTypeAdapterTest extends TestCase {
String afterYearLongSep = JavaVersion.isJava9OrLater() ? " at " : " ";
String utcFull = JavaVersion.isJava9OrLater() ? "Coordinated Universal Time" : "UTC";
assertFormatted(String.format("Jan 1, 1970%s12:00:00 AM", afterYearSep),
DateType.DATE.createDefaultsAdapter());
assertFormatted("1/1/70", DateType.DATE.createAdapter(DateFormat.SHORT));
assertFormatted("Jan 1, 1970", DateType.DATE.createAdapter(DateFormat.MEDIUM));
assertFormatted("January 1, 1970", DateType.DATE.createAdapter(DateFormat.LONG));
DateType.DATE.createDefaultsAdapterFactory());
assertFormatted("1/1/70", DateType.DATE.createAdapterFactory(DateFormat.SHORT));
assertFormatted("Jan 1, 1970", DateType.DATE.createAdapterFactory(DateFormat.MEDIUM));
assertFormatted("January 1, 1970", DateType.DATE.createAdapterFactory(DateFormat.LONG));
assertFormatted(String.format("1/1/70%s12:00 AM", afterYearSep),
DateType.DATE.createAdapter(DateFormat.SHORT, DateFormat.SHORT));
DateType.DATE.createAdapterFactory(DateFormat.SHORT, DateFormat.SHORT));
assertFormatted(String.format("Jan 1, 1970%s12:00:00 AM", afterYearSep),
DateType.DATE.createAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
DateType.DATE.createAdapterFactory(DateFormat.MEDIUM, DateFormat.MEDIUM));
assertFormatted(String.format("January 1, 1970%s12:00:00 AM UTC", afterYearLongSep),
DateType.DATE.createAdapter(DateFormat.LONG, DateFormat.LONG));
DateType.DATE.createAdapterFactory(DateFormat.LONG, DateFormat.LONG));
assertFormatted(String.format("Thursday, January 1, 1970%s12:00:00 AM %s", afterYearLongSep, utcFull),
DateType.DATE.createAdapter(DateFormat.FULL, DateFormat.FULL));
DateType.DATE.createAdapterFactory(DateFormat.FULL, DateFormat.FULL));
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
@ -79,21 +84,21 @@ public class DefaultDateTypeAdapterTest extends TestCase {
try {
String afterYearSep = JavaVersion.isJava9OrLater() ? " à " : " ";
assertParsed(String.format("1 janv. 1970%s00:00:00", afterYearSep),
DateType.DATE.createDefaultsAdapter());
assertParsed("01/01/70", DateType.DATE.createAdapter(DateFormat.SHORT));
assertParsed("1 janv. 1970", DateType.DATE.createAdapter(DateFormat.MEDIUM));
assertParsed("1 janvier 1970", DateType.DATE.createAdapter(DateFormat.LONG));
DateType.DATE.createDefaultsAdapterFactory());
assertParsed("01/01/70", DateType.DATE.createAdapterFactory(DateFormat.SHORT));
assertParsed("1 janv. 1970", DateType.DATE.createAdapterFactory(DateFormat.MEDIUM));
assertParsed("1 janvier 1970", DateType.DATE.createAdapterFactory(DateFormat.LONG));
assertParsed("01/01/70 00:00",
DateType.DATE.createAdapter(DateFormat.SHORT, DateFormat.SHORT));
DateType.DATE.createAdapterFactory(DateFormat.SHORT, DateFormat.SHORT));
assertParsed(String.format("1 janv. 1970%s00:00:00", afterYearSep),
DateType.DATE.createAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
DateType.DATE.createAdapterFactory(DateFormat.MEDIUM, DateFormat.MEDIUM));
assertParsed(String.format("1 janvier 1970%s00:00:00 UTC", afterYearSep),
DateType.DATE.createAdapter(DateFormat.LONG, DateFormat.LONG));
DateType.DATE.createAdapterFactory(DateFormat.LONG, DateFormat.LONG));
assertParsed(JavaVersion.isJava9OrLater() ? (JavaVersion.getMajorJavaVersion() <11 ?
"jeudi 1 janvier 1970 à 00:00:00 Coordinated Universal Time" :
"jeudi 1 janvier 1970 à 00:00:00 Temps universel coordonné") :
"jeudi 1 janvier 1970 00 h 00 UTC",
DateType.DATE.createAdapter(DateFormat.FULL, DateFormat.FULL));
DateType.DATE.createAdapterFactory(DateFormat.FULL, DateFormat.FULL));
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
@ -106,18 +111,18 @@ public class DefaultDateTypeAdapterTest extends TestCase {
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
try {
assertParsed("Jan 1, 1970 0:00:00 AM", DateType.DATE.createDefaultsAdapter());
assertParsed("1/1/70", DateType.DATE.createAdapter(DateFormat.SHORT));
assertParsed("Jan 1, 1970", DateType.DATE.createAdapter(DateFormat.MEDIUM));
assertParsed("January 1, 1970", DateType.DATE.createAdapter(DateFormat.LONG));
assertParsed("Jan 1, 1970 0:00:00 AM", DateType.DATE.createDefaultsAdapterFactory());
assertParsed("1/1/70", DateType.DATE.createAdapterFactory(DateFormat.SHORT));
assertParsed("Jan 1, 1970", DateType.DATE.createAdapterFactory(DateFormat.MEDIUM));
assertParsed("January 1, 1970", DateType.DATE.createAdapterFactory(DateFormat.LONG));
assertParsed("1/1/70 0:00 AM",
DateType.DATE.createAdapter(DateFormat.SHORT, DateFormat.SHORT));
DateType.DATE.createAdapterFactory(DateFormat.SHORT, DateFormat.SHORT));
assertParsed("Jan 1, 1970 0:00:00 AM",
DateType.DATE.createAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
DateType.DATE.createAdapterFactory(DateFormat.MEDIUM, DateFormat.MEDIUM));
assertParsed("January 1, 1970 0:00:00 AM UTC",
DateType.DATE.createAdapter(DateFormat.LONG, DateFormat.LONG));
DateType.DATE.createAdapterFactory(DateFormat.LONG, DateFormat.LONG));
assertParsed("Thursday, January 1, 1970 0:00:00 AM UTC",
DateType.DATE.createAdapter(DateFormat.FULL, DateFormat.FULL));
DateType.DATE.createAdapterFactory(DateFormat.FULL, DateFormat.FULL));
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
@ -132,8 +137,8 @@ public class DefaultDateTypeAdapterTest extends TestCase {
try {
String afterYearSep = JavaVersion.isJava9OrLater() ? ", " : " ";
assertFormatted(String.format("Dec 31, 1969%s4:00:00 PM", afterYearSep),
DateType.DATE.createDefaultsAdapter());
assertParsed("Dec 31, 1969 4:00:00 PM", DateType.DATE.createDefaultsAdapter());
DateType.DATE.createDefaultsAdapterFactory());
assertParsed("Dec 31, 1969 4:00:00 PM", DateType.DATE.createDefaultsAdapterFactory());
} finally {
TimeZone.setDefault(defaultTimeZone);
Locale.setDefault(defaultLocale);
@ -141,17 +146,17 @@ public class DefaultDateTypeAdapterTest extends TestCase {
}
public void testDateDeserializationISO8601() throws Exception {
DefaultDateTypeAdapter<Date> adapter = DateType.DATE.createDefaultsAdapter();
assertParsed("1970-01-01T00:00:00.000Z", adapter);
assertParsed("1970-01-01T00:00Z", adapter);
assertParsed("1970-01-01T00:00:00+00:00", adapter);
assertParsed("1970-01-01T01:00:00+01:00", adapter);
assertParsed("1970-01-01T01:00:00+01", adapter);
TypeAdapterFactory adapterFactory = DateType.DATE.createDefaultsAdapterFactory();
assertParsed("1970-01-01T00:00:00.000Z", adapterFactory);
assertParsed("1970-01-01T00:00Z", adapterFactory);
assertParsed("1970-01-01T00:00:00+00:00", adapterFactory);
assertParsed("1970-01-01T01:00:00+01:00", adapterFactory);
assertParsed("1970-01-01T01:00:00+01", adapterFactory);
}
public void testDateSerialization() throws Exception {
int dateStyle = DateFormat.LONG;
DefaultDateTypeAdapter<Date> dateTypeAdapter = DateType.DATE.createAdapter(dateStyle);
TypeAdapter<Date> dateTypeAdapter = dateAdapter(DateType.DATE.createAdapterFactory(dateStyle));
DateFormat formatter = DateFormat.getDateInstance(dateStyle, Locale.US);
Date currentDate = new Date();
@ -161,7 +166,7 @@ public class DefaultDateTypeAdapterTest extends TestCase {
public void testDatePattern() throws Exception {
String pattern = "yyyy-MM-dd";
DefaultDateTypeAdapter<Date> dateTypeAdapter = DateType.DATE.createAdapter(pattern);
TypeAdapter<Date> dateTypeAdapter = dateAdapter(DateType.DATE.createAdapterFactory(pattern));
DateFormat formatter = new SimpleDateFormat(pattern);
Date currentDate = new Date();
@ -171,30 +176,38 @@ public class DefaultDateTypeAdapterTest extends TestCase {
public void testInvalidDatePattern() throws Exception {
try {
DateType.DATE.createAdapter("I am a bad Date pattern....");
DateType.DATE.createAdapterFactory("I am a bad Date pattern....");
fail("Invalid date pattern should fail.");
} catch (IllegalArgumentException expected) { }
}
public void testNullValue() throws Exception {
DefaultDateTypeAdapter<Date> adapter = DateType.DATE.createDefaultsAdapter();
TypeAdapter<Date> adapter = dateAdapter(DateType.DATE.createDefaultsAdapterFactory());
assertNull(adapter.fromJson("null"));
assertEquals("null", adapter.toJson(null));
}
public void testUnexpectedToken() throws Exception {
try {
DefaultDateTypeAdapter<Date> adapter = DateType.DATE.createDefaultsAdapter();
TypeAdapter<Date> adapter = dateAdapter(DateType.DATE.createDefaultsAdapterFactory());
adapter.fromJson("{}");
fail("Unexpected token should fail.");
} catch (IllegalStateException expected) { }
}
private void assertFormatted(String formatted, DefaultDateTypeAdapter<Date> adapter) {
private static TypeAdapter<Date> dateAdapter(TypeAdapterFactory adapterFactory) {
TypeAdapter<Date> adapter = adapterFactory.create(new Gson(), TypeToken.get(Date.class));
assertNotNull(adapter);
return adapter;
}
private static void assertFormatted(String formatted, TypeAdapterFactory adapterFactory) {
TypeAdapter<Date> adapter = dateAdapter(adapterFactory);
assertEquals(toLiteral(formatted), adapter.toJson(new Date(0)));
}
private void assertParsed(String date, DefaultDateTypeAdapter<Date> adapter) throws IOException {
private static void assertParsed(String date, TypeAdapterFactory adapterFactory) throws IOException {
TypeAdapter<Date> adapter = dateAdapter(adapterFactory);
assertEquals(date, new Date(0), adapter.fromJson(toLiteral(date)));
assertEquals("ISO 8601", new Date(0), adapter.fromJson(toLiteral("1970-01-01T00:00:00Z")));
}

View File

@ -0,0 +1,16 @@
package com.google.gson.internal.sql;
import junit.framework.TestCase;
public class SqlTypesSupportTest extends TestCase {
public void testSupported() {
assertTrue(SqlTypesSupport.SUPPORTS_SQL_TYPES);
assertNotNull(SqlTypesSupport.DATE_DATE_TYPE);
assertNotNull(SqlTypesSupport.TIMESTAMP_DATE_TYPE);
assertNotNull(SqlTypesSupport.DATE_FACTORY);
assertNotNull(SqlTypesSupport.TIME_FACTORY);
assertNotNull(SqlTypesSupport.TIMESTAMP_FACTORY);
}
}