From 51077e8ad0757b98d979dbc0969cfc7052041e44 Mon Sep 17 00:00:00 2001 From: Andrea Gazzarini Date: Fri, 30 Nov 2018 12:06:37 +0100 Subject: [PATCH] SEARCH-1286 date type casting errors (#27) * [ SEARCH-1286 ] additional ThreadLocal + date format (UTC - msecs) * [ SEARCH-1286 ] ThreadLocal + other minor refactoring + unit tests * [ SEARCH-1286 ] Fixed Timezone issue in Unit tests * [ SEARCH-1286 ] Fixed Timezone issue II in Unit tests * [ SEARCH-1286 ] Fixed Locale issue in CachingDataFormat * Merge branches 'fix/SEARCH-1286_date_type_casting_errors' and 'master' of https://github.com/Alfresco/alfresco-core into fix/SEARCH-1286_date_type_casting_errors # Conflicts: # src/main/java/org/alfresco/util/CachingDateFormat.java # src/test/java/org/alfresco/util/CachingDateFormatTest.java --- .../org/alfresco/util/CachingDateFormat.java | 47 ++++++++++++------- .../alfresco/util/CachingDateFormatTest.java | 28 +++++++---- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/alfresco/util/CachingDateFormat.java b/src/main/java/org/alfresco/util/CachingDateFormat.java index 446e9567ee..c719c42276 100644 --- a/src/main/java/org/alfresco/util/CachingDateFormat.java +++ b/src/main/java/org/alfresco/util/CachingDateFormat.java @@ -18,7 +18,8 @@ */ package org.alfresco.util; -import java.text.NumberFormat; +import static java.util.Arrays.stream; + import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; @@ -27,8 +28,6 @@ import java.util.*; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; -import static java.util.Arrays.stream; - /** * Provides thread safe means of obtaining a cached date formatter. *

@@ -85,37 +84,34 @@ public class CachingDateFormat extends SimpleDateFormat new StringAndResolution("yyyy", Calendar.YEAR) }; - private static ThreadLocal S_LOCAL_DATE_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_FULL_GENERIC)); + static ThreadLocal S_LOCAL_DATE_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_FULL_GENERIC)); - private static ThreadLocal S_LOCAL_DATEONLY_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_DATE_GENERIC)); + static ThreadLocal S_LOCAL_DATEONLY_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_DATE_GENERIC)); - private static ThreadLocal S_LOCAL_TIMEONLY_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_TIME_GENERIC)); + static ThreadLocal S_LOCAL_TIMEONLY_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_TIME_GENERIC)); - private static ThreadLocal S_LOCAL_CMIS_SQL_DATETIME = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_CMIS_SQL)); + static ThreadLocal S_LOCAL_CMIS_SQL_DATETIME = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_CMIS_SQL)); - private static ThreadLocal S_LOCAL_SOLR_DATETIME = ThreadLocal.withInitial(()-> + static ThreadLocal S_LOCAL_SOLR_DATETIME = ThreadLocal.withInitial(()-> { - CachingDateFormat formatter = newDateFormat(FORMAT_SOLR); + CachingDateFormat formatter = newDateFormatWithLocale(FORMAT_SOLR, Locale.ENGLISH); /* SEARCH-1263 Apache Solr only supports the ISO 8601 date format: UTC and western locale are mandatory (only Arabic numerals (0123456789) are supported) */ formatter.setTimeZone(TimeZone.getTimeZone(UTC)); - formatter.setNumberFormat(NumberFormat.getNumberInstance(Locale.ENGLISH)); return formatter; }); - private static ThreadLocal S_UTC_DATETIME_WITHOUT_MSECS = ThreadLocal.withInitial(() -> + static ThreadLocal S_UTC_DATETIME_WITHOUT_MSECS = ThreadLocal.withInitial(() -> { - CachingDateFormat formatter = newDateFormat(UTC_WITHOUT_MSECS); + CachingDateFormat formatter = newDateFormatWithLocale(UTC_WITHOUT_MSECS, Locale.ENGLISH); formatter.setTimeZone(TimeZone.getTimeZone(UTC)); - formatter.setNumberFormat(NumberFormat.getNumberInstance(Locale.ENGLISH)); - return formatter; }); - private static ThreadLocal S_LENIENT_PARSERS = + static ThreadLocal S_LENIENT_PARSERS = ThreadLocal.withInitial(() -> stream(LENIENT_FORMATS) .map(format -> { @@ -126,6 +122,11 @@ public class CachingDateFormat extends SimpleDateFormat private Map cacheDates = new WeakHashMap<>(89); + private CachingDateFormat(String pattern, Locale locale) + { + super(pattern, locale); + } + private CachingDateFormat(String pattern) { super(pattern); @@ -325,8 +326,6 @@ public class CachingDateFormat extends SimpleDateFormat } throw new ParseException("Unknown date format", 0); - - } public static SimpleDateFormatAndResolution[] getLenientFormatters() @@ -403,4 +402,18 @@ public class CachingDateFormat extends SimpleDateFormat formatter.setLenient(false); return formatter; } + + /** + * Creates a new non-lenient localised {@link CachingDateFormat} instance. + * + * @param pattern the date / datetime pattern. + * @param locale the locale. + * @return new non-lenient {@link CachingDateFormat} instance. + */ + private static CachingDateFormat newDateFormatWithLocale(String pattern, Locale locale) + { + CachingDateFormat formatter = new CachingDateFormat(pattern, locale); + formatter.setLenient(false); + return formatter; + } } diff --git a/src/test/java/org/alfresco/util/CachingDateFormatTest.java b/src/test/java/org/alfresco/util/CachingDateFormatTest.java index ecf964d8d0..dfd3096181 100644 --- a/src/test/java/org/alfresco/util/CachingDateFormatTest.java +++ b/src/test/java/org/alfresco/util/CachingDateFormatTest.java @@ -18,7 +18,12 @@ */ package org.alfresco.util; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + import org.junit.After; +import org.junit.Before; import org.junit.Test; import java.text.SimpleDateFormat; @@ -29,24 +34,26 @@ import java.util.Date; import java.util.Locale; import java.util.TimeZone; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; - public class CachingDateFormatTest { private final LocalDateTime REFERENCE_DATE_TIME = LocalDateTime.of(2018, 4, 1, 10, 0); //2018-04-01 at 10:00am private final Locale defaultLocale = Locale.getDefault(); - + + @Before + public void setUp() + { + CachingDateFormat.S_LOCAL_SOLR_DATETIME.remove(); + } + @Test - public void solrDatetimeFormat_DateNotUTC_shouldReturnISO8601DateString() + public void solrDatetimeFormat_shouldFormatTheMinDate() { Date shanghaiDate = testDate("Asia/Shanghai"); - SimpleDateFormat solrDatetimeFormat = CachingDateFormat.getSolrDatetimeFormat(); - + SimpleDateFormat solrDatetimeFormat = CachingDateFormat.getSolrDatetimeFormatWithoutMsecs(); + String formattedDate = solrDatetimeFormat.format(shanghaiDate); - - assertThat(formattedDate,is("2018-04-01T02:00:00.000Z")); + + assertThat(formattedDate,is("2018-04-01T02:00:00Z")); } @Test @@ -54,6 +61,7 @@ public class CachingDateFormatTest { for(Locale currentLocale:Locale.getAvailableLocales()) { + CachingDateFormat.S_LOCAL_SOLR_DATETIME.remove(); Locale.setDefault(currentLocale); Date utcDate = testDate("UTC");