From 5d8eb2424b51e6575fb66ff310867d8bb379913e Mon Sep 17 00:00:00 2001 From: Gethin James Date: Thu, 2 Mar 2017 09:23:19 +0100 Subject: [PATCH] SEARCH-339: Moved the date parsing from Solr4QueryParser and added a test --- .../alfresco/util/SearchDateConversion.java | 177 ++++++++++++++++++ .../util/SearchDateConversionTest.java | 170 +++++++++++++++++ 2 files changed, 347 insertions(+) create mode 100644 src/main/java/org/alfresco/util/SearchDateConversion.java create mode 100644 src/test/java/org/alfresco/util/SearchDateConversionTest.java diff --git a/src/main/java/org/alfresco/util/SearchDateConversion.java b/src/main/java/org/alfresco/util/SearchDateConversion.java new file mode 100644 index 0000000000..1829827438 --- /dev/null +++ b/src/main/java/org/alfresco/util/SearchDateConversion.java @@ -0,0 +1,177 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import org.alfresco.service.cmr.search.IntervalSet; +import org.springframework.extensions.surf.util.I18NUtil; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +/** + * Moved from Solr4QueryParser + */ +public class SearchDateConversion +{ + + public static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("UTC"); + /** + * + * @param dateString + * @return Pair + */ + public static Pair parseDateString(String dateString) + { + try + { + Pair result = CachingDateFormat.lenientParse(dateString, Calendar.YEAR); + return result; + } catch (java.text.ParseException e) + { + SimpleDateFormat oldDf = CachingDateFormat.getDateFormat(); + try + { + Date date = oldDf.parse(dateString); + return new Pair(date, Calendar.SECOND); + } catch (java.text.ParseException ee) + { + if (dateString.equalsIgnoreCase("min")) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.set(Calendar.YEAR, cal.getMinimum(Calendar.YEAR)); + cal.set(Calendar.DAY_OF_YEAR, cal.getMinimum(Calendar.DAY_OF_YEAR)); + cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE)); + cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND)); + cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND)); + return new Pair(cal.getTime(), Calendar.MILLISECOND); + } else if (dateString.equalsIgnoreCase("now")) + { + return new Pair(new Date(), Calendar.MILLISECOND); + } else if (dateString.equalsIgnoreCase("today")) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.setTime(new Date()); + cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE)); + cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND)); + cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND)); + return new Pair(cal.getTime(), Calendar.DAY_OF_MONTH); + } else if (dateString.equalsIgnoreCase("max")) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.set(Calendar.YEAR, cal.getMaximum(Calendar.YEAR)); + cal.set(Calendar.DAY_OF_YEAR, cal.getMaximum(Calendar.DAY_OF_YEAR)); + cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY)); + cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE)); + cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND)); + cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND)); + return new Pair(cal.getTime(), Calendar.MILLISECOND); + } else + { + return null; // delegate to SOLR date parsing + } + } + } + } + + /** + * @param dateAndResolution + * @return String date + */ + public static String getDateEnd(Pair dateAndResolution) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.setTime(dateAndResolution.getFirst()); + switch (dateAndResolution.getSecond()) + { + case Calendar.YEAR: + cal.set(Calendar.MONTH, cal.getActualMaximum(Calendar.MONTH)); + case Calendar.MONTH: + cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); + case Calendar.DAY_OF_MONTH: + cal.set(Calendar.HOUR_OF_DAY, cal.getActualMaximum(Calendar.HOUR_OF_DAY)); + case Calendar.HOUR_OF_DAY: + cal.set(Calendar.MINUTE, cal.getActualMaximum(Calendar.MINUTE)); + case Calendar.MINUTE: + cal.set(Calendar.SECOND, cal.getActualMaximum(Calendar.SECOND)); + case Calendar.SECOND: + cal.set(Calendar.MILLISECOND, cal.getActualMaximum(Calendar.MILLISECOND)); + case Calendar.MILLISECOND: + default: + } + SimpleDateFormat formatter = CachingDateFormat.getSolrDatetimeFormat(); + formatter.setTimeZone(UTC_TIMEZONE); + return formatter.format(cal.getTime()); + } + + /** + * @param dateAndResolution + * @return String date + */ + public static String getDateStart(Pair dateAndResolution) + { + Calendar cal = Calendar.getInstance(I18NUtil.getLocale()); + cal.setTime(dateAndResolution.getFirst()); + switch (dateAndResolution.getSecond()) + { + case Calendar.YEAR: + cal.set(Calendar.MONTH, cal.getActualMinimum(Calendar.MONTH)); + case Calendar.MONTH: + cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH)); + case Calendar.DAY_OF_MONTH: + cal.set(Calendar.HOUR_OF_DAY, cal.getActualMinimum(Calendar.HOUR_OF_DAY)); + case Calendar.HOUR_OF_DAY: + cal.set(Calendar.MINUTE, cal.getActualMinimum(Calendar.MINUTE)); + case Calendar.MINUTE: + cal.set(Calendar.SECOND, cal.getActualMinimum(Calendar.SECOND)); + case Calendar.SECOND: + cal.set(Calendar.MILLISECOND, cal.getActualMinimum(Calendar.MILLISECOND)); + case Calendar.MILLISECOND: + default: + } + SimpleDateFormat formatter = CachingDateFormat.getSolrDatetimeFormat(); + formatter.setTimeZone(UTC_TIMEZONE); + return formatter.format(cal.getTime()); + } + + public static IntervalSet parseDateInterval(IntervalSet theSet, boolean isDate) + { + if (isDate) + { + Pair dateAndResolution1 = parseDateString(theSet.getStart()); + Pair dateAndResolution2 = parseDateString(theSet.getEnd()); + String start = dateAndResolution1 == null ? theSet.getStart() + : (theSet.isStartInclusive() ? getDateStart(dateAndResolution1) : getDateEnd(dateAndResolution1)); + String end = dateAndResolution2 == null ? theSet.getEnd() + : (theSet.isEndInclusive() ? getDateEnd(dateAndResolution2) : getDateStart(dateAndResolution2)); + return new IntervalSet(start, end, theSet.getLabel(), false, true); + } + return theSet; + } +} diff --git a/src/test/java/org/alfresco/util/SearchDateConversionTest.java b/src/test/java/org/alfresco/util/SearchDateConversionTest.java new file mode 100644 index 0000000000..246522381d --- /dev/null +++ b/src/test/java/org/alfresco/util/SearchDateConversionTest.java @@ -0,0 +1,170 @@ +/* + * #%L + * Alfresco Data model classes + * %% + * Copyright (C) 2005 - 2017 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ +package org.alfresco.util; + +import static org.junit.Assert.*; +import org.alfresco.service.cmr.search.IntervalSet; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.extensions.surf.util.I18NUtil; + +import java.io.UnsupportedEncodingException; +import java.util.Calendar; +import java.util.Date; +import java.util.Locale; + +/** + * Basic calls + */ +public class SearchDateConversionTest +{ + SearchDateConversion subject = new SearchDateConversion(); + + @Test + public void parseDateString() throws Exception + { + Pair result = subject.parseDateString("2017"); + assertEquals(Calendar.YEAR, result.getSecond().intValue()); + assertEquals(1483225200000l, result.getFirst().getTime()); + + result = subject.parseDateString("2017-12"); + assertEquals(Calendar.MONTH, result.getSecond().intValue()); + assertEquals(1512082800000l, result.getFirst().getTime()); + + result = subject.parseDateString("2017-12-12"); + assertEquals(Calendar.DAY_OF_MONTH, result.getSecond().intValue()); + assertEquals(1513033200000l, result.getFirst().getTime()); + + result = subject.parseDateString("NOW"); + assertEquals(Calendar.MILLISECOND, result.getSecond().intValue()); + + result = subject.parseDateString("MIN"); + assertEquals(Calendar.MILLISECOND, result.getSecond().intValue()); + + result = subject.parseDateString("TODAY"); + assertEquals(Calendar.DAY_OF_MONTH, result.getSecond().intValue()); + + result = subject.parseDateString("MAX"); + assertEquals(Calendar.MILLISECOND, result.getSecond().intValue()); + + result = subject.parseDateString("NONSENSE"); + assertNull(result); + + result = subject.parseDateString("NOW/YEAR"); + assertNull(result); + + result = subject.parseDateString("*"); + assertNull(result); + } + + @Test + public void getDateEnd() throws Exception + { + setLocale(Locale.UK); + Pair result = subject.parseDateString("2017-12"); + assertEquals("2017-12-31T22:59:59.999Z", subject.getDateEnd(result)); + + result = subject.parseDateString("2017-12-12"); + assertEquals("2017-12-12T22:59:59.999Z", subject.getDateEnd(result)); + + result = subject.parseDateString("2017"); + assertEquals("2017-12-31T22:59:59.999Z", subject.getDateEnd(result)); + } + + @Test + public void getDateStart() throws Exception + { + setLocale(Locale.UK); + Pair result = subject.parseDateString("2017-12"); + assertEquals("2017-11-30T23:00:00.000Z", subject.getDateStart(result)); + + result = subject.parseDateString("2017-12-12"); + assertEquals("2017-12-11T23:00:00.000Z", subject.getDateStart(result)); + + result = subject.parseDateString("2017"); + assertEquals("2016-12-31T23:00:00.000Z", subject.getDateStart(result)); + } + + @Test + public void testIntervalDates() throws UnsupportedEncodingException + { + setLocale(Locale.UK); + IntervalSet intervalSet = new IntervalSet("1", "10", "just numbers", false, true); + IntervalSet validated = subject.parseDateInterval(intervalSet, false); + assertEquals(intervalSet, validated); + + intervalSet = new IntervalSet("2006", "2010", "years", true, true); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2005-12-31T23:00:00.000Z", validated.getStart()); + assertFalse(validated.isStartInclusive()); + assertEquals("2010-12-31T22:59:59.999Z", validated.getEnd()); + assertTrue(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2006", "2010", "years", false, false); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2006-12-31T22:59:59.999Z", validated.getStart()); + assertFalse(validated.isStartInclusive()); + assertEquals("2009-12-31T23:00:00.000Z", validated.getEnd()); + assertTrue(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2006-09", "2010-03", "months", true, true); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2006-08-31T22:00:00.000Z", validated.getStart()); + assertFalse(validated.isStartInclusive()); + assertEquals("2010-03-31T21:59:59.999Z", validated.getEnd()); + assertTrue(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2006-09", "2010-03", "months", false, false); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2006-09-30T21:59:59.999Z", validated.getStart()); + assertFalse(validated.isStartInclusive()); + assertEquals("2010-02-28T23:00:00.000Z", validated.getEnd()); + assertTrue(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2017-09-01", "2017-09-30", "sept", true, true); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2017-08-31T22:00:00.000Z", validated.getStart()); + assertFalse(validated.isStartInclusive()); + assertEquals("2017-09-30T21:59:59.999Z", validated.getEnd()); + assertTrue(validated.isEndInclusive()); + + intervalSet = new IntervalSet("2017-08-31", "2017-10-01", "sept", false, false); + validated = subject.parseDateInterval(intervalSet, true); + assertEquals("2017-08-31T21:59:59.999Z", validated.getStart()); + assertFalse(validated.isStartInclusive()); + assertEquals("2017-09-30T22:00:00.000Z", validated.getEnd()); + assertTrue(validated.isEndInclusive()); + } + + + private void setLocale(Locale locale) + { + I18NUtil.setLocale(locale); + } + + +} \ No newline at end of file