Repository: assertj/assertj (Java)

Issue:
Add "yyyy-MM-dd'T'HH:mm:ssX" timezone aware format to default ones. 
#### Summary

Add "yyyy-MM-dd'T'HH:mm:ssX" to the default date formats to support TZ comparison.

#### Example

```java
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.clear();
cal.set(2017, Calendar.NOVEMBER, 27, 20, 13, 24);
Date date = cal.getTime();

assertThat(date)
    .isEqualTo("2017-11-27T20:13:24+00:00");
```

See #1123 




Hints:

Patch:
diff --git a/src/main/java/org/assertj/core/api/AbstractDateAssert.java b/src/main/java/org/assertj/core/api/AbstractDateAssert.java
--- a/src/main/java/org/assertj/core/api/AbstractDateAssert.java
+++ b/src/main/java/org/assertj/core/api/AbstractDateAssert.java
@@ -16,10 +16,7 @@
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.assertj.core.util.DateUtil.newIsoDateFormat;
-import static org.assertj.core.util.DateUtil.newIsoDateTimeFormat;
-import static org.assertj.core.util.DateUtil.newIsoDateTimeWithMsFormat;
-import static org.assertj.core.util.DateUtil.newTimestampDateFormat;
+import static org.assertj.core.util.DateUtil.*;
 import static org.assertj.core.util.Lists.newArrayList;
 import static org.assertj.core.util.Preconditions.checkNotNull;
 
@@ -68,6 +65,7 @@ public abstract class AbstractDateAssert<SELF extends AbstractDateAssert<SELF>>
    */
   private static final List<DateFormat> DEFAULT_DATE_FORMATS = newArrayList(newIsoDateTimeWithMsFormat(),
                                                                             newTimestampDateFormat(),
+                                                                            newIsoDateTimeWithUtcTimeZoneFormat(),
                                                                             newIsoDateTimeFormat(),
                                                                             newIsoDateFormat());
 
diff --git a/src/main/java/org/assertj/core/api/Assertions.java b/src/main/java/org/assertj/core/api/Assertions.java
--- a/src/main/java/org/assertj/core/api/Assertions.java
+++ b/src/main/java/org/assertj/core/api/Assertions.java
@@ -2447,7 +2447,8 @@ public static void setLenientDateParsing(boolean value) {
    *   assertThat(date).isEqualTo("2003/04/26");
    * } catch (AssertionError e) {
    *   assertThat(e).hasMessage("Failed to parse 2003/04/26 with any of these date formats: " +
-   *                            "[yyyy-MM-dd'T'HH:mm:ss.SSS, yyyy-MM-dd'T'HH:mm:ss, yyyy-MM-dd]");
+   *                            "[yyyy-MM-dd'T'HH:mm:ss.SSS, yyyy-MM-dd'T'HH:mm:ssX, " +
+   *                            "yyyy-MM-dd'T'HH:mm:ss, yyyy-MM-dd]");
    * }
    *
    * // registering a custom date format to make the assertion pass
@@ -2492,7 +2493,8 @@ public static void registerCustomDateFormat(DateFormat userCustomDateFormat) {
    *   assertThat(date).isEqualTo("2003/04/26");
    * } catch (AssertionError e) {
    *   assertThat(e).hasMessage("Failed to parse 2003/04/26 with any of these date formats: " +
-   *                            "[yyyy-MM-dd'T'HH:mm:ss.SSS, yyyy-MM-dd'T'HH:mm:ss, yyyy-MM-dd]");
+   *                            "[yyyy-MM-dd'T'HH:mm:ss.SSS, yyyy-MM-dd'T'HH:mm:ssX, " +
+   *                            "yyyy-MM-dd'T'HH:mm:ss, yyyy-MM-dd]");
    * }
    *
    * // registering a custom date format to make the assertion pass
@@ -2517,6 +2519,7 @@ public static void registerCustomDateFormat(String userCustomDateFormatPattern)
    * <ul>
    * <li><code>yyyy-MM-dd'T'HH:mm:ss.SSS</code></li>
    * <li><code>yyyy-MM-dd HH:mm:ss.SSS</code> (for {@link Timestamp} String representation support)</li>
+   * <li><code>yyyy-MM-dd'T'HH:mm:ssX</code></li>
    * <li><code>yyyy-MM-dd'T'HH:mm:ss</code></li>
    * <li><code>yyyy-MM-dd</code></li>
    * </ul>
diff --git a/src/main/java/org/assertj/core/util/DateUtil.java b/src/main/java/org/assertj/core/util/DateUtil.java
--- a/src/main/java/org/assertj/core/util/DateUtil.java
+++ b/src/main/java/org/assertj/core/util/DateUtil.java
@@ -56,6 +56,14 @@ public static DateFormat newIsoDateFormat() {
     return strictDateFormatForPattern("yyyy-MM-dd");
   }
 
+  /**
+   * ISO 8601 date-time format with UTC time zone (yyyy-MM-dd'T'HH:mm:ssX), example :
+   * <code>2003-04-26T03:01:02+00:00</code>
+   */
+  public static DateFormat newIsoDateTimeWithUtcTimeZoneFormat() {
+    return strictDateFormatForPattern("yyyy-MM-dd'T'HH:mm:ssX");
+  }
+
   /**
    * ISO 8601 date-time format (yyyy-MM-dd'T'HH:mm:ss), example : <code>2003-04-26T13:01:02</code>
    * @return a {@code yyyy-MM-dd'T'HH:mm:ss} {@link DateFormat}


Test patch:
diff --git a/src/test/java/org/assertj/core/api/date/AbstractDateAssertWithDateArg_Test.java b/src/test/java/org/assertj/core/api/date/AbstractDateAssertWithDateArg_Test.java
--- a/src/test/java/org/assertj/core/api/date/AbstractDateAssertWithDateArg_Test.java
+++ b/src/test/java/org/assertj/core/api/date/AbstractDateAssertWithDateArg_Test.java
@@ -89,6 +89,7 @@ public void should_fail_because_date_string_representation_does_not_follow_expec
                                 " with any of these date formats:%n" +
                                 "   [yyyy-MM-dd'T'HH:mm:ss.SSS,%n" +
                                 "    yyyy-MM-dd HH:mm:ss.SSS,%n" +
+                                "    yyyy-MM-dd'T'HH:mm:ssX,%n" +
                                 "    yyyy-MM-dd'T'HH:mm:ss,%n" +
                                 "    yyyy-MM-dd]");
     assertionInvocationWithStringArg(dateAsStringWithBadFormat);
diff --git a/src/test/java/org/assertj/core/api/date/DateAssert_with_string_based_date_representation_Test.java b/src/test/java/org/assertj/core/api/date/DateAssert_with_string_based_date_representation_Test.java
--- a/src/test/java/org/assertj/core/api/date/DateAssert_with_string_based_date_representation_Test.java
+++ b/src/test/java/org/assertj/core/api/date/DateAssert_with_string_based_date_representation_Test.java
@@ -25,6 +25,7 @@
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.TimeZone;
 
 import org.assertj.core.api.DateAssertBaseTest;
 import org.assertj.core.test.ExpectedException;
@@ -51,6 +52,7 @@ public void tearDown() {
 
   @Test
   public void date_assertion_using_default_date_string_representation() {
+
     // datetime with ms is supported
     final Date date1timeWithMS = parseDatetimeWithMs("2003-04-26T03:01:02.999");
     assertThat(date1timeWithMS).isEqualTo("2003-04-26T03:01:02.999");
@@ -73,12 +75,36 @@ public void date_assertion_should_support_timestamp_string_representation() thro
     assertThat(date).isEqualTo(timestampAsString);
   }
 
+  @Test
+  public void date_assertion_should_support_date_with_utc_time_zone_string_representation() throws ParseException {
+    SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+    isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+    Date date = isoFormat.parse("2003-04-26T00:00:00");
+
+    assertThat(date).isEqualTo("2003-04-26T00:00:00+00:00");
+  }
+
+  @Test
+  public void date_assertion_should_support_date_with_utc_time_zone_in_different_time_zone_string_representation() throws ParseException {
+    SimpleDateFormat isoDateFormatUtc = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+    isoDateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+    SimpleDateFormat isoDateFormatNewYork = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
+    isoDateFormatNewYork.setTimeZone(TimeZone.getTimeZone("America/New_York"));
+
+    Date date = isoDateFormatUtc.parse("2003-04-26T00:00:00");
+    String newYorkDate = isoDateFormatNewYork.format(date);
+
+    assertThat(date).isEqualTo(newYorkDate);
+  }
+
   @Test
   public void should_fail_if_given_date_string_representation_cant_be_parsed_with_default_date_formats() {
     final String dateAsString = "2003/04/26";
     thrown.expectAssertionError("Failed to parse 2003/04/26 with any of these date formats:%n" +
                                 "   [yyyy-MM-dd'T'HH:mm:ss.SSS,%n" +
                                 "    yyyy-MM-dd HH:mm:ss.SSS,%n" +
+                                "    yyyy-MM-dd'T'HH:mm:ssX,%n" +
                                 "    yyyy-MM-dd'T'HH:mm:ss,%n" +
                                 "    yyyy-MM-dd]");
     assertThat(new Date()).isEqualTo(dateAsString);
@@ -98,6 +124,7 @@ public void should_fail_if_given_date_string_representation_cant_be_parsed_with_
                                 "    yyyy/MM/dd,%n" +
                                 "    yyyy-MM-dd'T'HH:mm:ss.SSS,%n" +
                                 "    yyyy-MM-dd HH:mm:ss.SSS,%n" +
+                                "    yyyy-MM-dd'T'HH:mm:ssX,%n" +
                                 "    yyyy-MM-dd'T'HH:mm:ss,%n" +
                                 "    yyyy-MM-dd]");
     final Date date = DateUtil.parse("2003-04-26");
@@ -133,6 +160,7 @@ public void use_custom_date_formats_set_from_Assertions_entry_point() {
                                       "   [yyyy/MM/dd'T'HH:mm:ss,%n" +
                                       "    yyyy-MM-dd'T'HH:mm:ss.SSS,%n" +
                                       "    yyyy-MM-dd HH:mm:ss.SSS,%n" +
+                                      "    yyyy-MM-dd'T'HH:mm:ssX,%n" +
                                       "    yyyy-MM-dd'T'HH:mm:ss,%n" +
                                       "    yyyy-MM-dd]"));
     }
@@ -165,6 +193,7 @@ public void use_custom_date_formats_first_then_defaults_to_parse_a_date() {
       assertThat(e).hasMessage(format("Failed to parse 2003/04/26 with any of these date formats:%n" +
                                       "   [yyyy-MM-dd'T'HH:mm:ss.SSS,%n" +
                                       "    yyyy-MM-dd HH:mm:ss.SSS,%n" +
+                                      "    yyyy-MM-dd'T'HH:mm:ssX,%n" +
                                       "    yyyy-MM-dd'T'HH:mm:ss,%n" +
                                       "    yyyy-MM-dd]"));
     }
@@ -185,6 +214,7 @@ public void use_custom_date_formats_first_then_defaults_to_parse_a_date() {
                                       "   [yyyy/MM/dd,%n" +
                                       "    yyyy-MM-dd'T'HH:mm:ss.SSS,%n" +
                                       "    yyyy-MM-dd HH:mm:ss.SSS,%n" +
+                                      "    yyyy-MM-dd'T'HH:mm:ssX,%n" +
                                       "    yyyy-MM-dd'T'HH:mm:ss,%n" +
                                       "    yyyy-MM-dd]"));