diff --git a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache index c81b75d73db..91d1eb93daf 100644 --- a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache @@ -55,13 +55,15 @@ public class ApiClient { private DateFormat dateFormat; public ApiClient() { - // Use ISO 8601 format for date and datetime. - // See https://en.wikipedia.org/wiki/ISO_8601 - this.dateFormat = new SimpleDateFormat("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'T'HH:mm:ss.SSSXXX"); // Use UTC as the default time zone. this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + this.json.setDateFormat((DateFormat) dateFormat.clone()); + // Set default User-Agent. setUserAgent("Java-Swagger"); @@ -74,6 +76,13 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } + /** + * Gets the JSON instance to do JSON serialization and deserialization. + */ + public JSON getJSON() { + return json; + } + public String getBasePath() { return basePath; } @@ -227,6 +236,8 @@ public class ApiClient { */ public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); return this; } diff --git a/modules/swagger-codegen/src/main/resources/Java/JSON.mustache b/modules/swagger-codegen/src/main/resources/Java/JSON.mustache index 43b38f6e21d..54faed8dcb3 100644 --- a/modules/swagger-codegen/src/main/resources/Java/JSON.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/JSON.mustache @@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.datatype.joda.*; +import java.text.DateFormat; + import java.io.IOException; {{>generatedAnnotation}} @@ -20,6 +22,13 @@ public class JSON { mapper.registerModule(new JodaModule()); } + /** + * Set the date format for JSON (de)serialization with Date properties. + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + /** * Serialize the given Java object into JSON string. */ diff --git a/modules/swagger-codegen/src/main/resources/Java/libraries/jersey2/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/libraries/jersey2/ApiClient.mustache index c71b6089358..bd64a6fe659 100644 --- a/modules/swagger-codegen/src/main/resources/Java/libraries/jersey2/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/libraries/jersey2/ApiClient.mustache @@ -60,13 +60,15 @@ public class ApiClient { private DateFormat dateFormat; public ApiClient() { - // Use ISO 8601 format for date and datetime. - // See https://en.wikipedia.org/wiki/ISO_8601 - this.dateFormat = new SimpleDateFormat("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'T'HH:mm:ss.SSSXXX"); // Use UTC as the default time zone. this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + this.json.setDateFormat((DateFormat) dateFormat.clone()); + // Set default User-Agent. setUserAgent("Java-Swagger"); @@ -81,6 +83,13 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } + /** + * Gets the JSON instance to do JSON serialization and deserialization. + */ + public JSON getJSON() { + return json; + } + public String getBasePath() { return basePath; } @@ -235,6 +244,8 @@ public class ApiClient { */ public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); return this; } 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 2ee5ab3e887..f238c37fb47 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 + * When lenientDatetimeFormat is enabled, 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/default/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/default/src/main/java/io/swagger/client/ApiClient.java index da7f3ba5a4e..bb8aaa7b990 100644 --- a/samples/client/petstore/java/default/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/default/src/main/java/io/swagger/client/ApiClient.java @@ -39,7 +39,7 @@ import io.swagger.client.auth.HttpBasicAuth; import io.swagger.client.auth.ApiKeyAuth; import io.swagger.client.auth.OAuth; -@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-11-02T21:16:46.418+08:00") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-11-07T15:05:10.376+08:00") public class ApiClient { private Map hostMap = new HashMap(); private Map defaultHeaderMap = new HashMap(); @@ -55,13 +55,15 @@ public class ApiClient { private DateFormat dateFormat; public ApiClient() { - // Use ISO 8601 format for date and datetime. - // See https://en.wikipedia.org/wiki/ISO_8601 - this.dateFormat = new SimpleDateFormat("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'T'HH:mm:ss.SSSXXX"); // Use UTC as the default time zone. this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + this.json.setDateFormat((DateFormat) dateFormat.clone()); + // Set default User-Agent. setUserAgent("Java-Swagger"); @@ -73,6 +75,13 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } + /** + * Gets the JSON instance to do JSON serialization and deserialization. + */ + public JSON getJSON() { + return json; + } + public String getBasePath() { return basePath; } @@ -226,6 +235,8 @@ public class ApiClient { */ public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); return this; } diff --git a/samples/client/petstore/java/default/src/main/java/io/swagger/client/JSON.java b/samples/client/petstore/java/default/src/main/java/io/swagger/client/JSON.java index 60872714a37..180f9b8cc19 100644 --- a/samples/client/petstore/java/default/src/main/java/io/swagger/client/JSON.java +++ b/samples/client/petstore/java/default/src/main/java/io/swagger/client/JSON.java @@ -4,9 +4,11 @@ import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.datatype.joda.*; +import java.text.DateFormat; + import java.io.IOException; -@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-10-30T16:36:47.681+08:00") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-11-07T15:05:10.376+08:00") public class JSON { private ObjectMapper mapper; @@ -20,6 +22,13 @@ public class JSON { mapper.registerModule(new JodaModule()); } + /** + * Set the date format for JSON (de)serialization with Date properties. + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + /** * Serialize the given Java object into JSON string. */ diff --git a/samples/client/petstore/java/default/src/test/java/io/swagger/client/ApiClientTest.java b/samples/client/petstore/java/default/src/test/java/io/swagger/client/ApiClientTest.java index 802c0cae3b9..3d57f3fa84c 100644 --- a/samples/client/petstore/java/default/src/test/java/io/swagger/client/ApiClientTest.java +++ b/samples/client/petstore/java/default/src/test/java/io/swagger/client/ApiClientTest.java @@ -2,6 +2,8 @@ package io.swagger.client; import io.swagger.client.auth.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.*; import org.junit.*; @@ -16,6 +18,26 @@ public class ApiClientTest { apiClient = new ApiClient(); } + @Test + public void testParseAndFormatDate() { + // default date format + String dateStr = "2015-11-07T03:49:09.356Z"; + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T03:49:09.356+00:00"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T03:49:09.356Z"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T05:49:09.356+02:00"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T02:49:09.356-01:00"))); + + // custom date 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.setDateFormat(format); + dateStr = "2015-11-07T13:49:09+10:00"; + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T03:49:09+00:00"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T03:49:09Z"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T00:49:09-03:00"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T13:49:09+10:00"))); + } + @Test public void testSelectHeaderAccept() { String[] accepts = {"APPLICATION/JSON", "APPLICATION/XML"}; diff --git a/samples/client/petstore/java/default/src/test/java/io/swagger/client/JSONTest.java b/samples/client/petstore/java/default/src/test/java/io/swagger/client/JSONTest.java new file mode 100644 index 00000000000..1250a135078 --- /dev/null +++ b/samples/client/petstore/java/default/src/test/java/io/swagger/client/JSONTest.java @@ -0,0 +1,52 @@ +package io.swagger.client; + +import io.swagger.client.model.Order; + +import java.lang.Exception; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.TimeZone; + +import org.junit.*; +import static org.junit.Assert.*; + + +public class JSONTest { + JSON json = null; + Order order = null; + + @Before + public void setup() { + json = new JSON(); + order = new Order(); + } + + @Test + public void testDefaultDate() throws Exception { + final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + final String dateStr = "2015-11-07T14:11:05.267Z"; + order.setShipDate(dateFormat.parse(dateStr)); + + String str = json.serialize(order); + TypeRef typeRef = new TypeRef() { }; + Order o = json.deserialize(str, typeRef); + assertEquals(dateStr, dateFormat.format(o.getShipDate())); + } + + @Test + public void testCustomDate() throws Exception { + final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT-2")); + final String dateStr = "2015-11-07T14:11:05-02:00"; + order.setShipDate(dateFormat.parse(dateStr)); + + json.setDateFormat(dateFormat); + String str = json.serialize(order); + TypeRef typeRef = new TypeRef() { }; + Order o = json.deserialize(str, typeRef); + assertEquals(dateStr, dateFormat.format(o.getShipDate())); + } +} \ No newline at end of file diff --git a/samples/client/petstore/java/default/src/test/java/io/swagger/petstore/test/StoreApiTest.java b/samples/client/petstore/java/default/src/test/java/io/swagger/petstore/test/StoreApiTest.java index a1fd7e345a8..6094f2242e1 100644 --- a/samples/client/petstore/java/default/src/test/java/io/swagger/petstore/test/StoreApiTest.java +++ b/samples/client/petstore/java/default/src/test/java/io/swagger/petstore/test/StoreApiTest.java @@ -8,6 +8,7 @@ import io.swagger.client.auth.*; import io.swagger.client.model.*; import java.util.Map; +import java.text.SimpleDateFormat; import org.junit.*; import static org.junit.Assert.*; @@ -21,6 +22,8 @@ public class StoreApiTest { // setup authentication ApiKeyAuth apiKeyAuth = (ApiKeyAuth) api.getApiClient().getAuthentication("api_key"); apiKeyAuth.setApiKey("special-key"); + // set custom date format that is used by the petstore server + api.getApiClient().setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); } @Test diff --git a/samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/ApiClient.java index 1fc3258b9dc..9bbc5407af0 100644 --- a/samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/ApiClient.java @@ -43,7 +43,7 @@ import io.swagger.client.auth.HttpBasicAuth; import io.swagger.client.auth.ApiKeyAuth; import io.swagger.client.auth.OAuth; -@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-11-02T22:10:35.641+08:00") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-11-09T11:02:32.553+08:00") public class ApiClient { private Client client; private Map hostMap = new HashMap(); @@ -60,13 +60,15 @@ public class ApiClient { private DateFormat dateFormat; public ApiClient() { - // Use ISO 8601 format for date and datetime. - // See https://en.wikipedia.org/wiki/ISO_8601 - this.dateFormat = new SimpleDateFormat("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'T'HH:mm:ss.SSSXXX"); // Use UTC as the default time zone. this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + this.json.setDateFormat((DateFormat) dateFormat.clone()); + // Set default User-Agent. setUserAgent("Java-Swagger"); @@ -80,6 +82,13 @@ public class ApiClient { authentications = Collections.unmodifiableMap(authentications); } + /** + * Gets the JSON instance to do JSON serialization and deserialization. + */ + public JSON getJSON() { + return json; + } + public String getBasePath() { return basePath; } @@ -234,6 +243,8 @@ public class ApiClient { */ public ApiClient setDateFormat(DateFormat dateFormat) { this.dateFormat = dateFormat; + // also set the date format for model (de)serialization with Date properties + this.json.setDateFormat((DateFormat) dateFormat.clone()); return this; } diff --git a/samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/JSON.java b/samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/JSON.java index 8ce930ce5c1..35ab10fd9c6 100644 --- a/samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/JSON.java +++ b/samples/client/petstore/java/jersey2/src/main/java/io/swagger/client/JSON.java @@ -4,9 +4,11 @@ import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.datatype.joda.*; +import java.text.DateFormat; + import java.io.IOException; -@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-10-21T11:55:20.020+08:00") +@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2015-11-09T11:02:32.553+08:00") public class JSON { private ObjectMapper mapper; @@ -20,6 +22,13 @@ public class JSON { mapper.registerModule(new JodaModule()); } + /** + * Set the date format for JSON (de)serialization with Date properties. + */ + public void setDateFormat(DateFormat dateFormat) { + mapper.setDateFormat(dateFormat); + } + /** * Serialize the given Java object into JSON string. */ diff --git a/samples/client/petstore/java/jersey2/src/test/java/io/swagger/client/ApiClientTest.java b/samples/client/petstore/java/jersey2/src/test/java/io/swagger/client/ApiClientTest.java index 802c0cae3b9..3d57f3fa84c 100644 --- a/samples/client/petstore/java/jersey2/src/test/java/io/swagger/client/ApiClientTest.java +++ b/samples/client/petstore/java/jersey2/src/test/java/io/swagger/client/ApiClientTest.java @@ -2,6 +2,8 @@ package io.swagger.client; import io.swagger.client.auth.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.*; import org.junit.*; @@ -16,6 +18,26 @@ public class ApiClientTest { apiClient = new ApiClient(); } + @Test + public void testParseAndFormatDate() { + // default date format + String dateStr = "2015-11-07T03:49:09.356Z"; + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T03:49:09.356+00:00"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T03:49:09.356Z"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T05:49:09.356+02:00"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T02:49:09.356-01:00"))); + + // custom date 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.setDateFormat(format); + dateStr = "2015-11-07T13:49:09+10:00"; + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T03:49:09+00:00"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T03:49:09Z"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T00:49:09-03:00"))); + assertEquals(dateStr, apiClient.formatDate(apiClient.parseDate("2015-11-07T13:49:09+10:00"))); + } + @Test public void testSelectHeaderAccept() { String[] accepts = {"APPLICATION/JSON", "APPLICATION/XML"}; diff --git a/samples/client/petstore/java/jersey2/src/test/java/io/swagger/client/JSONTest.java b/samples/client/petstore/java/jersey2/src/test/java/io/swagger/client/JSONTest.java new file mode 100644 index 00000000000..1250a135078 --- /dev/null +++ b/samples/client/petstore/java/jersey2/src/test/java/io/swagger/client/JSONTest.java @@ -0,0 +1,52 @@ +package io.swagger.client; + +import io.swagger.client.model.Order; + +import java.lang.Exception; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.TimeZone; + +import org.junit.*; +import static org.junit.Assert.*; + + +public class JSONTest { + JSON json = null; + Order order = null; + + @Before + public void setup() { + json = new JSON(); + order = new Order(); + } + + @Test + public void testDefaultDate() throws Exception { + final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + final String dateStr = "2015-11-07T14:11:05.267Z"; + order.setShipDate(dateFormat.parse(dateStr)); + + String str = json.serialize(order); + TypeRef typeRef = new TypeRef() { }; + Order o = json.deserialize(str, typeRef); + assertEquals(dateStr, dateFormat.format(o.getShipDate())); + } + + @Test + public void testCustomDate() throws Exception { + final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT-2")); + final String dateStr = "2015-11-07T14:11:05-02:00"; + order.setShipDate(dateFormat.parse(dateStr)); + + json.setDateFormat(dateFormat); + String str = json.serialize(order); + TypeRef typeRef = new TypeRef() { }; + Order o = json.deserialize(str, typeRef); + assertEquals(dateStr, dateFormat.format(o.getShipDate())); + } +} \ No newline at end of file diff --git a/samples/client/petstore/java/jersey2/src/test/java/io/swagger/petstore/test/StoreApiTest.java b/samples/client/petstore/java/jersey2/src/test/java/io/swagger/petstore/test/StoreApiTest.java index a1fd7e345a8..6094f2242e1 100644 --- a/samples/client/petstore/java/jersey2/src/test/java/io/swagger/petstore/test/StoreApiTest.java +++ b/samples/client/petstore/java/jersey2/src/test/java/io/swagger/petstore/test/StoreApiTest.java @@ -8,6 +8,7 @@ import io.swagger.client.auth.*; import io.swagger.client.model.*; import java.util.Map; +import java.text.SimpleDateFormat; import org.junit.*; import static org.junit.Assert.*; @@ -21,6 +22,8 @@ public class StoreApiTest { // setup authentication ApiKeyAuth apiKeyAuth = (ApiKeyAuth) api.getApiClient().getAuthentication("api_key"); apiKeyAuth.setApiKey("special-key"); + // set custom date format that is used by the petstore server + api.getApiClient().setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); } @Test 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 88b8f5602d1..51c3d5464f2 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 + * When lenientDatetimeFormat is enabled, 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 802c0cae3b9..aaf4f33c49e 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 00000000000..fdc2e4c7d4a --- /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 diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/petstore/test/StoreApiTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/petstore/test/StoreApiTest.java index a1fd7e345a8..589dae1a3ca 100644 --- a/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/petstore/test/StoreApiTest.java +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/io/swagger/petstore/test/StoreApiTest.java @@ -8,6 +8,7 @@ import io.swagger.client.auth.*; import io.swagger.client.model.*; import java.util.Map; +import java.text.SimpleDateFormat; import org.junit.*; import static org.junit.Assert.*; @@ -21,6 +22,12 @@ public class StoreApiTest { // setup authentication ApiKeyAuth apiKeyAuth = (ApiKeyAuth) api.getApiClient().getAuthentication("api_key"); apiKeyAuth.setApiKey("special-key"); + // set custom date format that is used by the petstore server + // Note: it would still work without this setting as okhttp-gson Java client supports + // various date formats by default (with lenientDatetimeFormat enabled), including + // the one used by petstore server + api.getApiClient().setDatetimeFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); + api.getApiClient().setLenientDatetimeFormat(false); } @Test