diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache index 2ee5ab3e88..a19a16743f 100644 --- a/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache @@ -75,13 +75,11 @@ public class ApiClient { private int statusCode; private Map> responseHeaders; - private String dateFormat; - private DateFormat dateFormatter; + private DateFormat dateFormat; + private DateFormat datetimeFormat; + private boolean lenientDatetimeFormat; private int dateLength; - private String datetimeFormat; - private DateFormat datetimeFormatter; - private InputStream sslCaCert; private boolean verifyingSsl; @@ -95,10 +93,19 @@ public class ApiClient { json = new JSON(this); - // Use ISO 8601 format for date and datetime. - // See https://en.wikipedia.org/wiki/ISO_8601 - setDateFormat("yyyy-MM-dd"); - setDatetimeFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + /* + * Use RFC3339 format for date and datetime. + * See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + */ + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + // Always use UTC as the default time zone when dealing with date (without time). + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + // Use the system's default time zone when dealing with datetime (mainly formatting). + this.datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + // Be lenient on datetime formats when parsing datetime from string. + // See parseDatetime. + this.lenientDatetimeFormat = true; // Set default User-Agent. setUserAgent("Java-Swagger"); @@ -186,32 +193,35 @@ public class ApiClient { return this; } - public String getDateFormat() { + public DateFormat getDateFormat() { return dateFormat; } - public ApiClient setDateFormat(String dateFormat) { + public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; - - this.dateFormatter = new SimpleDateFormat(dateFormat); - // Use UTC as the default time zone. - this.dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); - - this.dateLength = this.dateFormatter.format(new Date()).length(); - + this.dateLength = this.dateFormat.format(new Date()).length(); return this; } - public String getDatetimeFormat() { + public DateFormat getDatetimeFormat() { return datetimeFormat; } - public ApiClient setDatetimeFormat(String datetimeFormat) { + public ApiClient setDatetimeFormat(DateFormat datetimeFormat) { this.datetimeFormat = datetimeFormat; + return this; + } - this.datetimeFormatter = new SimpleDateFormat(datetimeFormat); - // Note: The datetime formatter uses the system's default time zone. + /** + * Whether to allow various ISO 8601 datetime formats when parsing a datetime string. + * @see #parseDatetime(String) + */ + public boolean isLenientDatetimeFormat() { + return lenientDatetimeFormat; + } + public ApiClient setLenientDatetimeFormat(boolean lenientDatetimeFormat) { + this.lenientDatetimeFormat = lenientDatetimeFormat; return this; } @@ -225,15 +235,15 @@ public class ApiClient { if (str == null) return null; try { - return dateFormatter.parse(str); + return dateFormat.parse(str); } catch (ParseException e) { throw new RuntimeException(e); } } /** - * Parse the given date-time string into Date object. - * The default datetimeFormat supports these ISO 8601 datetime formats: + * Parse the given datetime string into Date object. + * When lenientDatetimeFormat is enabled, the following ISO 8601 datetime formats are supported: * 2015-08-16T08:20:05Z * 2015-8-16T8:20:05Z * 2015-08-16T08:20:05+00:00 @@ -253,25 +263,25 @@ public class ApiClient { if (str == null) return null; - if ("yyyy-MM-dd'T'HH:mm:ss.SSSZ".equals(datetimeFormat)) { + if (lenientDatetimeFormat) { /* * When the default datetime format is used, process the given string * to support various formats defined by ISO 8601. */ // normalize time zone - // trailing "Z": 2015-08-16T08:20:05Z => 2015-08-16T08:20:05+0000 - str = str.replaceAll("[zZ]\\z", "+0000"); - // remove colon: 2015-08-16T08:20:05+00:00 => 2015-08-16T08:20:05+0000 - str = str.replaceAll("([+-]\\d{2}):(\\d{2})\\z", "$1$2"); - // expand time zone: 2015-08-16T08:20:05+00 => 2015-08-16T08:20:05+0000 - str = str.replaceAll("([+-]\\d{2})\\z", "$100"); + // trailing "Z": 2015-08-16T08:20:05Z => 2015-08-16T08:20:05+00:00 + str = str.replaceAll("[zZ]\\z", "+00:00"); + // add colon: 2015-08-16T08:20:05+0000 => 2015-08-16T08:20:05+00:00 + str = str.replaceAll("([+-]\\d{2})(\\d{2})\\z", "$1:$2"); + // expand time zone: 2015-08-16T08:20:05+00 => 2015-08-16T08:20:05+00:00 + str = str.replaceAll("([+-]\\d{2})\\z", "$1:00"); // add milliseconds when missing - // 2015-08-16T08:20:05+0000 => 2015-08-16T08:20:05.000+0000 - str = str.replaceAll("(:\\d{1,2})([+-]\\d{4})\\z", "$1.000$2"); + // 2015-08-16T08:20:05+00:00 => 2015-08-16T08:20:05.000+00:00 + str = str.replaceAll("(:\\d{1,2})([+-]\\d{2}:\\d{2})\\z", "$1.000$2"); } try { - return datetimeFormatter.parse(str); + return datetimeFormat.parse(str); } catch (ParseException e) { throw new RuntimeException(e); } @@ -290,14 +300,14 @@ public class ApiClient { * Format the given Date object into string. */ public String formatDate(Date date) { - return dateFormatter.format(date); + return dateFormat.format(date); } /** * Format the given Date object into string. */ public String formatDatetime(Date date) { - return datetimeFormatter.format(date); + return datetimeFormat.format(date); } /** diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java index 88b8f5602d..eac3d025df 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/io/swagger/client/ApiClient.java @@ -75,13 +75,11 @@ public class ApiClient { private int statusCode; private Map> responseHeaders; - private String dateFormat; - private DateFormat dateFormatter; + private DateFormat dateFormat; + private DateFormat datetimeFormat; + private boolean lenientDatetimeFormat; private int dateLength; - private String datetimeFormat; - private DateFormat datetimeFormatter; - private InputStream sslCaCert; private boolean verifyingSsl; @@ -95,10 +93,19 @@ public class ApiClient { json = new JSON(this); - // Use ISO 8601 format for date and datetime. - // See https://en.wikipedia.org/wiki/ISO_8601 - setDateFormat("yyyy-MM-dd"); - setDatetimeFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + /* + * Use RFC3339 format for date and datetime. + * See http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14 + */ + this.dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + // Always use UTC as the default time zone when dealing with date (without time). + this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + // Use the system's default time zone when dealing with datetime (mainly formatting). + this.datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + + // Be lenient on datetime formats when parsing datetime from string. + // See parseDatetime. + this.lenientDatetimeFormat = true; // Set default User-Agent. setUserAgent("Java-Swagger"); @@ -185,32 +192,35 @@ public class ApiClient { return this; } - public String getDateFormat() { + public DateFormat getDateFormat() { return dateFormat; } - public ApiClient setDateFormat(String dateFormat) { + public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; - - this.dateFormatter = new SimpleDateFormat(dateFormat); - // Use UTC as the default time zone. - this.dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); - - this.dateLength = this.dateFormatter.format(new Date()).length(); - + this.dateLength = this.dateFormat.format(new Date()).length(); return this; } - public String getDatetimeFormat() { + public DateFormat getDatetimeFormat() { return datetimeFormat; } - public ApiClient setDatetimeFormat(String datetimeFormat) { + public ApiClient setDatetimeFormat(DateFormat datetimeFormat) { this.datetimeFormat = datetimeFormat; + return this; + } - this.datetimeFormatter = new SimpleDateFormat(datetimeFormat); - // Note: The datetime formatter uses the system's default time zone. + /** + * Whether to allow various ISO 8601 datetime formats when parsing a datetime string. + * @see #parseDatetime(String) + */ + public boolean isLenientDatetimeFormat() { + return lenientDatetimeFormat; + } + public ApiClient setLenientDatetimeFormat(boolean lenientDatetimeFormat) { + this.lenientDatetimeFormat = lenientDatetimeFormat; return this; } @@ -224,15 +234,15 @@ public class ApiClient { if (str == null) return null; try { - return dateFormatter.parse(str); + return dateFormat.parse(str); } catch (ParseException e) { throw new RuntimeException(e); } } /** - * Parse the given date-time string into Date object. - * The default datetimeFormat supports these ISO 8601 datetime formats: + * Parse the given datetime string into Date object. + * When lenientDatetimeFormat is enabled, the following ISO 8601 datetime formats are supported: * 2015-08-16T08:20:05Z * 2015-8-16T8:20:05Z * 2015-08-16T08:20:05+00:00 @@ -252,25 +262,25 @@ public class ApiClient { if (str == null) return null; - if ("yyyy-MM-dd'T'HH:mm:ss.SSSZ".equals(datetimeFormat)) { + if (lenientDatetimeFormat) { /* * When the default datetime format is used, process the given string * to support various formats defined by ISO 8601. */ // normalize time zone - // trailing "Z": 2015-08-16T08:20:05Z => 2015-08-16T08:20:05+0000 - str = str.replaceAll("[zZ]\\z", "+0000"); - // remove colon: 2015-08-16T08:20:05+00:00 => 2015-08-16T08:20:05+0000 - str = str.replaceAll("([+-]\\d{2}):(\\d{2})\\z", "$1$2"); - // expand time zone: 2015-08-16T08:20:05+00 => 2015-08-16T08:20:05+0000 - str = str.replaceAll("([+-]\\d{2})\\z", "$100"); + // trailing "Z": 2015-08-16T08:20:05Z => 2015-08-16T08:20:05+00:00 + str = str.replaceAll("[zZ]\\z", "+00:00"); + // add colon: 2015-08-16T08:20:05+0000 => 2015-08-16T08:20:05+00:00 + str = str.replaceAll("([+-]\\d{2})(\\d{2})\\z", "$1:$2"); + // expand time zone: 2015-08-16T08:20:05+00 => 2015-08-16T08:20:05+00:00 + str = str.replaceAll("([+-]\\d{2})\\z", "$1:00"); // add milliseconds when missing - // 2015-08-16T08:20:05+0000 => 2015-08-16T08:20:05.000+0000 - str = str.replaceAll("(:\\d{1,2})([+-]\\d{4})\\z", "$1.000$2"); + // 2015-08-16T08:20:05+00:00 => 2015-08-16T08:20:05.000+00:00 + str = str.replaceAll("(:\\d{1,2})([+-]\\d{2}:\\d{2})\\z", "$1.000$2"); } try { - return datetimeFormatter.parse(str); + return datetimeFormat.parse(str); } catch (ParseException e) { throw new RuntimeException(e); } @@ -289,14 +299,14 @@ public class ApiClient { * Format the given Date object into string. */ public String formatDate(Date date) { - return dateFormatter.format(date); + return dateFormat.format(date); } /** * Format the given Date object into string. */ public String formatDatetime(Date date) { - return datetimeFormatter.format(date); + return datetimeFormat.format(date); } /** diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/ApiClientTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/ApiClientTest.java index 802c0cae3b..aaf4f33c49 100644 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/ApiClientTest.java +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/ApiClientTest.java @@ -2,7 +2,10 @@ package io.swagger.client; import io.swagger.client.auth.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.*; +import java.util.TimeZone; import org.junit.*; import static org.junit.Assert.*; @@ -16,6 +19,64 @@ public class ApiClientTest { apiClient = new ApiClient(); } + @Test + public void testParseAndFormatDatetime() { + // default datetime format with UTC time zone + apiClient.getDatetimeFormat().setTimeZone(TimeZone.getTimeZone("UTC")); + String dateStr = "2015-11-07T03:49:09.356Z"; + assertTrue(apiClient.isLenientDatetimeFormat()); + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09.356+00:00"))); + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T05:49:09.356+02:00"))); + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T02:49:09.356-01:00"))); + // support various cases + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09.356Z"))); + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09.356+00"))); + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T02:49:09.356-0100"))); + dateStr = "2015-11-07T03:49:09.000Z"; + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T05:49:09+02"))); + + // custom datetime format: without milli-seconds, custom time zone + DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + format.setTimeZone(TimeZone.getTimeZone("GMT+10")); + apiClient.setDatetimeFormat(format); + // disable support of various datetime format + apiClient.setLenientDatetimeFormat(false); + dateStr = "2015-11-07T13:49:09+10:00"; + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09+00:00"))); + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T03:49:09Z"))); + assertEquals(dateStr, apiClient.formatDatetime(apiClient.parseDatetime("2015-11-07T00:49:09-03:00"))); + + try { + // invalid time zone format + apiClient.parseDatetime("2015-11-07T03:49:09+00"); + fail("parseDatetime should fail"); + } catch (RuntimeException e) { + // OK + } + try { + // unexpected miliseconds + apiClient.parseDatetime("2015-11-07T03:49:09.000Z"); + fail("parseDatetime should fail"); + } catch (RuntimeException e) { + // OK + } + } + + @Test + public void testParseAndFormatDate() { + // default date format + String dateStr = "2015-11-07"; + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDatetime("2015-11-07T03:49:09.356+00:00"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07"))); + + // custom date format: without day + DateFormat format = new SimpleDateFormat("yyyy-MM"); + apiClient.setDateFormat(format); + dateStr = "2015-11"; + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDatetime("2015-11-07T03:49:09Z"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11"))); + } + @Test public void testSelectHeaderAccept() { String[] accepts = {"APPLICATION/JSON", "APPLICATION/XML"}; diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/JSONTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/JSONTest.java new file mode 100644 index 0000000000..fdc2e4c7d4 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/client/JSONTest.java @@ -0,0 +1,55 @@ +package io.swagger.client; + +import com.google.gson.reflect.TypeToken; + +import io.swagger.client.model.Order; + +import java.lang.Exception; +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +import org.junit.*; +import static org.junit.Assert.*; + +public class JSONTest { + ApiClient apiClient = null; + JSON json = null; + Order order = null; + + @Before + public void setup() { + apiClient = new ApiClient(); + json = new JSON(apiClient); + order = new Order(); + } + + @Test + public void testDefaultDate() throws Exception { + final DateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + datetimeFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + final String dateStr = "2015-11-07T14:11:05.267Z"; + order.setShipDate(datetimeFormat.parse(dateStr)); + + String str = json.serialize(order); + Type type = new TypeToken() { }.getType(); + Order o = json.deserialize(str, type); + assertEquals(dateStr, datetimeFormat.format(o.getShipDate())); + } + + @Test + public void testCustomDate() throws Exception { + final DateFormat datetimeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + datetimeFormat.setTimeZone(TimeZone.getTimeZone("GMT-2")); + final String dateStr = "2015-11-07T14:11:05-02:00"; + order.setShipDate(datetimeFormat.parse(dateStr)); + + apiClient.setDatetimeFormat(datetimeFormat); + apiClient.setLenientDatetimeFormat(false); + String str = json.serialize(order); + Type type = new TypeToken() { }.getType(); + Order o = json.deserialize(str, type); + assertEquals(dateStr, datetimeFormat.format(o.getShipDate())); + } +} \ No newline at end of file