From 140dd8711c3f2189db74aca5479c8314d550391c Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Wed, 1 Jun 2011 11:52:56 -0700 Subject: [PATCH] Issue 574: work around bad date format --- .../org/jclouds/date/internal/DateUtils.java | 52 +++++++++++++++++++ .../internal/SimpleDateFormatDateService.java | 43 +++------------ .../org/jclouds/date/DateServiceTest.java | 34 +++++++----- .../jclouds/date/joda/JodaDateService.java | 33 +++--------- 4 files changed, 89 insertions(+), 73 deletions(-) create mode 100644 core/src/main/java/org/jclouds/date/internal/DateUtils.java diff --git a/core/src/main/java/org/jclouds/date/internal/DateUtils.java b/core/src/main/java/org/jclouds/date/internal/DateUtils.java new file mode 100644 index 0000000000..ae7e3f4e21 --- /dev/null +++ b/core/src/main/java/org/jclouds/date/internal/DateUtils.java @@ -0,0 +1,52 @@ +/** + * + * Copyright (C) 2011 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ==================================================================== + */ +package org.jclouds.date.internal; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author Adrian Cole + */ +public class DateUtils { + + public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern.compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]"); + + public static final Pattern TZ_PATTERN = Pattern.compile("(.*)[+-][0-9][0-9]:?[0-9][0-9]Z?"); + + public static String trimNanosToMillis(String toParse) { + if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches()) + toParse = toParse.substring(0, toParse.length() - 3) + 'Z'; + return toParse; + } + + public static final Pattern SECOND_PATTERN = Pattern.compile(".*[0-2][0-9]:00"); + + public static String trimTZ(String toParse) { + Matcher matcher = TZ_PATTERN.matcher(toParse); + if (matcher.find()) { + toParse = matcher.group(1) + 'Z'; + } + if (toParse.length() == 25 && SECOND_PATTERN.matcher(toParse).matches()) + toParse = toParse.substring(0, toParse.length() - 6) + 'Z'; + return toParse; + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java b/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java index 8a9f8249a3..9dbe5a6686 100755 --- a/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java +++ b/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java @@ -17,18 +17,16 @@ * ==================================================================== */ package org.jclouds.date.internal; +import static org.jclouds.date.internal.DateUtils.trimNanosToMillis; +import static org.jclouds.date.internal.DateUtils.trimTZ; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.SimpleTimeZone; -import java.util.regex.Pattern; - -import javax.annotation.Resource; import org.jclouds.date.DateService; -import org.jclouds.logging.Logger; /** * @@ -39,8 +37,6 @@ import org.jclouds.logging.Logger; */ public class SimpleDateFormatDateService implements DateService { - @Resource - protected Logger logger = Logger.NULL; /* * Use default Java Date/SimpleDateFormat classes for date manipulation, but be *very* careful to * guard against the lack of thread safety. @@ -50,16 +46,16 @@ public class SimpleDateFormatDateService implements DateService { "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); // @GuardedBy("this") - private static final SimpleDateFormat iso8601SimpleDateFormat = new SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); + private static final SimpleDateFormat iso8601SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", + Locale.US); // @GuardedBy("this") - private static final SimpleDateFormat rfc822SimpleDateFormat = new SimpleDateFormat( - "EEE, dd MMM yyyy HH:mm:ss z", Locale.US); + private static final SimpleDateFormat rfc822SimpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", + Locale.US); // @GuardedBy("this") - private static final SimpleDateFormat cSimpleDateFormat = new SimpleDateFormat( - "EEE MMM dd HH:mm:ss '+0000' yyyy", Locale.US); + private static final SimpleDateFormat cSimpleDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss '+0000' yyyy", + Locale.US); static { iso8601SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT")); @@ -138,29 +134,6 @@ public class SimpleDateFormatDateService implements DateService { } } - public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern - .compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]"); - - public static final Pattern TZ_PATTERN = Pattern.compile(".*[+-][0-9][0-9]:?[0-9][0-9]"); - - private String trimNanosToMillis(String toParse) { - if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches()) - toParse = toParse.substring(0, toParse.length() - 3) + 'Z'; - return toParse; - } - - public static final Pattern SECOND_PATTERN = Pattern.compile(".*[0-2][0-9]:00"); - - private String trimTZ(String toParse) { - if (TZ_PATTERN.matcher(toParse).matches()) { - logger.trace("trimming tz from %s", toParse); - toParse = toParse.substring(0, toParse.length() - 6) + 'Z'; - } - if (toParse.length() == 25 && SECOND_PATTERN.matcher(toParse).matches()) - toParse = toParse.substring(0, toParse.length() - 6) + 'Z'; - return toParse; - } - public final Date iso8601SecondsDateParse(String toParse) { toParse = trimTZ(toParse); synchronized (iso8601SecondsSimpleDateFormat) { diff --git a/core/src/test/java/org/jclouds/date/DateServiceTest.java b/core/src/test/java/org/jclouds/date/DateServiceTest.java index 37aaba1ace..f93eb01c18 100755 --- a/core/src/test/java/org/jclouds/date/DateServiceTest.java +++ b/core/src/test/java/org/jclouds/date/DateServiceTest.java @@ -68,7 +68,7 @@ public class DateServiceTest extends PerformanceTest { public final Date date; TestData(String iso8601, String iso8601DateStringTz, String iso8601Seconds, String rfc822, String cDateString, - Date dateTime) { + Date dateTime) { this.iso8601DateString = iso8601; this.iso8601DateStringTz = iso8601DateStringTz; this.iso8601SecondsDateString = iso8601Seconds; @@ -81,18 +81,18 @@ public class DateServiceTest extends PerformanceTest { public DateServiceTest() { // Constant time test values, each TestData item must contain matching times! testData = new TestData[] { - new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07-04:00", "2009-03-12T02:00:07Z", - "Thu, 12 Mar 2009 02:00:07 GMT", "Thu Mar 12 02:00:07 +0000 2009", new Date(1236823207000l)), - new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07+04:00", "2009-03-12T02:00:07Z", - "Thu, 12 Mar 2009 02:00:07 GMT", "Thu Mar 12 02:00:07 +0000 2009", new Date(1236823207000l)), - new TestData("2009-03-14T04:00:07.000Z", "2009-03-14T04:00:07Z+04:00", "2009-03-14T04:00:07Z", - "Sat, 14 Mar 2009 04:00:07 GMT", "Thu Mar 14 04:00:07 +0000 2009", new Date(1237003207000l)), - new TestData("2009-03-16T06:00:07.000Z", "2009-03-16T06:00:07Z+04:00", "2009-03-16T06:00:07Z", - "Mon, 16 Mar 2009 06:00:07 GMT", "Thu Mar 16 06:00:07 +0000 2009", new Date(1237183207000l)), - new TestData("2009-03-18T08:00:07.000Z", "2009-03-18T08:00:07Z+04:00", "2009-03-18T08:00:07Z", - "Wed, 18 Mar 2009 08:00:07 GMT", "Thu Mar 18 08:00:07 +0000 2009", new Date(1237363207000l)), - new TestData("2009-03-20T10:00:07.000Z", "2009-03-20T10:00:07Z+04:00", "2009-03-20T10:00:07Z", - "Fri, 20 Mar 2009 10:00:07 GMT", "Thu Mar 20 10:00:07 +0000 2009", new Date(1237543207000l)) }; + new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07-04:00", "2009-03-12T02:00:07Z", + "Thu, 12 Mar 2009 02:00:07 GMT", "Thu Mar 12 02:00:07 +0000 2009", new Date(1236823207000l)), + new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07+04:00", "2009-03-12T02:00:07Z", + "Thu, 12 Mar 2009 02:00:07 GMT", "Thu Mar 12 02:00:07 +0000 2009", new Date(1236823207000l)), + new TestData("2009-03-14T04:00:07.000Z", "2009-03-14T04:00:07Z+04:00", "2009-03-14T04:00:07Z", + "Sat, 14 Mar 2009 04:00:07 GMT", "Thu Mar 14 04:00:07 +0000 2009", new Date(1237003207000l)), + new TestData("2009-03-16T06:00:07.000Z", "2009-03-16T06:00:07Z+04:00", "2009-03-16T06:00:07Z", + "Mon, 16 Mar 2009 06:00:07 GMT", "Thu Mar 16 06:00:07 +0000 2009", new Date(1237183207000l)), + new TestData("2009-03-18T08:00:07.000Z", "2009-03-18T08:00:07Z+04:00", "2009-03-18T08:00:07Z", + "Wed, 18 Mar 2009 08:00:07 GMT", "Thu Mar 18 08:00:07 +0000 2009", new Date(1237363207000l)), + new TestData("2009-03-20T10:00:07.000Z", "2009-03-20T10:00:07Z+04:00", "2009-03-20T10:00:07Z", + "Fri, 20 Mar 2009 10:00:07 GMT", "Thu Mar 20 10:00:07 +0000 2009", new Date(1237543207000l)) }; } @Test @@ -162,6 +162,14 @@ public class DateServiceTest extends PerformanceTest { assertEquals(dateService.rfc822DateFormat(date), "Sat, 26 Sep 2009 23:37:05 GMT"); } + @Test + void testTzWithExtraZ() throws ExecutionException, InterruptedException { + assertEquals(dateService.iso8601SecondsDateParse("2011-05-26T06:14:13-04:00").toString(), + "Wed May 25 23:14:13 PDT 2011"); + assertEquals(dateService.iso8601SecondsDateParse("2011-05-26T06:14:13-04:00Z").toString(), + "Wed May 25 23:14:13 PDT 2011"); + } + @Test void testRfc822DateFormatResponseTime() throws ExecutionException, InterruptedException { for (int i = 0; i < LOOP_COUNT; i++) diff --git a/drivers/joda/src/main/java/org/jclouds/date/joda/JodaDateService.java b/drivers/joda/src/main/java/org/jclouds/date/joda/JodaDateService.java index 86f72bc5a7..337c018235 100755 --- a/drivers/joda/src/main/java/org/jclouds/date/joda/JodaDateService.java +++ b/drivers/joda/src/main/java/org/jclouds/date/joda/JodaDateService.java @@ -18,9 +18,11 @@ */ package org.jclouds.date.joda; +import static org.jclouds.date.internal.DateUtils.trimNanosToMillis; +import static org.jclouds.date.internal.DateUtils.trimTZ; + import java.util.Date; import java.util.Locale; -import java.util.regex.Pattern; import javax.inject.Singleton; @@ -39,19 +41,16 @@ import org.joda.time.format.DateTimeFormatter; public class JodaDateService implements DateService { private static final DateTimeFormatter rfc822DateFormatter = DateTimeFormat.forPattern( - "EEE, dd MMM yyyy HH:mm:ss 'GMT'").withLocale(Locale.US).withZone( - DateTimeZone.forID("GMT")); + "EEE, dd MMM yyyy HH:mm:ss 'GMT'").withLocale(Locale.US).withZone(DateTimeZone.forID("GMT")); - private static final DateTimeFormatter cDateFormatter = DateTimeFormat.forPattern( - "EEE MMM dd HH:mm:ss '+0000' yyyy").withLocale(Locale.US).withZone( - DateTimeZone.forID("GMT")); + private static final DateTimeFormatter cDateFormatter = DateTimeFormat + .forPattern("EEE MMM dd HH:mm:ss '+0000' yyyy").withLocale(Locale.US).withZone(DateTimeZone.forID("GMT")); private static final DateTimeFormatter iso8601SecondsDateFormatter = DateTimeFormat.forPattern( "yyyy-MM-dd'T'HH:mm:ss'Z'").withLocale(Locale.US).withZone(DateTimeZone.forID("GMT")); private static final DateTimeFormatter iso8601DateFormatter = DateTimeFormat.forPattern( - "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withLocale(Locale.US).withZone( - DateTimeZone.forID("GMT")); + "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withLocale(Locale.US).withZone(DateTimeZone.forID("GMT")); public final Date fromSeconds(long seconds) { return new Date(seconds * 1000); @@ -98,27 +97,11 @@ public class JodaDateService implements DateService { } public final Date iso8601DateParse(String toParse) { + toParse = trimTZ(toParse); toParse = trimNanosToMillis(toParse); return iso8601DateFormatter.parseDateTime(toParse).toDate(); } - public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern - .compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]"); - - private String trimNanosToMillis(String toParse) { - if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches()) - toParse = toParse.substring(0, toParse.length() - 3) + 'Z'; - return toParse; - } - - public static final Pattern SECOND_PATTERN = Pattern.compile(".*[0-2][0-9]:00"); - - private String trimTZ(String toParse) { - if (toParse.length() == 25 && SECOND_PATTERN.matcher(toParse).matches()) - toParse = toParse.substring(0, toParse.length() - 6) + 'Z'; - return toParse; - } - public final Date iso8601SecondsDateParse(String toParse) { toParse = trimTZ(toParse); return iso8601SecondsDateFormatter.parseDateTime(toParse).toDate();