mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
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
This commit is contained in:
@@ -18,7 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.util;
|
package org.alfresco.util;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
import static java.util.Arrays.stream;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.ParsePosition;
|
import java.text.ParsePosition;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -27,8 +28,6 @@ import java.util.*;
|
|||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
import org.joda.time.format.ISODateTimeFormat;
|
import org.joda.time.format.ISODateTimeFormat;
|
||||||
|
|
||||||
import static java.util.Arrays.stream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides <b>thread safe</b> means of obtaining a cached date formatter.
|
* Provides <b>thread safe</b> means of obtaining a cached date formatter.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -85,37 +84,34 @@ public class CachingDateFormat extends SimpleDateFormat
|
|||||||
new StringAndResolution("yyyy", Calendar.YEAR)
|
new StringAndResolution("yyyy", Calendar.YEAR)
|
||||||
};
|
};
|
||||||
|
|
||||||
private static ThreadLocal<SimpleDateFormat> S_LOCAL_DATE_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_FULL_GENERIC));
|
static ThreadLocal<SimpleDateFormat> S_LOCAL_DATE_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_FULL_GENERIC));
|
||||||
|
|
||||||
private static ThreadLocal<SimpleDateFormat> S_LOCAL_DATEONLY_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_DATE_GENERIC));
|
static ThreadLocal<SimpleDateFormat> S_LOCAL_DATEONLY_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_DATE_GENERIC));
|
||||||
|
|
||||||
private static ThreadLocal<SimpleDateFormat> S_LOCAL_TIMEONLY_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_TIME_GENERIC));
|
static ThreadLocal<SimpleDateFormat> S_LOCAL_TIMEONLY_FORMAT = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_TIME_GENERIC));
|
||||||
|
|
||||||
private static ThreadLocal<SimpleDateFormat> S_LOCAL_CMIS_SQL_DATETIME = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_CMIS_SQL));
|
static ThreadLocal<SimpleDateFormat> S_LOCAL_CMIS_SQL_DATETIME = ThreadLocal.withInitial(() -> newDateFormat(FORMAT_CMIS_SQL));
|
||||||
|
|
||||||
private static ThreadLocal<SimpleDateFormat> S_LOCAL_SOLR_DATETIME = ThreadLocal.withInitial(()->
|
static ThreadLocal<SimpleDateFormat> S_LOCAL_SOLR_DATETIME = ThreadLocal.withInitial(()->
|
||||||
{
|
{
|
||||||
CachingDateFormat formatter = newDateFormat(FORMAT_SOLR);
|
CachingDateFormat formatter = newDateFormatWithLocale(FORMAT_SOLR, Locale.ENGLISH);
|
||||||
/*
|
/*
|
||||||
SEARCH-1263
|
SEARCH-1263
|
||||||
Apache Solr only supports the ISO 8601 date format:
|
Apache Solr only supports the ISO 8601 date format:
|
||||||
UTC and western locale are mandatory (only Arabic numerals (0123456789) are supported)
|
UTC and western locale are mandatory (only Arabic numerals (0123456789) are supported)
|
||||||
*/
|
*/
|
||||||
formatter.setTimeZone(TimeZone.getTimeZone(UTC));
|
formatter.setTimeZone(TimeZone.getTimeZone(UTC));
|
||||||
formatter.setNumberFormat(NumberFormat.getNumberInstance(Locale.ENGLISH));
|
|
||||||
return formatter;
|
return formatter;
|
||||||
});
|
});
|
||||||
|
|
||||||
private static ThreadLocal<SimpleDateFormat> S_UTC_DATETIME_WITHOUT_MSECS = ThreadLocal.withInitial(() ->
|
static ThreadLocal<SimpleDateFormat> 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.setTimeZone(TimeZone.getTimeZone(UTC));
|
||||||
formatter.setNumberFormat(NumberFormat.getNumberInstance(Locale.ENGLISH));
|
|
||||||
|
|
||||||
return formatter;
|
return formatter;
|
||||||
});
|
});
|
||||||
|
|
||||||
private static ThreadLocal<SimpleDateFormatAndResolution[]> S_LENIENT_PARSERS =
|
static ThreadLocal<SimpleDateFormatAndResolution[]> S_LENIENT_PARSERS =
|
||||||
ThreadLocal.withInitial(() ->
|
ThreadLocal.withInitial(() ->
|
||||||
stream(LENIENT_FORMATS)
|
stream(LENIENT_FORMATS)
|
||||||
.map(format -> {
|
.map(format -> {
|
||||||
@@ -126,6 +122,11 @@ public class CachingDateFormat extends SimpleDateFormat
|
|||||||
|
|
||||||
private Map<String, Date> cacheDates = new WeakHashMap<>(89);
|
private Map<String, Date> cacheDates = new WeakHashMap<>(89);
|
||||||
|
|
||||||
|
private CachingDateFormat(String pattern, Locale locale)
|
||||||
|
{
|
||||||
|
super(pattern, locale);
|
||||||
|
}
|
||||||
|
|
||||||
private CachingDateFormat(String pattern)
|
private CachingDateFormat(String pattern)
|
||||||
{
|
{
|
||||||
super(pattern);
|
super(pattern);
|
||||||
@@ -325,8 +326,6 @@ public class CachingDateFormat extends SimpleDateFormat
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new ParseException("Unknown date format", 0);
|
throw new ParseException("Unknown date format", 0);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SimpleDateFormatAndResolution[] getLenientFormatters()
|
public static SimpleDateFormatAndResolution[] getLenientFormatters()
|
||||||
@@ -403,4 +402,18 @@ public class CachingDateFormat extends SimpleDateFormat
|
|||||||
formatter.setLenient(false);
|
formatter.setLenient(false);
|
||||||
return formatter;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.util;
|
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.After;
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
@@ -29,24 +34,26 @@ import java.util.Date;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
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
|
public class CachingDateFormatTest
|
||||||
{
|
{
|
||||||
private final LocalDateTime REFERENCE_DATE_TIME = LocalDateTime.of(2018, 4, 1, 10, 0); //2018-04-01 at 10:00am
|
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();
|
private final Locale defaultLocale = Locale.getDefault();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
CachingDateFormat.S_LOCAL_SOLR_DATETIME.remove();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void solrDatetimeFormat_DateNotUTC_shouldReturnISO8601DateString()
|
public void solrDatetimeFormat_shouldFormatTheMinDate()
|
||||||
{
|
{
|
||||||
Date shanghaiDate = testDate("Asia/Shanghai");
|
Date shanghaiDate = testDate("Asia/Shanghai");
|
||||||
SimpleDateFormat solrDatetimeFormat = CachingDateFormat.getSolrDatetimeFormat();
|
SimpleDateFormat solrDatetimeFormat = CachingDateFormat.getSolrDatetimeFormatWithoutMsecs();
|
||||||
|
|
||||||
String formattedDate = solrDatetimeFormat.format(shanghaiDate);
|
String formattedDate = solrDatetimeFormat.format(shanghaiDate);
|
||||||
|
|
||||||
assertThat(formattedDate,is("2018-04-01T02:00:00.000Z"));
|
assertThat(formattedDate,is("2018-04-01T02:00:00Z"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -54,6 +61,7 @@ public class CachingDateFormatTest
|
|||||||
{
|
{
|
||||||
for(Locale currentLocale:Locale.getAvailableLocales())
|
for(Locale currentLocale:Locale.getAvailableLocales())
|
||||||
{
|
{
|
||||||
|
CachingDateFormat.S_LOCAL_SOLR_DATETIME.remove();
|
||||||
Locale.setDefault(currentLocale);
|
Locale.setDefault(currentLocale);
|
||||||
|
|
||||||
Date utcDate = testDate("UTC");
|
Date utcDate = testDate("UTC");
|
||||||
|
Reference in New Issue
Block a user