From 2e9be1d6b36a7fcc40bef1f6778ee25e878ff6b6 Mon Sep 17 00:00:00 2001 From: Jeff Nelson Date: Sun, 10 Nov 2013 09:13:27 -0500 Subject: [PATCH 1/5] Added gradle support Change-Id: Ia5a04830b15ca0d57e746cd20723ee9a214ccbe6 --- build.gradle | 15 +++ gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 +++++++++++++++++++++++ gradlew.bat | 90 +++++++++++++ 4 files changed, 275 insertions(+) create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..9648b4a --- /dev/null +++ b/build.gradle @@ -0,0 +1,15 @@ +apply plugin: 'java' + +repositories { + mavenCentral() +} + +dependencies { + compile 'org.slf4j:slf4j-api:1.7.5' + compile 'ch.qos.logback:logback-classic:1.0.13' + compile 'joda-time:joda-time:2.2' + + testCompile 'junit:junit:4.11' +} + + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..cd90998 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Oct 06 07:30:41 CDT 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-1.8-bin.zip diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..91a7e26 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..aec9973 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 384d63074e24678d0b6b6088680517192ea566e7 Mon Sep 17 00:00:00 2001 From: Jeff Nelson Date: Sun, 10 Nov 2013 09:13:52 -0500 Subject: [PATCH 2/5] Added eclipse project files Change-Id: I96d2dff9864e0de538711176b12c61ffa8061b1a --- .classpath | 8 ++++++++ .project | 18 ++++++++++++++++++ ....springsource.ide.eclipse.gradle.core.prefs | 3 +++ 3 files changed, 29 insertions(+) create mode 100644 .classpath create mode 100644 .project create mode 100644 .settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..233109c --- /dev/null +++ b/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..829beab --- /dev/null +++ b/.project @@ -0,0 +1,18 @@ + + + stringtotime + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.springsource.ide.eclipse.gradle.core.nature + org.eclipse.jdt.core.javanature + + diff --git a/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs new file mode 100644 index 0000000..8b63538 --- /dev/null +++ b/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs @@ -0,0 +1,3 @@ +#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences +#Sun Nov 10 09:12:34 EST 2013 +org.springsource.ide.eclipse.gradle.rootprojectloc= From a22ea262c998fc2b4906fbbf52f6176d67798823 Mon Sep 17 00:00:00 2001 From: Jeff Nelson Date: Sun, 10 Nov 2013 09:49:02 -0500 Subject: [PATCH 3/5] deprecated old static factories and public constructors in favor of static factories that return joda or long timestamp Change-Id: I88908e2ef377dd16ce3a28677b7ded353856b2ff --- build.gradle | 1 + .../java/com/clutch/dates/DateEditor.java | 26 - .../java/com/clutch/dates/StringToTime.java | 1177 ++++++++++------- .../com/clutch/dates/StringToTimeTest.java | 32 - 4 files changed, 693 insertions(+), 543 deletions(-) delete mode 100644 src/main/java/com/clutch/dates/DateEditor.java diff --git a/build.gradle b/build.gradle index 9648b4a..171ce1a 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,7 @@ dependencies { compile 'org.slf4j:slf4j-api:1.7.5' compile 'ch.qos.logback:logback-classic:1.0.13' compile 'joda-time:joda-time:2.2' + compile 'com.google.guava:guava:15.0' testCompile 'junit:junit:4.11' } diff --git a/src/main/java/com/clutch/dates/DateEditor.java b/src/main/java/com/clutch/dates/DateEditor.java deleted file mode 100644 index d97b715..0000000 --- a/src/main/java/com/clutch/dates/DateEditor.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.clutch.dates; - -import java.beans.PropertyEditorSupport; -import java.util.Date; - -import org.springframework.beans.PropertyEditorRegistrar; -import org.springframework.beans.PropertyEditorRegistry; - -public class DateEditor extends PropertyEditorSupport implements PropertyEditorRegistrar { - - @Override - public void setAsText(String text) throws IllegalArgumentException { - Object date = StringToTime.date(text); - if (!Boolean.FALSE.equals(date)) - setValue((Date) date); - else - throw new IllegalArgumentException(String.format("[%s] is not a date.", text)); - } - -// @Override - public void registerCustomEditors(PropertyEditorRegistry registry) { - registry.registerCustomEditor(Date.class, new DateEditor()); - registry.registerCustomEditor(Date.class, new DateEditor()); - } - -} diff --git a/src/main/java/com/clutch/dates/StringToTime.java b/src/main/java/com/clutch/dates/StringToTime.java index 70bf99e..83e0ce7 100644 --- a/src/main/java/com/clutch/dates/StringToTime.java +++ b/src/main/java/com/clutch/dates/StringToTime.java @@ -9,50 +9,80 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Level; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; /** - * A Java implementation of the PHP function strtotime(String, int): accepts various expressions of time - * in String format, and instantiates a {@link java.util.Date} object. + * A Java implementation of the PHP function strtotime(String, int): accepts + * various expressions of time + * in String format, and instantiates a {@link java.util.Date} + * object. * *

- * There are two ways to use StringToTime to parse dates: + * There are two ways to use StringToTime to parse dates: *

    - *
  • static methods ({@link #time(Object)}, {@link #date(Object)}, {@link #cal(Object)})
  • - *
  • creating an instance of StringToTime with {@link #StringToTime(Object)}
  • + *
  • static methods ({@link #time(Object)}, {@link #date(Object)}, + * {@link #cal(Object)})
  • + *
  • creating an instance of StringToTime with + * {@link #StringToTime(Object)}
  • *
*

* - *

The static methods provide a UNIX-style timestamp, a {@link java.util.Date} instance, or a - * {@link java.util.Calendar} instance. In the event the time expression provided is invalid, - * these methods return Boolean.FALSE.

+ *

+ * The static methods provide a UNIX-style timestamp, a {@link java.util.Date} + * instance, or a {@link java.util.Calendar} instance. In the event the time + * expression provided is invalid, these methods return + * Boolean.FALSE. + *

* - *

Instances of StringToTime inherit from {@link java.util.Date}; so, when instantiated - * with an expression that the algorithm recognizes, the resulting instance of StringToTime - * can be passed to any method or caller requiring a {@link java.util.Date} object. Unlike the static methods, - * attempting to create a StringToTime instance with an invalid expression of time - * results in a {@link StringToTimeException}.

+ *

+ * Instances of StringToTime inherit from {@link java.util.Date}; + * so, when instantiated with an expression that the algorithm recognizes, the + * resulting instance of StringToTime can be passed to any method + * or caller requiring a {@link java.util.Date} object. Unlike the static + * methods, attempting to create a StringToTime instance with an + * invalid expression of time results in a {@link StringToTimeException}. + *

* *

Valid expressions of time

* - *

All expressions are case-insensitive.

+ *

+ * All expressions are case-insensitive. + *

* *
    *
  • now (equal to new Date())
  • *
  • today (equal to StringToTime("00:00:00.000"))
  • - *
  • midnight (equal to StringToTime("00:00:00.000 +24 hours"))
  • - *
  • morning or this morning (by default, equal toStringToTime("07:00:00.000"))
  • - *
  • noon (by default, equal to StringToTime("12:00:00.000")
  • - *
  • afternoon or this afternoon (by default, equal to StringToTime("13:00:00.000")
  • - *
  • evening or this evening (by default, equal to StringToTime("17:00:00.000")
  • - *
  • tonight (by default, equal to StringToTime("20:00:00.000")
  • - *
  • tomorrow (by default, equal to StringToTime("now +24 hours"))
  • - *
  • tomorrow morning (by default, equal to StringToTime("morning +24 hours"))
  • - *
  • noon tomorrow or tomorrow noon (by default, equal to StringToTime("noon +24 hours"))
  • - *
  • tomorrow afternoon (by default, equal to StringToTime("afternoon +24 hours"))
  • - *
  • yesterday (by default, equal to StringToTime("now -24 hours"))
  • - *
  • all the permutations of yesterday and morning, noon, afternoon, and evening
  • + *
  • midnight (equal to + * StringToTime("00:00:00.000 +24 hours"))
  • + *
  • morning or this morning (by default, equal to + * StringToTime("07:00:00.000"))
  • + *
  • noon (by default, equal to + * StringToTime("12:00:00.000")
  • + *
  • afternoon or this afternoon (by default, equal + * to StringToTime("13:00:00.000")
  • + *
  • evening or this evening (by default, equal to + * StringToTime("17:00:00.000")
  • + *
  • tonight (by default, equal to + * StringToTime("20:00:00.000")
  • + *
  • tomorrow (by default, equal to + * StringToTime("now +24 hours"))
  • + *
  • tomorrow morning (by default, equal to + * StringToTime("morning +24 hours"))
  • + *
  • noon tomorrow or tomorrow noon (by default, + * equal to StringToTime("noon +24 hours"))
  • + *
  • tomorrow afternoon (by default, equal to + * StringToTime("afternoon +24 hours"))
  • + *
  • yesterday (by default, equal to + * StringToTime("now -24 hours"))
  • + *
  • all the permutations of yesterday and morning, + * noon, afternoon, and evening
  • *
  • October 26, 1981 or Oct 26, 1981
  • *
  • October 26 or Oct 26
  • *
  • 26 October 1981
  • @@ -70,204 +100,369 @@ */ public class StringToTime extends Date { + /** + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated + public static Object cal(Object dateTimeString) { + return cal(dateTimeString, new Date()); + } + + /** + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated + public static Object cal(Object dateTimeString, Date now) { + Object date = date(dateTimeString, now); + if(Boolean.FALSE.equals(date)) + return Boolean.FALSE; + else { + Calendar cal = Calendar.getInstance(); + cal.setTime((Date) date); + return cal; + } + } + + /** + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated + public static Object date(Object dateTimeString) { + return date(dateTimeString, new Date()); + } + + /** + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated + public static Object date(Object dateTimeString, Date now) { + Object time = time(dateTimeString, now); + return (Boolean.FALSE.equals(time)) ? Boolean.FALSE : new Date( + (Long) time); + } + + /** + * Return a {@link DateTime} object that represents the instant expressed by + * {@code string}. + * + * @param string + * @return the DateTime instant + */ + public static DateTime parseDateTime(String string) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(string)); + return new DateTime(new StringToTime(string)); + } + + /** + * A single parameter version of {@link #time(String, Date)}, passing a new + * instance of {@link java.util.Date} as the + * second parameter. + * + * @param dateTimeString + * @return A {@link java.lang.Long} timestamp representative of + * dateTimeString, or {@link java.lang.Boolean} + * false. + * @see #time(String, Date) + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated + public static Object time(Object dateTimeString) { + return time(dateTimeString, new Date()); + } + + /** + * Parse dateTimeString and produce a timestamp. + * + * @param dateTimeString + * @param now + * @return
      + *
    • If equal to "now", return the number of + * milliseconds since January 1, 1970 or the value of + * now.
    • + *
    • If an incremental or decremental statement, e.g., +1 hour or + * -1 week, or a composite thereof, e.g., +1 hour 1 minute 1 second, + * returns a date equal to the increment/decrement plus the value of + * now. + *
    + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated + public static Object time(Object dateTimeString, Date now) { + try { + if(dateTimeString == null) + return Boolean.FALSE; + else { + String trimmed = String.valueOf(dateTimeString).trim(); + for (PatternAndFormat paf : known) { + Matcher m = paf.matches(trimmed); + if(m.matches()) { + Long time = paf.parse(trimmed, now, m); + // System.out.println(String.format("[%s] triggered format [%s]: %s", + // dateTimeString, paf.f, new Date(time))); + log.debug(String.format( + "[%s] triggered format [%s]: %s", + dateTimeString, paf.f, new Date(time))); + return time; + } + } + + // no match + + log.debug(String.format("Unrecognized date/time string [%s]", + dateTimeString)); + return Boolean.FALSE; + } + } + catch (Exception e) { // thrown by various features of the parser + if(!Boolean.parseBoolean(System.getProperty(StringToTime.class + + ".EXCEPTION_ON_PARSE_FAILURE", "false"))) { + log.debug(String.format( + "Failed to parse [%s] into a java.util.Date instance", + dateTimeString)); + return Boolean.FALSE; + } + else + throw new StringToTimeException(dateTimeString, e); + } + } + + /** + * Return a unix timestamp with millisecond precision that represents the + * instant expressed by {@code string}. + * + * @param string + * @return the long timestamp + */ + public static long parseTime(String string) { + return parseDateTime(string).getMillis(); + + } + + private static ParserResult getParserResult(String trimmedDateTimeString, + Date now) throws ParseException { + for (PatternAndFormat paf : known) { + Matcher m = paf.matches(trimmedDateTimeString); + if(m.matches()) { + log.debug(String.format( + "Date/time string [%s] triggered format [%s]", + trimmedDateTimeString, paf.f)); + return new ParserResult( + paf.parse(trimmedDateTimeString, now, m), paf.f.type); + } + } + + return null; + } + private static final long serialVersionUID = 7889493424407815134L; - private static final Log log = LogFactory.getLog(StringToTime.class); - + private static final Logger log = LoggerFactory + .getLogger(StringToTime.class); + static { + // Set to Level.DEBUG to see information about string parsing logic + ((ch.qos.logback.classic.Logger) log).setLevel(Level.INFO); + } + // default SimpleDateFormat string is the standard MySQL date format private static final String defaultSimpleDateFormat = "yyyy-MM-dd HH:mm:ss.SSS"; - - // An expression of time (hour)(:(minute))?((:(second))(.(millisecond))?)?( *(am?|pm?))?(RFC 822 time zone|general time zone)? + + // An expression of time (hour)(:(minute))?((:(second))(.(millisecond))?)?( + // *(am?|pm?))?(RFC 822 time zone|general time zone)? private static final String timeExpr = "(\\d{1,2})(:(\\d{1,2}))?(:(\\d{1,2})(\\.(\\d{1,3}))?)?( *(am?|pm?))?( *\\-\\d{4}|[a-z]{3}|[a-z ]+)?"; - - /** Patterns and formats recognized by the algorithm; first match wins, so insert most specific patterns first. */ + + /** + * Patterns and formats recognized by the algorithm; first match wins, so + * insert most specific patterns first. + */ private static final PatternAndFormat[] known = { - - // TODO: ISO 8601 and derivatives - - // just the year - new PatternAndFormat( - Pattern.compile("\\d{4}"), - new Format(FormatType.YEAR) - ), - - // decrement, e.g., -1 day - new PatternAndFormat( - Pattern.compile("\\-( *\\d{1,} +[^ ]+){1,}", Pattern.CASE_INSENSITIVE), - new Format(FormatType.DECREMENT) - ), - - // increment, e.g., +1 day - new PatternAndFormat( - Pattern.compile("\\+?( *\\d{1,} +[^ ]+){1,}", Pattern.CASE_INSENSITIVE), - new Format(FormatType.INCREMENT) - ), - - // e.g., October 26 and Oct 26 - new PatternAndFormat( - Pattern.compile("([a-z]+) +(\\d{1,2})", Pattern.CASE_INSENSITIVE), - new Format(FormatType.MONTH_AND_DATE) - ), - - // e.g., 26 October 1981, or 26 Oct 1981, or 26 Oct 81 - new PatternAndFormat( - Pattern.compile("\\d{1,2} +[a-z]+ +(\\d{2}|\\d{4})", Pattern.CASE_INSENSITIVE), - new Format("d MMM y") - ), - - // now or today - new PatternAndFormat( - Pattern.compile("(midnight|now|today|(this +)?(morning|afternoon|evening)|tonight|noon( +tomorrow)?|tomorrow|tomorrow +(morning|afternoon|evening|night|noon)?|yesterday|yesterday +(morning|afternoon|evening|night)?)", Pattern.CASE_INSENSITIVE), - new Format(FormatType.WORD) - ), - - // time, 24-hour and 12-hour - new PatternAndFormat( - Pattern.compile(timeExpr, Pattern.CASE_INSENSITIVE), - new Format(FormatType.TIME) - ), - - // e.g., October 26, 1981 or Oct 26, 1981 - new PatternAndFormat( - Pattern.compile("[a-z]+ +\\d{1,2} *, *(\\d{2}|\\d{4})", Pattern.CASE_INSENSITIVE), - new Format("MMM d, y") - ), - - // e.g., 10/26/1981 or 10/26/81 - new PatternAndFormat( - Pattern.compile("\\d{1,2}/\\d{1,2}/\\d{2,4}"), - new Format("M/d/y") - ), - - // e.g., 10-26-1981 or 10-26-81 - new PatternAndFormat( - Pattern.compile("\\d{1,2}\\-\\d{1,2}\\-\\d{2,4}"), - new Format("M-d-y") - ), - - // e.g., 10/26 or 10-26 - new PatternAndFormat( - Pattern.compile("(\\d{1,2})(/|\\-)(\\d{1,2})"), - new Format(FormatType.MONTH_AND_DATE_WITH_SLASHES) - ), - - // e.g., 1981/10/26 - new PatternAndFormat( - Pattern.compile("\\d{4}/\\d{1,2}/\\d{1,2}"), - new Format("y/M/d") - ), - - // e.g., 1981-10-26 - new PatternAndFormat( - Pattern.compile("\\d{4}\\-\\d{1,2}\\-\\d{1,2}"), - new Format("y-M-d") - ), - - // e.g., October or Oct - new PatternAndFormat( - Pattern.compile("(Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(ust)?|Sep(tember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?)", Pattern.CASE_INSENSITIVE), - new Format(FormatType.MONTH) - ), - - // e.g., Tuesday or Tue - new PatternAndFormat( - Pattern.compile("(Sun(day)?|Mon(day)?|Tue(sday)?|Wed(nesday)?|Thu(rsday)?|Fri(day)?|Sat(urday)?)", Pattern.CASE_INSENSITIVE), - new Format(FormatType.DAY_OF_WEEK) - ), - - // next, e.g., next Tuesday - new PatternAndFormat( - Pattern.compile("next +(.*)", Pattern.CASE_INSENSITIVE), - new Format(FormatType.NEXT) - ), - - // last, e.g., last Tuesday - new PatternAndFormat( - Pattern.compile("last +(.*)", Pattern.CASE_INSENSITIVE), - new Format(FormatType.LAST) - ), - - // compound statement - new PatternAndFormat( - Pattern.compile("(.*) +(((\\+|\\-){1}.*)|"+timeExpr+")$", Pattern.CASE_INSENSITIVE), - new Format(FormatType.COMPOUND) - ) - - + + // TODO: ISO 8601 and derivatives + + // just the year + new PatternAndFormat(Pattern.compile("\\d{4}"), new Format( + FormatType.YEAR)), + + // decrement, e.g., -1 day + new PatternAndFormat(Pattern.compile("\\-( *\\d{1,} +[^ ]+){1,}", + Pattern.CASE_INSENSITIVE), new Format(FormatType.DECREMENT)), + + // increment, e.g., +1 day + new PatternAndFormat(Pattern.compile("\\+?( *\\d{1,} +[^ ]+){1,}", + Pattern.CASE_INSENSITIVE), new Format(FormatType.INCREMENT)), + + // e.g., October 26 and Oct 26 + new PatternAndFormat(Pattern.compile("([a-z]+) +(\\d{1,2})", + Pattern.CASE_INSENSITIVE), new Format( + FormatType.MONTH_AND_DATE)), + + // e.g., 26 October 1981, or 26 Oct 1981, or 26 Oct 81 + new PatternAndFormat(Pattern.compile( + "\\d{1,2} +[a-z]+ +(\\d{2}|\\d{4})", + Pattern.CASE_INSENSITIVE), new Format("d MMM y")), + + // now or today + new PatternAndFormat( + Pattern.compile( + "(midnight|now|today|(this +)?(morning|afternoon|evening)|tonight|noon( +tomorrow)?|tomorrow|tomorrow +(morning|afternoon|evening|night|noon)?|yesterday|yesterday +(morning|afternoon|evening|night)?)", + Pattern.CASE_INSENSITIVE), new Format( + FormatType.WORD)), + + // time, 24-hour and 12-hour + new PatternAndFormat(Pattern.compile(timeExpr, + Pattern.CASE_INSENSITIVE), new Format(FormatType.TIME)), + + // e.g., October 26, 1981 or Oct 26, 1981 + new PatternAndFormat(Pattern.compile( + "[a-z]+ +\\d{1,2} *, *(\\d{2}|\\d{4})", + Pattern.CASE_INSENSITIVE), new Format("MMM d, y")), + + // e.g., 10/26/1981 or 10/26/81 + new PatternAndFormat(Pattern.compile("\\d{1,2}/\\d{1,2}/\\d{2,4}"), + new Format("M/d/y")), + + // e.g., 10-26-1981 or 10-26-81 + new PatternAndFormat( + Pattern.compile("\\d{1,2}\\-\\d{1,2}\\-\\d{2,4}"), + new Format("M-d-y")), + + // e.g., 10/26 or 10-26 + new PatternAndFormat( + Pattern.compile("(\\d{1,2})(/|\\-)(\\d{1,2})"), new Format( + FormatType.MONTH_AND_DATE_WITH_SLASHES)), + + // e.g., 1981/10/26 + new PatternAndFormat(Pattern.compile("\\d{4}/\\d{1,2}/\\d{1,2}"), + new Format("y/M/d")), + + // e.g., 1981-10-26 + new PatternAndFormat( + Pattern.compile("\\d{4}\\-\\d{1,2}\\-\\d{1,2}"), + new Format("y-M-d")), + + // e.g., October or Oct + new PatternAndFormat( + Pattern.compile( + "(Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(ust)?|Sep(tember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?)", + Pattern.CASE_INSENSITIVE), new Format( + FormatType.MONTH)), + + // e.g., Tuesday or Tue + new PatternAndFormat( + Pattern.compile( + "(Sun(day)?|Mon(day)?|Tue(sday)?|Wed(nesday)?|Thu(rsday)?|Fri(day)?|Sat(urday)?)", + Pattern.CASE_INSENSITIVE), new Format( + FormatType.DAY_OF_WEEK)), + + // next, e.g., next Tuesday + new PatternAndFormat(Pattern.compile("next +(.*)", + Pattern.CASE_INSENSITIVE), new Format(FormatType.NEXT)), + + // last, e.g., last Tuesday + new PatternAndFormat(Pattern.compile("last +(.*)", + Pattern.CASE_INSENSITIVE), new Format(FormatType.LAST)), + + // compound statement + new PatternAndFormat(Pattern.compile("(.*) +(((\\+|\\-){1}.*)|" + + timeExpr + ")$", Pattern.CASE_INSENSITIVE), new Format( + FormatType.COMPOUND)) + }; - - /** Date/Time string parsed */ - private Object dateTimeString; - + /** The format to use in {@link #toString()) */ private String simpleDateFormat; - - /** The {@link java.util.Date} interpreted from {@link #dateTimeString}, or {@link java.lang.Boolean} false */ + + /** + * The {@link java.util.Date} interpreted from {@link #dateTimeString}, or + * {@link java.lang.Boolean} false + */ private Object date; - - + + /** + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated public StringToTime() { super(); this.date = new Date(this.getTime()); } - + + /** + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated public StringToTime(Date date) { super(date.getTime()); this.date = new Date(this.getTime()); } - + + /** + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated public StringToTime(Object dateTimeString) { this(dateTimeString, new Date(), defaultSimpleDateFormat); } - - public StringToTime(Object dateTimeString, String simpleDateFormat) { - this(dateTimeString, new Date(), simpleDateFormat); - } - + + /** + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated public StringToTime(Object dateTimeString, Date now) { this(dateTimeString, now, defaultSimpleDateFormat); } - - public StringToTime(Object dateTimeString, Long now) { - this(dateTimeString, new Date(now), defaultSimpleDateFormat); - } - - public StringToTime(Object dateTimeString, Integer now) { - this(dateTimeString, new Date(new Long(now)), defaultSimpleDateFormat); - } - + + /** + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. + */ + @Deprecated public StringToTime(Object dateTimeString, Date now, String simpleDateFormat) { super(0); assert dateTimeString != null; - assert now != null; - assert simpleDateFormat != null; - - this.dateTimeString = dateTimeString; + assert now != null; + assert simpleDateFormat != null; + this.simpleDateFormat = simpleDateFormat; - + date = StringToTime.date(dateTimeString, now); - if (!Boolean.FALSE.equals(date)) + if(!Boolean.FALSE.equals(date)) setTime(((Date) date).getTime()); else throw new StringToTimeException(dateTimeString); } - + /** - * @return {@link java.util.Date#getTime()} + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. */ - public long getTime() { - return super.getTime(); + @Deprecated + public StringToTime(Object dateTimeString, Integer now) { + this(dateTimeString, new Date(new Long(now)), defaultSimpleDateFormat); } - + /** - * @return Calendar set to timestamp {@link java.util.Date#getTime()} + * @deprecated use {@link StringToTime#parseTime(String)} or + * {@link StringToTime#parseDateTime(String)} instead. */ - public Calendar getCal() { - Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(super.getTime()); - return cal; + @Deprecated + public StringToTime(Object dateTimeString, Long now) { + this(dateTimeString, new Date(now), defaultSimpleDateFormat); + } + + public StringToTime(Object dateTimeString, String simpleDateFormat) { + this(dateTimeString, new Date(), simpleDateFormat); } - + /** * @param simpleDateFormat * @see {@link SimpleDateFormat} @@ -276,145 +471,45 @@ public Calendar getCal() { public String format(String simpleDateFormat) { return new SimpleDateFormat(simpleDateFormat).format(this); } - + /** - * @return If {@link #simpleDateFormat} provided in constructor, then attempts to format date - * accordingly; otherwise, returns the String value of {@link java.util.Date#getTime()}. + * @return Calendar set to timestamp {@link java.util.Date#getTime()} */ - public String toString() { - if (simpleDateFormat != null) - return new SimpleDateFormat(simpleDateFormat).format(this); - else - return new SimpleDateFormat("yyyy/dd/MM").format(this); //String.valueOf(super.getTime()); + public Calendar getCal() { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(super.getTime()); + return cal; } - - + /** - * A single parameter version of {@link #time(String, Date)}, passing a new instance of {@link java.util.Date} as the - * second parameter. - * @param dateTimeString - * @return A {@link java.lang.Long} timestamp representative of dateTimeString, or {@link java.lang.Boolean} false. - * @see #time(String, Date) + * @return {@link java.util.Date#getTime()} */ - public static Object time(Object dateTimeString) { - return time(dateTimeString, new Date()); + public long getTime() { + return super.getTime(); } - + /** - * Parse dateTimeString and produce a timestamp. - * @param dateTimeString - * @param now - * @return
      - *
    • If equal to "now", return the number of milliseconds since January 1, 1970 or the value of now.
    • - *
    • If an incremental or decremental statement, e.g., +1 hour or -1 week, or a composite thereof, e.g., +1 hour 1 minute 1 second, - * returns a date equal to the increment/decrement plus the value of now. - *
    + * @return If {@link #simpleDateFormat} provided in constructor, then + * attempts to format date accordingly; otherwise, + * returns the String value of + * {@link java.util.Date#getTime()}. */ - public static Object time(Object dateTimeString, Date now) { - try { - if (dateTimeString == null) - return Boolean.FALSE; - else { - String trimmed = String.valueOf(dateTimeString).trim(); - for(PatternAndFormat paf : known) { - Matcher m = paf.matches(trimmed); - if (m.matches()) { - Long time = paf.parse(trimmed, now, m); - //System.out.println(String.format("[%s] triggered format [%s]: %s", dateTimeString, paf.f, new Date(time))); - if (log.isDebugEnabled()) - log.debug(String.format("[%s] triggered format [%s]: %s", dateTimeString, paf.f, new Date(time))); - return time; - } - } - - // no match - if (log.isDebugEnabled()) - log.debug(String.format("Unrecognized date/time string [%s]", dateTimeString)); - return Boolean.FALSE; - } - } catch (Exception e) { // thrown by various features of the parser - if (!Boolean.parseBoolean(System.getProperty(StringToTime.class+".EXCEPTION_ON_PARSE_FAILURE", "false"))) { - if (log.isDebugEnabled()) - log.debug(String.format("Failed to parse [%s] into a java.util.Date instance", dateTimeString)); - return Boolean.FALSE; - } - else - throw new StringToTimeException(dateTimeString, e); - } - } - - private static ParserResult getParserResult(String trimmedDateTimeString, Date now) throws ParseException { - for(PatternAndFormat paf : known) { - Matcher m = paf.matches(trimmedDateTimeString); - if (m.matches()) { - log.debug(String.format("Date/time string [%s] triggered format [%s]", trimmedDateTimeString, paf.f)); - return new ParserResult(paf.parse(trimmedDateTimeString, now, m), paf.f.type); - } - } - - return null; - } - - public static Object date(Object dateTimeString) { - return date(dateTimeString, new Date()); - } - - public static Object date(Object dateTimeString, Date now) { - Object time = time(dateTimeString, now); - return (Boolean.FALSE.equals(time)) ? Boolean.FALSE : new Date((Long) time); - } - - public static Object cal(Object dateTimeString) { - return cal(dateTimeString, new Date()); - } - - public static Object cal(Object dateTimeString, Date now) { - Object date = date(dateTimeString, now); - if (Boolean.FALSE.equals(date)) - return Boolean.FALSE; - else { - Calendar cal = Calendar.getInstance(); - cal.setTime((Date) date); - return cal; - } - } - - private static class PatternAndFormat { - public Pattern p; - public Format f; - - public PatternAndFormat(Pattern p, Format f) { - this.p = p; - this.f = f; - } - - public Matcher matches(String dateTimeString) { - return p.matcher(dateTimeString); - } - - public Long parse(String dateTimeString, Date now, Matcher m) throws ParseException { - return f.parse(dateTimeString, now, m).getTime(); - } - } - - private static class ParserResult { - public FormatType type; - public Long timestamp; - - public ParserResult(Long timestamp, FormatType type) { - this.timestamp = timestamp; - this.type = type; - } + public String toString() { + if(simpleDateFormat != null) + return new SimpleDateFormat(simpleDateFormat).format(this); + else + return new SimpleDateFormat("yyyy/dd/MM").format(this); // String.valueOf(super.getTime()); } - + private static class Format { - - private static Pattern unit = Pattern.compile("(\\d{1,}) +(s(ec(ond)?)?|mo(n(th)?)?|(hour|hr?)|d(ay)?|(w(eek)?|wk)|m(in(ute)?)?|(y(ear)?|yr))s?"); - + + private static Pattern unit = Pattern + .compile("(\\d{1,}) +(s(ec(ond)?)?|mo(n(th)?)?|(hour|hr?)|d(ay)?|(w(eek)?|wk)|m(in(ute)?)?|(y(ear)?|yr))s?"); + private static Pattern removeExtraSpaces = Pattern.compile(" +"); - + private static Map translateDayOfWeek = new HashMap(); - + static { translateDayOfWeek.put("sunday", 1); translateDayOfWeek.put("sun", 1); @@ -431,60 +526,58 @@ private static class Format { translateDayOfWeek.put("saturday", 7); translateDayOfWeek.put("sat", 7); } - + private String sdf; - + private FormatType type; - + public Format(FormatType type) { this.type = type; } - + public Format(String sdf) { this.sdf = sdf; } - - public String toString() { - if (sdf != null) - return sdf; - else - return type.toString(); - } - - public Date parse(String dateTimeString, Date now, Matcher m) throws ParseException { - if (sdf != null) + + public Date parse(String dateTimeString, Date now, Matcher m) + throws ParseException { + if(sdf != null) return new SimpleDateFormat(sdf).parse(dateTimeString); else { - dateTimeString = removeExtraSpaces.matcher(dateTimeString).replaceAll(" ").toLowerCase(); - + dateTimeString = removeExtraSpaces.matcher(dateTimeString) + .replaceAll(" ").toLowerCase(); + try { Calendar cal = Calendar.getInstance(); cal.setTime(now); - + // word expressions, e.g., "now" and "today" and "tonight" - if (type == FormatType.WORD) { - if ("now".equals(dateTimeString)) + if(type == FormatType.WORD) { + if("now".equals(dateTimeString)) return (now != null ? now : new Date()); - - else if ("today".equals(dateTimeString)) { + + else if("today".equals(dateTimeString)) { cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return new Date(cal.getTimeInMillis()); } - - else if ("morning".equals(dateTimeString) || "this morning".equals(dateTimeString)) { + + else if("morning".equals(dateTimeString) + || "this morning".equals(dateTimeString)) { // by default, this morning begins at 07:00:00.000 - int thisMorningBeginsAt = Integer.parseInt(System.getProperty(StringToTime.class+".THIS_MORNING_BEGINS_AT", "7")); + int thisMorningBeginsAt = Integer.parseInt(System + .getProperty(StringToTime.class + + ".THIS_MORNING_BEGINS_AT", "7")); cal.set(Calendar.HOUR_OF_DAY, thisMorningBeginsAt); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return new Date(cal.getTimeInMillis()); } - - else if ("noon".equals(dateTimeString)) { + + else if("noon".equals(dateTimeString)) { // noon is 12:00:00.000 cal.set(Calendar.HOUR_OF_DAY, 12); cal.set(Calendar.MINUTE, 0); @@ -492,284 +585,369 @@ else if ("noon".equals(dateTimeString)) { cal.set(Calendar.MILLISECOND, 0); return new Date(cal.getTimeInMillis()); } - - else if ("afternoon".equals(dateTimeString) || "this afternoon".equals(dateTimeString)) { + + else if("afternoon".equals(dateTimeString) + || "this afternoon".equals(dateTimeString)) { // by default, this afternoon begins at 13:00:00.000 - int thisAfternoonBeginsAt = Integer.parseInt(System.getProperty(StringToTime.class+".THIS_AFTERNOON_BEGINS_AT", "13")); + int thisAfternoonBeginsAt = Integer + .parseInt(System + .getProperty( + StringToTime.class + + ".THIS_AFTERNOON_BEGINS_AT", + "13")); cal.set(Calendar.HOUR_OF_DAY, thisAfternoonBeginsAt); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return new Date(cal.getTimeInMillis()); } - - else if ("evening".equals(dateTimeString) || "this evening".equals(dateTimeString)) { + + else if("evening".equals(dateTimeString) + || "this evening".equals(dateTimeString)) { // by default, this evening begins at 17:00:00.000 - int thisEveningBeginsAt = Integer.parseInt(System.getProperty(StringToTime.class+".THIS_EVENING_BEGINS_AT", "17")); + int thisEveningBeginsAt = Integer.parseInt(System + .getProperty(StringToTime.class + + ".THIS_EVENING_BEGINS_AT", "17")); cal.set(Calendar.HOUR_OF_DAY, thisEveningBeginsAt); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return new Date(cal.getTimeInMillis()); } - - else if ("tonight".equals(dateTimeString)) { + + else if("tonight".equals(dateTimeString)) { // by default, tonight begins at 20:00:00.000 - int tonightBeginsAt = Integer.parseInt(System.getProperty(StringToTime.class+".TONIGHT_BEGINS_AT", "20")); + int tonightBeginsAt = Integer.parseInt(System + .getProperty(StringToTime.class + + ".TONIGHT_BEGINS_AT", "20")); cal.set(Calendar.HOUR_OF_DAY, tonightBeginsAt); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return new Date(cal.getTimeInMillis()); } - - else if ("midnight".equals(dateTimeString)) { + + else if("midnight".equals(dateTimeString)) { return new StringToTime("00:00:00 +24 hours", now); } - - else if ("tomorrow".equals(dateTimeString)) { + + else if("tomorrow".equals(dateTimeString)) { return new StringToTime("now +24 hours", now); } - - else if ("tomorrow morning".equals(dateTimeString)) { + + else if("tomorrow morning".equals(dateTimeString)) { return new StringToTime("morning +24 hours", now); } - - else if ("tomorrow noon".equals(dateTimeString) || "noon tomorrow".equals(dateTimeString)) { + + else if("tomorrow noon".equals(dateTimeString) + || "noon tomorrow".equals(dateTimeString)) { return new StringToTime("noon +24 hours", now); } - - else if ("tomorrow afternoon".equals(dateTimeString)) { + + else if("tomorrow afternoon".equals(dateTimeString)) { return new StringToTime("afternoon +24 hours", now); } - - else if ("tomorrow evening".equals(dateTimeString)) { + + else if("tomorrow evening".equals(dateTimeString)) { return new StringToTime("evening +24 hours", now); } - - else if ("tomorrow night".equals(dateTimeString)) { + + else if("tomorrow night".equals(dateTimeString)) { return new StringToTime("tonight +24 hours", now); } - - else if ("yesterday".equals(dateTimeString)) { + + else if("yesterday".equals(dateTimeString)) { return new StringToTime("now -24 hours", now); } - - else if ("yesterday morning".equals(dateTimeString)) { + + else if("yesterday morning".equals(dateTimeString)) { return new StringToTime("morning -24 hours", now); } - - else if ("yesterday noon".equals(dateTimeString) || "noon yesterday".equals(dateTimeString)) { + + else if("yesterday noon".equals(dateTimeString) + || "noon yesterday".equals(dateTimeString)) { return new StringToTime("noon -24 hours", now); } - - else if ("yesterday afternoon".equals(dateTimeString)) { + + else if("yesterday afternoon".equals(dateTimeString)) { return new StringToTime("afternoon -24 hours", now); } - - else if ("yesterday evening".equals(dateTimeString)) { + + else if("yesterday evening".equals(dateTimeString)) { return new StringToTime("evening -24 hours", now); } - - else if ("yesterday night".equals(dateTimeString)) { + + else if("yesterday night".equals(dateTimeString)) { return new StringToTime("tonight -24 hours", now); } - - + else - throw new ParseException(String.format("Unrecognized date word: %s", dateTimeString), 0); + throw new ParseException(String.format( + "Unrecognized date word: %s", + dateTimeString), 0); } - + // time expressions, 24-hour and 12-hour - else if (type == FormatType.TIME) { - // An expression of time (hour)(:(minute))?((:(second))(.(millisecond))?)?( *(am?|pm?))?(RFC 822 time zone|general time zone)? + else if(type == FormatType.TIME) { + // An expression of time + // (hour)(:(minute))?((:(second))(.(millisecond))?)?( + // *(am?|pm?))?(RFC 822 time zone|general time zone)? String hour = m.group(1); String min = m.group(3); String sec = m.group(5); String ms = m.group(7); String amOrPm = m.group(8); - - if (hour != null) { - if (amOrPm != null) + + if(hour != null) { + if(amOrPm != null) cal.set(Calendar.HOUR, new Integer(hour)); else cal.set(Calendar.HOUR_OF_DAY, new Integer(hour)); } else cal.set(Calendar.HOUR, 0); - - cal.set(Calendar.MINUTE, (min != null ? new Integer(min) : 0)); - cal.set(Calendar.SECOND, (sec != null ? new Integer(sec) : 0)); - cal.set(Calendar.MILLISECOND, (ms != null ? new Integer(ms) : 0)); - - if (amOrPm != null) - cal.set(Calendar.AM_PM, (amOrPm.equals("a") || amOrPm.equals("am") ? Calendar.AM : Calendar.PM)); - - + + cal.set(Calendar.MINUTE, + (min != null ? new Integer(min) : 0)); + cal.set(Calendar.SECOND, + (sec != null ? new Integer(sec) : 0)); + cal.set(Calendar.MILLISECOND, + (ms != null ? new Integer(ms) : 0)); + + if(amOrPm != null) + cal.set(Calendar.AM_PM, (amOrPm.equals("a") + || amOrPm.equals("am") ? Calendar.AM + : Calendar.PM)); + return new Date(cal.getTimeInMillis()); } - + // increments - else if (type == FormatType.INCREMENT || type == FormatType.DECREMENT) { + else if(type == FormatType.INCREMENT + || type == FormatType.DECREMENT) { Matcher units = unit.matcher(dateTimeString); while (units.find()) { - Integer val = new Integer(units.group(1)) * (type == FormatType.DECREMENT ? -1 : 1); + Integer val = new Integer(units.group(1)) + * (type == FormatType.DECREMENT ? -1 : 1); String u = units.group(2); - + // second - if ("s".equals(u) || "sec".equals(u) || "second".equals(u)) - cal.set(Calendar.SECOND, cal.get(Calendar.SECOND)+val); - + if("s".equals(u) || "sec".equals(u) + || "second".equals(u)) + cal.set(Calendar.SECOND, + cal.get(Calendar.SECOND) + val); + // minute - else if ("m".equals(u) || "min".equals(u) || "minute".equals(u)) - cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE)+val); - + else if("m".equals(u) || "min".equals(u) + || "minute".equals(u)) + cal.set(Calendar.MINUTE, + cal.get(Calendar.MINUTE) + val); + // hour - else if ("h".equals(u) || "hr".equals(u) || "hour".equals(u)) - cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY)+val); - + else if("h".equals(u) || "hr".equals(u) + || "hour".equals(u)) + cal.set(Calendar.HOUR_OF_DAY, + cal.get(Calendar.HOUR_OF_DAY) + val); + // day - else if ("d".equals(u) || "day".equals(u)) - cal.set(Calendar.DATE, cal.get(Calendar.DATE)+val); - + else if("d".equals(u) || "day".equals(u)) + cal.set(Calendar.DATE, cal.get(Calendar.DATE) + + val); + // week - else if ("w".equals(u) || "wk".equals(u) || "week".equals(u)) - cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR)+val); - + else if("w".equals(u) || "wk".equals(u) + || "week".equals(u)) + cal.set(Calendar.WEEK_OF_YEAR, + cal.get(Calendar.WEEK_OF_YEAR) + val); + // month - else if ("mo".equals(u) || "mon".equals(u) || "month".equals(u)) - cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)+val); - + else if("mo".equals(u) || "mon".equals(u) + || "month".equals(u)) + cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + + val); + // year - else if ("y".equals(u) || "yr".equals(u) || "year".equals(u)) - cal.set(Calendar.YEAR, cal.get(Calendar.YEAR)+val); - + else if("y".equals(u) || "yr".equals(u) + || "year".equals(u)) + cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + + val); + else - throw new IllegalArgumentException(String.format("Unrecognized %s unit: [%s]", type, u)); + throw new IllegalArgumentException( + String.format( + "Unrecognized %s unit: [%s]", + type, u)); } - + return new Date(cal.getTimeInMillis()); } - + // compound expressions - else if (type == FormatType.COMPOUND) { + else if(type == FormatType.COMPOUND) { Object date = StringToTime.date(m.group(1), now); - if (!Boolean.FALSE.equals(date)) - return (Date) StringToTime.date(m.group(2), (Date) date); + if(!Boolean.FALSE.equals(date)) + return (Date) StringToTime.date(m.group(2), + (Date) date); else - throw new IllegalArgumentException(String.format("Couldn't parse %s, so couldn't compound with %s", m.group(1), m.group(2))); + throw new IllegalArgumentException( + String.format( + "Couldn't parse %s, so couldn't compound with %s", + m.group(1), m.group(2))); } - + // month of the year - else if (type == FormatType.MONTH) { + else if(type == FormatType.MONTH) { Calendar ref = Calendar.getInstance(); - ref.setTime(new SimpleDateFormat("MMM d, y").parse(String.format("%s 1, 1970", m.group(1)))); + ref.setTime(new SimpleDateFormat("MMM d, y") + .parse(String.format("%s 1, 1970", m.group(1)))); cal.set(Calendar.MONTH, ref.get(Calendar.MONTH)); - + return new Date(cal.getTimeInMillis()); } - + // day of week - else if (type == FormatType.DAY_OF_WEEK) { + else if(type == FormatType.DAY_OF_WEEK) { Integer ref = translateDayOfWeek.get(dateTimeString); - if (cal.get(Calendar.DAY_OF_WEEK) >= ref) - cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR)+1); + if(cal.get(Calendar.DAY_OF_WEEK) >= ref) + cal.set(Calendar.WEEK_OF_YEAR, + cal.get(Calendar.WEEK_OF_YEAR) + 1); cal.set(Calendar.DAY_OF_WEEK, ref); - + return new Date(cal.getTimeInMillis()); } - + // month and day with slashes - else if (type == FormatType.MONTH_AND_DATE_WITH_SLASHES) { + else if(type == FormatType.MONTH_AND_DATE_WITH_SLASHES) { Calendar ref = Calendar.getInstance(); - ref.setTime(new SimpleDateFormat("M/d/y").parse(String.format("%s/%s/1970", m.group(1), m.group(3)))); + ref.setTime(new SimpleDateFormat("M/d/y").parse(String + .format("%s/%s/1970", m.group(1), m.group(3)))); cal.set(Calendar.MONTH, ref.get(Calendar.MONTH)); cal.set(Calendar.DATE, ref.get(Calendar.DATE)); - + return new Date(cal.getTimeInMillis()); } - + // month and day long-hand - else if (type == FormatType.MONTH_AND_DATE) { + else if(type == FormatType.MONTH_AND_DATE) { Calendar ref = Calendar.getInstance(); - ref.setTime(new SimpleDateFormat("MMM d, y").parse(String.format("%s %s, 1970", m.group(1), m.group(2)))); + ref.setTime(new SimpleDateFormat("MMM d, y") + .parse(String.format("%s %s, 1970", m.group(1), + m.group(2)))); cal.set(Calendar.MONTH, ref.get(Calendar.MONTH)); cal.set(Calendar.DATE, ref.get(Calendar.DATE)); - + return new Date(cal.getTimeInMillis()); } - + // next X - else if (type == FormatType.NEXT) { - // Format types MONTH and DAY_OF_WEEK both return future dates, so no additional processing is needed + else if(type == FormatType.NEXT) { + // Format types MONTH and DAY_OF_WEEK both return future + // dates, so no additional processing is needed String expr = m.group(1); - ParserResult parsed = StringToTime.getParserResult(expr, now); - - if (parsed != null && ( FormatType.MONTH.equals(parsed.type) || FormatType.DAY_OF_WEEK.equals(parsed.type) || FormatType.MONTH_AND_DATE.equals(parsed.type)) ) + ParserResult parsed = StringToTime.getParserResult( + expr, now); + + if(parsed != null + && (FormatType.MONTH.equals(parsed.type) + || FormatType.DAY_OF_WEEK + .equals(parsed.type) || FormatType.MONTH_AND_DATE + .equals(parsed.type))) return new Date(parsed.timestamp); else { - if ("week".equals(expr)) - cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR)+1); - else if ("month".equals(expr)) - cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)+1); - else if ("year".equals(expr)) - cal.set(Calendar.YEAR, cal.get(Calendar.YEAR)+1); + if("week".equals(expr)) + cal.set(Calendar.WEEK_OF_YEAR, + cal.get(Calendar.WEEK_OF_YEAR) + 1); + else if("month".equals(expr)) + cal.set(Calendar.MONTH, + cal.get(Calendar.MONTH) + 1); + else if("year".equals(expr)) + cal.set(Calendar.YEAR, + cal.get(Calendar.YEAR) + 1); else - throw new IllegalArgumentException(String.format("Invalid expression of time: %s", dateTimeString)); - + throw new IllegalArgumentException( + String.format( + "Invalid expression of time: %s", + dateTimeString)); + return new Date(cal.getTimeInMillis()); } } - + // last X - else if (type == FormatType.LAST) { + else if(type == FormatType.LAST) { String expr = m.group(1); - ParserResult parsed = StringToTime.getParserResult(expr, now); - - if (parsed != null && (FormatType.MONTH.equals(parsed.type) || FormatType.MONTH_AND_DATE.equals(parsed.type))) { - return new StringToTime("-1 year", new Date(parsed.timestamp)); + ParserResult parsed = StringToTime.getParserResult( + expr, now); + + if(parsed != null + && (FormatType.MONTH.equals(parsed.type) || FormatType.MONTH_AND_DATE + .equals(parsed.type))) { + return new StringToTime("-1 year", new Date( + parsed.timestamp)); } - - else if (parsed != null && FormatType.DAY_OF_WEEK.equals(parsed.type)) { - return new StringToTime("-1 week", new Date(parsed.timestamp)); + + else if(parsed != null + && FormatType.DAY_OF_WEEK.equals(parsed.type)) { + return new StringToTime("-1 week", new Date( + parsed.timestamp)); } - + else { - if ("week".equals(expr)) - cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR)-1); - else if ("month".equals(expr)) - cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)-1); - else if ("year".equals(expr)) - cal.set(Calendar.YEAR, cal.get(Calendar.YEAR)-1); + if("week".equals(expr)) + cal.set(Calendar.WEEK_OF_YEAR, + cal.get(Calendar.WEEK_OF_YEAR) - 1); + else if("month".equals(expr)) + cal.set(Calendar.MONTH, + cal.get(Calendar.MONTH) - 1); + else if("year".equals(expr)) + cal.set(Calendar.YEAR, + cal.get(Calendar.YEAR) - 1); else - throw new IllegalArgumentException(String.format("Invalid expression of time: %s", dateTimeString)); - + throw new IllegalArgumentException( + String.format( + "Invalid expression of time: %s", + dateTimeString)); + return new Date(cal.getTimeInMillis()); } } - + // year - else if (type == FormatType.YEAR) { + else if(type == FormatType.YEAR) { cal.set(Calendar.YEAR, new Integer(m.group(0))); return new Date(cal.getTimeInMillis()); } - + // unimplemented format type else - throw new IllegalStateException(String.format("Unimplemented FormatType: %s", type)); - } catch (ParseException e) { + throw new IllegalStateException(String.format( + "Unimplemented FormatType: %s", type)); + } + catch (ParseException e) { throw e; - } catch (IllegalStateException e) { + } + catch (IllegalStateException e) { throw e; - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { throw e; - } catch (Exception e) { - throw new RuntimeException(String.format("Unknown failure in string-to-time conversion: %s", e.getMessage()), e); + } + catch (Exception e) { + throw new RuntimeException(String.format( + "Unknown failure in string-to-time conversion: %s", + e.getMessage()), e); } } } + + public String toString() { + if(sdf != null) + return sdf; + else + return type.toString(); + } } - + private enum FormatType { COMPOUND, MONTH_AND_DATE_WITH_SLASHES, @@ -784,5 +962,34 @@ private enum FormatType { TIME, YEAR } - + + private static class ParserResult { + public FormatType type; + public Long timestamp; + + public ParserResult(Long timestamp, FormatType type) { + this.timestamp = timestamp; + this.type = type; + } + } + + private static class PatternAndFormat { + public Pattern p; + public Format f; + + public PatternAndFormat(Pattern p, Format f) { + this.p = p; + this.f = f; + } + + public Matcher matches(String dateTimeString) { + return p.matcher(dateTimeString); + } + + public Long parse(String dateTimeString, Date now, Matcher m) + throws ParseException { + return f.parse(dateTimeString, now, m).getTime(); + } + } + } diff --git a/src/test/java/com/clutch/dates/StringToTimeTest.java b/src/test/java/com/clutch/dates/StringToTimeTest.java index c42e2f1..27f99b1 100644 --- a/src/test/java/com/clutch/dates/StringToTimeTest.java +++ b/src/test/java/com/clutch/dates/StringToTimeTest.java @@ -7,9 +7,6 @@ import junit.framework.TestCase; -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; - public class StringToTimeTest extends TestCase { public void testMySqlDateFormat() { @@ -119,35 +116,6 @@ public void testStaticMethods() { Date date = (Date) StringToTime.date("now", now); assertEquals(new Date(now.getTime()), date); } - - public void testInstancePattern() { - StringToTime date = new StringToTime("26 October 1981"); - BeanWrapper bean = new BeanWrapperImpl(date); - Calendar cal = new GregorianCalendar(1981, Calendar.OCTOBER, 26); - Long myBirthday = cal.getTimeInMillis(); - - // string value of the StringToTime object is the timestamp - assertEquals(myBirthday, new Long(date.getTime())); - - // formatting controlled by constructor - date = new StringToTime("26 October 1981", "d MMM yyyy"); - assertEquals("26 Oct 1981", date.toString()); - date = new StringToTime("26 October 1981", "M/d/yy"); - assertEquals("10/26/81", date.toString()); - - // time property - assertEquals(myBirthday, bean.getPropertyValue("time")); - - // date property - Date now = new Date(myBirthday); - assertEquals(now, date); - - // calendar property - assertEquals(cal, bean.getPropertyValue("cal")); - - // format on demand - assertEquals("October 26, 1981", date.format("MMMM d, yyyy")); - } public void testNow() { Date now = new Date(); From fac12d72dbc1ec91d2e577d1f27ca1432636d48a Mon Sep 17 00:00:00 2001 From: Jeff Nelson Date: Sun, 10 Nov 2013 11:37:09 -0500 Subject: [PATCH 4/5] Turn StringToTime into a static utility class There is really no need for StringToTime to be used as an object instance, especially since java Date is inferior to Joda DateTime. Therefore, I've altered the class to preserve the parsing logic that the original author wrote, but to function as a static util class and either return a timestamp or a joda DateTime object. This greatly simplifies the class. Right now, the parsing still uses java Date under the hood, but that may be changed in a future commit Change-Id: Ice0dc3287117b0017dfea7c6b18b4850f048cdf1 --- .../java/com/clutch/dates/StringToTime.java | 476 +++++------------- 1 file changed, 126 insertions(+), 350 deletions(-) diff --git a/src/main/java/com/clutch/dates/StringToTime.java b/src/main/java/com/clutch/dates/StringToTime.java index 83e0ce7..b861b45 100644 --- a/src/main/java/com/clutch/dates/StringToTime.java +++ b/src/main/java/com/clutch/dates/StringToTime.java @@ -17,39 +17,14 @@ import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.google.common.base.Throwables; /** * A Java implementation of the PHP function strtotime(String, int): accepts * various expressions of time - * in String format, and instantiates a {@link java.util.Date} + * in String format, and returns a timestamp or {@link DateTime} * object. * - *

    - * There are two ways to use StringToTime to parse dates: - *

      - *
    • static methods ({@link #time(Object)}, {@link #date(Object)}, - * {@link #cal(Object)})
    • - *
    • creating an instance of StringToTime with - * {@link #StringToTime(Object)}
    • - *
    - *

    - * - *

    - * The static methods provide a UNIX-style timestamp, a {@link java.util.Date} - * instance, or a {@link java.util.Calendar} instance. In the event the time - * expression provided is invalid, these methods return - * Boolean.FALSE. - *

    - * - *

    - * Instances of StringToTime inherit from {@link java.util.Date}; - * so, when instantiated with an expression that the algorithm recognizes, the - * resulting instance of StringToTime can be passed to any method - * or caller requiring a {@link java.util.Date} object. Unlike the static - * methods, attempting to create a StringToTime instance with an - * invalid expression of time results in a {@link StringToTimeException}. - *

    - * *

    Valid expressions of time

    * *

    @@ -98,152 +73,65 @@ * @since JRE 1.5.0 * @see http://us3.php.net/manual/en/function.strtotime.php */ -public class StringToTime extends Date { +public class StringToTime { /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public static Object cal(Object dateTimeString) { - return cal(dateTimeString, new Date()); - } - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public static Object cal(Object dateTimeString, Date now) { - Object date = date(dateTimeString, now); - if(Boolean.FALSE.equals(date)) - return Boolean.FALSE; - else { - Calendar cal = Calendar.getInstance(); - cal.setTime((Date) date); - return cal; - } - } - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public static Object date(Object dateTimeString) { - return date(dateTimeString, new Date()); - } - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public static Object date(Object dateTimeString, Date now) { - Object time = time(dateTimeString, now); - return (Boolean.FALSE.equals(time)) ? Boolean.FALSE : new Date( - (Long) time); - } - - /** - * Return a {@link DateTime} object that represents the instant expressed by - * {@code string}. + * Parse {@code string} and return a {@link DateTime} object. * * @param string - * @return the DateTime instant + * @return the corresponding DateTime */ public static DateTime parseDateTime(String string) { - Preconditions.checkArgument(!Strings.isNullOrEmpty(string)); - return new DateTime(new StringToTime(string)); + return new DateTime(parseLong(string)); } /** - * A single parameter version of {@link #time(String, Date)}, passing a new - * instance of {@link java.util.Date} as the - * second parameter. + * Parse {@code string} and return a timestamp with millisecond precision. * - * @param dateTimeString - * @return A {@link java.lang.Long} timestamp representative of - * dateTimeString, or {@link java.lang.Boolean} - * false. - * @see #time(String, Date) - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. + * @param string + * @return the corresponding timestamp */ - @Deprecated - public static Object time(Object dateTimeString) { - return time(dateTimeString, new Date()); + public static long parseLong(String string) { + return parseLong(string, new Date()); } /** - * Parse dateTimeString and produce a timestamp. + * Parse {@code string} relative to {@code now} and return a timestamp with + * millisecond precision. * - * @param dateTimeString + * @param string * @param now - * @return

      - *
    • If equal to "now", return the number of - * milliseconds since January 1, 1970 or the value of - * now.
    • - *
    • If an incremental or decremental statement, e.g., +1 hour or - * -1 week, or a composite thereof, e.g., +1 hour 1 minute 1 second, - * returns a date equal to the increment/decrement plus the value of - * now. - *
    - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. + * @return the corresponding timestamp */ - @Deprecated - public static Object time(Object dateTimeString, Date now) { + private static long parseLong(String string, Date now) { + Preconditions.checkArgument(!Strings.isNullOrEmpty(string)); try { - if(dateTimeString == null) - return Boolean.FALSE; - else { - String trimmed = String.valueOf(dateTimeString).trim(); - for (PatternAndFormat paf : known) { - Matcher m = paf.matches(trimmed); - if(m.matches()) { - Long time = paf.parse(trimmed, now, m); - // System.out.println(String.format("[%s] triggered format [%s]: %s", - // dateTimeString, paf.f, new Date(time))); - log.debug(String.format( - "[%s] triggered format [%s]: %s", - dateTimeString, paf.f, new Date(time))); - return time; - } + for (PatternAndFormat paf : known) { + Matcher m = paf.matches(string); + if(m.matches()) { + Long time = paf.parse(string, now, m); + log.debug(String.format("{} triggered format {}: {}", + string, paf.f, new Date(time))); + return time; } - - // no match - - log.debug(String.format("Unrecognized date/time string [%s]", - dateTimeString)); - return Boolean.FALSE; } + log.debug(String.format("Unrecognized date/time string {}", string)); + throw new ParseException("Unrecognized date/time string '" + string + + "'", 0); } catch (Exception e) { // thrown by various features of the parser - if(!Boolean.parseBoolean(System.getProperty(StringToTime.class - + ".EXCEPTION_ON_PARSE_FAILURE", "false"))) { - log.debug(String.format( - "Failed to parse [%s] into a java.util.Date instance", - dateTimeString)); - return Boolean.FALSE; - } - else - throw new StringToTimeException(dateTimeString, e); + throw Throwables.propagate(e); } } /** - * Return a unix timestamp with millisecond precision that represents the - * instant expressed by {@code string}. + * Return the parse result. * - * @param string - * @return the long timestamp + * @param trimmedDateTimeString + * @param now + * @return + * @throws ParseException */ - public static long parseTime(String string) { - return parseDateTime(string).getMillis(); - - } - private static ParserResult getParserResult(String trimmedDateTimeString, Date now) throws ParseException { for (PatternAndFormat paf : known) { @@ -260,8 +148,6 @@ private static ParserResult getParserResult(String trimmedDateTimeString, return null; } - private static final long serialVersionUID = 7889493424407815134L; - private static final Logger log = LoggerFactory .getLogger(StringToTime.class); static { @@ -269,9 +155,6 @@ private static ParserResult getParserResult(String trimmedDateTimeString, ((ch.qos.logback.classic.Logger) log).setLevel(Level.INFO); } - // default SimpleDateFormat string is the standard MySQL date format - private static final String defaultSimpleDateFormat = "yyyy-MM-dd HH:mm:ss.SSS"; - // An expression of time (hour)(:(minute))?((:(second))(.(millisecond))?)?( // *(am?|pm?))?(RFC 822 time zone|general time zone)? private static final String timeExpr = "(\\d{1,2})(:(\\d{1,2}))?(:(\\d{1,2})(\\.(\\d{1,3}))?)?( *(am?|pm?))?( *\\-\\d{4}|[a-z]{3}|[a-z ]+)?"; @@ -374,133 +257,6 @@ private static ParserResult getParserResult(String trimmedDateTimeString, }; - /** The format to use in {@link #toString()) */ - private String simpleDateFormat; - - /** - * The {@link java.util.Date} interpreted from {@link #dateTimeString}, or - * {@link java.lang.Boolean} false - */ - private Object date; - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public StringToTime() { - super(); - this.date = new Date(this.getTime()); - } - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public StringToTime(Date date) { - super(date.getTime()); - this.date = new Date(this.getTime()); - } - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public StringToTime(Object dateTimeString) { - this(dateTimeString, new Date(), defaultSimpleDateFormat); - } - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public StringToTime(Object dateTimeString, Date now) { - this(dateTimeString, now, defaultSimpleDateFormat); - } - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public StringToTime(Object dateTimeString, Date now, String simpleDateFormat) { - super(0); - assert dateTimeString != null; - assert now != null; - assert simpleDateFormat != null; - - this.simpleDateFormat = simpleDateFormat; - - date = StringToTime.date(dateTimeString, now); - if(!Boolean.FALSE.equals(date)) - setTime(((Date) date).getTime()); - else - throw new StringToTimeException(dateTimeString); - } - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public StringToTime(Object dateTimeString, Integer now) { - this(dateTimeString, new Date(new Long(now)), defaultSimpleDateFormat); - } - - /** - * @deprecated use {@link StringToTime#parseTime(String)} or - * {@link StringToTime#parseDateTime(String)} instead. - */ - @Deprecated - public StringToTime(Object dateTimeString, Long now) { - this(dateTimeString, new Date(now), defaultSimpleDateFormat); - } - - public StringToTime(Object dateTimeString, String simpleDateFormat) { - this(dateTimeString, new Date(), simpleDateFormat); - } - - /** - * @param simpleDateFormat - * @see {@link SimpleDateFormat} - * @return Date formatted according to simpleDateFormat - */ - public String format(String simpleDateFormat) { - return new SimpleDateFormat(simpleDateFormat).format(this); - } - - /** - * @return Calendar set to timestamp {@link java.util.Date#getTime()} - */ - public Calendar getCal() { - Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(super.getTime()); - return cal; - } - - /** - * @return {@link java.util.Date#getTime()} - */ - public long getTime() { - return super.getTime(); - } - - /** - * @return If {@link #simpleDateFormat} provided in constructor, then - * attempts to format date accordingly; otherwise, - * returns the String value of - * {@link java.util.Date#getTime()}. - */ - public String toString() { - if(simpleDateFormat != null) - return new SimpleDateFormat(simpleDateFormat).format(this); - else - return new SimpleDateFormat("yyyy/dd/MM").format(this); // String.valueOf(super.getTime()); - } - private static class Format { private static Pattern unit = Pattern @@ -553,10 +309,10 @@ public Date parse(String dateTimeString, Date now, Matcher m) // word expressions, e.g., "now" and "today" and "tonight" if(type == FormatType.WORD) { - if("now".equals(dateTimeString)) + if("now".equalsIgnoreCase(dateTimeString)) return (now != null ? now : new Date()); - else if("today".equals(dateTimeString)) { + else if("today".equalsIgnoreCase(dateTimeString)) { cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); @@ -564,8 +320,9 @@ else if("today".equals(dateTimeString)) { return new Date(cal.getTimeInMillis()); } - else if("morning".equals(dateTimeString) - || "this morning".equals(dateTimeString)) { + else if("morning".equalsIgnoreCase(dateTimeString) + || "this morning" + .equalsIgnoreCase(dateTimeString)) { // by default, this morning begins at 07:00:00.000 int thisMorningBeginsAt = Integer.parseInt(System .getProperty(StringToTime.class @@ -577,7 +334,7 @@ else if("morning".equals(dateTimeString) return new Date(cal.getTimeInMillis()); } - else if("noon".equals(dateTimeString)) { + else if("noon".equalsIgnoreCase(dateTimeString)) { // noon is 12:00:00.000 cal.set(Calendar.HOUR_OF_DAY, 12); cal.set(Calendar.MINUTE, 0); @@ -586,8 +343,9 @@ else if("noon".equals(dateTimeString)) { return new Date(cal.getTimeInMillis()); } - else if("afternoon".equals(dateTimeString) - || "this afternoon".equals(dateTimeString)) { + else if("afternoon".equalsIgnoreCase(dateTimeString) + || "this afternoon" + .equalsIgnoreCase(dateTimeString)) { // by default, this afternoon begins at 13:00:00.000 int thisAfternoonBeginsAt = Integer .parseInt(System @@ -602,8 +360,9 @@ else if("afternoon".equals(dateTimeString) return new Date(cal.getTimeInMillis()); } - else if("evening".equals(dateTimeString) - || "this evening".equals(dateTimeString)) { + else if("evening".equalsIgnoreCase(dateTimeString) + || "this evening" + .equalsIgnoreCase(dateTimeString)) { // by default, this evening begins at 17:00:00.000 int thisEveningBeginsAt = Integer.parseInt(System .getProperty(StringToTime.class @@ -615,7 +374,7 @@ else if("evening".equals(dateTimeString) return new Date(cal.getTimeInMillis()); } - else if("tonight".equals(dateTimeString)) { + else if("tonight".equalsIgnoreCase(dateTimeString)) { // by default, tonight begins at 20:00:00.000 int tonightBeginsAt = Integer.parseInt(System .getProperty(StringToTime.class @@ -627,58 +386,73 @@ else if("tonight".equals(dateTimeString)) { return new Date(cal.getTimeInMillis()); } - else if("midnight".equals(dateTimeString)) { - return new StringToTime("00:00:00 +24 hours", now); + else if("midnight".equalsIgnoreCase(dateTimeString)) { + return new Date( + parseLong("00:00:00 +24 hours", now)); } - else if("tomorrow".equals(dateTimeString)) { - return new StringToTime("now +24 hours", now); + else if("tomorrow".equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("now +24 hours", now)); } - else if("tomorrow morning".equals(dateTimeString)) { - return new StringToTime("morning +24 hours", now); + else if("tomorrow morning" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("morning +24 hours", now)); } - else if("tomorrow noon".equals(dateTimeString) - || "noon tomorrow".equals(dateTimeString)) { - return new StringToTime("noon +24 hours", now); + else if("tomorrow noon" + .equalsIgnoreCase(dateTimeString) + || "noon tomorrow" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("noon +24 hours", now)); } - else if("tomorrow afternoon".equals(dateTimeString)) { - return new StringToTime("afternoon +24 hours", now); + else if("tomorrow afternoon" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("afternoon +24 hours", + now)); } - else if("tomorrow evening".equals(dateTimeString)) { - return new StringToTime("evening +24 hours", now); + else if("tomorrow evening" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("evening +24 hours", now)); } - else if("tomorrow night".equals(dateTimeString)) { - return new StringToTime("tonight +24 hours", now); + else if("tomorrow night" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("tonight +24 hours", now)); } - else if("yesterday".equals(dateTimeString)) { - return new StringToTime("now -24 hours", now); + else if("yesterday".equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("now -24 hours", now)); } - else if("yesterday morning".equals(dateTimeString)) { - return new StringToTime("morning -24 hours", now); + else if("yesterday morning" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("morning -24 hours", now)); } - else if("yesterday noon".equals(dateTimeString) - || "noon yesterday".equals(dateTimeString)) { - return new StringToTime("noon -24 hours", now); + else if("yesterday noon" + .equalsIgnoreCase(dateTimeString) + || "noon yesterday" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("noon -24 hours", now)); } - else if("yesterday afternoon".equals(dateTimeString)) { - return new StringToTime("afternoon -24 hours", now); + else if("yesterday afternoon" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("afternoon -24 hours", + now)); } - else if("yesterday evening".equals(dateTimeString)) { - return new StringToTime("evening -24 hours", now); + else if("yesterday evening" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("evening -24 hours", now)); } - else if("yesterday night".equals(dateTimeString)) { - return new StringToTime("tonight -24 hours", now); + else if("yesterday night" + .equalsIgnoreCase(dateTimeString)) { + return new Date(parseLong("tonight -24 hours", now)); } else @@ -715,9 +489,10 @@ else if(type == FormatType.TIME) { (ms != null ? new Integer(ms) : 0)); if(amOrPm != null) - cal.set(Calendar.AM_PM, (amOrPm.equals("a") - || amOrPm.equals("am") ? Calendar.AM - : Calendar.PM)); + cal.set(Calendar.AM_PM, + (amOrPm.equalsIgnoreCase("a") + || amOrPm.equalsIgnoreCase("am") ? Calendar.AM + : Calendar.PM)); return new Date(cal.getTimeInMillis()); } @@ -732,43 +507,50 @@ else if(type == FormatType.INCREMENT String u = units.group(2); // second - if("s".equals(u) || "sec".equals(u) - || "second".equals(u)) + if("s".equalsIgnoreCase(u) + || "sec".equalsIgnoreCase(u) + || "second".equalsIgnoreCase(u)) cal.set(Calendar.SECOND, cal.get(Calendar.SECOND) + val); // minute - else if("m".equals(u) || "min".equals(u) - || "minute".equals(u)) + else if("m".equalsIgnoreCase(u) + || "min".equalsIgnoreCase(u) + || "minute".equalsIgnoreCase(u)) cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE) + val); // hour - else if("h".equals(u) || "hr".equals(u) - || "hour".equals(u)) + else if("h".equalsIgnoreCase(u) + || "hr".equalsIgnoreCase(u) + || "hour".equalsIgnoreCase(u)) cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) + val); // day - else if("d".equals(u) || "day".equals(u)) + else if("d".equalsIgnoreCase(u) + || "day".equalsIgnoreCase(u)) cal.set(Calendar.DATE, cal.get(Calendar.DATE) + val); // week - else if("w".equals(u) || "wk".equals(u) - || "week".equals(u)) + else if("w".equalsIgnoreCase(u) + || "wk".equalsIgnoreCase(u) + || "week".equalsIgnoreCase(u)) cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR) + val); // month - else if("mo".equals(u) || "mon".equals(u) - || "month".equals(u)) + else if("mo".equalsIgnoreCase(u) + || "mon".equalsIgnoreCase(u) + || "month".equalsIgnoreCase(u)) cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + val); // year - else if("y".equals(u) || "yr".equals(u) - || "year".equals(u)) + else if("y".equalsIgnoreCase(u) + || "yr".equalsIgnoreCase(u) + || "year".equalsIgnoreCase(u)) cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + val); @@ -784,15 +566,8 @@ else if("y".equals(u) || "yr".equals(u) // compound expressions else if(type == FormatType.COMPOUND) { - Object date = StringToTime.date(m.group(1), now); - if(!Boolean.FALSE.equals(date)) - return (Date) StringToTime.date(m.group(2), - (Date) date); - else - throw new IllegalArgumentException( - String.format( - "Couldn't parse %s, so couldn't compound with %s", - m.group(1), m.group(2))); + return new Date(parseLong(m.group(2), new Date( + parseLong(m.group(1), now)))); } // month of the year @@ -854,13 +629,13 @@ else if(type == FormatType.NEXT) { .equals(parsed.type))) return new Date(parsed.timestamp); else { - if("week".equals(expr)) + if("week".equalsIgnoreCase(expr)) cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR) + 1); - else if("month".equals(expr)) + else if("month".equalsIgnoreCase(expr)) cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1); - else if("year".equals(expr)) + else if("year".equalsIgnoreCase(expr)) cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 1); else @@ -882,24 +657,24 @@ else if(type == FormatType.LAST) { if(parsed != null && (FormatType.MONTH.equals(parsed.type) || FormatType.MONTH_AND_DATE .equals(parsed.type))) { - return new StringToTime("-1 year", new Date( - parsed.timestamp)); + return new Date(parseLong("-1 year", new Date( + parsed.timestamp))); } else if(parsed != null && FormatType.DAY_OF_WEEK.equals(parsed.type)) { - return new StringToTime("-1 week", new Date( - parsed.timestamp)); + return new Date(parseLong("-1 week", new Date( + parsed.timestamp))); } else { - if("week".equals(expr)) + if("week".equalsIgnoreCase(expr)) cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR) - 1); - else if("month".equals(expr)) + else if("month".equalsIgnoreCase(expr)) cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) - 1); - else if("year".equals(expr)) + else if("year".equalsIgnoreCase(expr)) cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1); else @@ -940,6 +715,7 @@ else if(type == FormatType.YEAR) { } } + @Override public String toString() { if(sdf != null) return sdf; From 1feafc2b528642df66b9c482ed8dda4926e69f31 Mon Sep 17 00:00:00 2001 From: Jeff Nelson Date: Sun, 10 Nov 2013 12:02:51 -0500 Subject: [PATCH 5/5] remove unused exception class and cleanup tests Change-Id: Ie8def9f5b20b32df33c5447308784d2232c8a180 --- .../java/com/clutch/dates/StringToTime.java | 6 +- .../clutch/dates/StringToTimeException.java | 15 - .../com/clutch/dates/StringToTimeTest.java | 465 +++++++++++------- 3 files changed, 296 insertions(+), 190 deletions(-) delete mode 100644 src/main/java/com/clutch/dates/StringToTimeException.java diff --git a/src/main/java/com/clutch/dates/StringToTime.java b/src/main/java/com/clutch/dates/StringToTime.java index b861b45..0f1d818 100644 --- a/src/main/java/com/clutch/dates/StringToTime.java +++ b/src/main/java/com/clutch/dates/StringToTime.java @@ -94,6 +94,10 @@ public static DateTime parseDateTime(String string) { public static long parseLong(String string) { return parseLong(string, new Date()); } + + protected static DateTime parseDateTime(String string, Date now){ + return new DateTime(parseLong(string, now)); + } /** * Parse {@code string} relative to {@code now} and return a timestamp with @@ -103,7 +107,7 @@ public static long parseLong(String string) { * @param now * @return the corresponding timestamp */ - private static long parseLong(String string, Date now) { + protected static long parseLong(String string, Date now) { Preconditions.checkArgument(!Strings.isNullOrEmpty(string)); try { for (PatternAndFormat paf : known) { diff --git a/src/main/java/com/clutch/dates/StringToTimeException.java b/src/main/java/com/clutch/dates/StringToTimeException.java deleted file mode 100644 index 9b20c66..0000000 --- a/src/main/java/com/clutch/dates/StringToTimeException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.clutch.dates; - -public class StringToTimeException extends RuntimeException { - - private static final long serialVersionUID = -3777846121104246071L; - - public StringToTimeException(Object dateTimeString) { - super(String.format("Failed to parse [%s] into a java.util.Date", dateTimeString)); - } - - public StringToTimeException(Object dateTimeString, Throwable cause) { - super(String.format("Failed to parse [%s] into a java.util.Date", dateTimeString), cause); - } - -} diff --git a/src/test/java/com/clutch/dates/StringToTimeTest.java b/src/test/java/com/clutch/dates/StringToTimeTest.java index 27f99b1..e98182f 100644 --- a/src/test/java/com/clutch/dates/StringToTimeTest.java +++ b/src/test/java/com/clutch/dates/StringToTimeTest.java @@ -3,17 +3,15 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; -import java.util.GregorianCalendar; -import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; -public class StringToTimeTest extends TestCase { +public class StringToTimeTest { + @Test public void testMySqlDateFormat() { - Date now = new Date(); Calendar cal = Calendar.getInstance(); - cal.setTime(now); - cal.set(Calendar.MONTH, Calendar.OCTOBER); cal.set(Calendar.DATE, 26); cal.set(Calendar.YEAR, 1981); @@ -21,57 +19,70 @@ public void testMySqlDateFormat() { cal.set(Calendar.MINUTE, 26); cal.set(Calendar.SECOND, 3); cal.set(Calendar.MILLISECOND, 435); - - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("1981-10-26 15:26:03.435", now)); - } - - /* FIXME - public void testISO8601() { - Date now = new Date(); - Calendar cal = Calendar.getInstance(); - cal.setTime(now); - - cal.set(Calendar.MONTH, Calendar.OCTOBER); - cal.set(Calendar.DATE, 26); - cal.set(Calendar.YEAR, 1981); - cal.set(Calendar.HOUR_OF_DAY, 15); - cal.set(Calendar.MINUTE, 25); - cal.set(Calendar.SECOND, 2); - cal.set(Calendar.MILLISECOND, 435); - - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("1981-10-26T15:26:03.435ZEST", now)); + + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("1981-10-26 15:26:03.435").toDate()); } - */ - + + /* + * FIXME + * + * @Test public void testISO8601() { + * Date now = new Date(); + * Calendar cal = Calendar.getInstance(); + * cal.setTime(now); + * + * cal.set(Calendar.MONTH, Calendar.OCTOBER); + * cal.set(Calendar.DATE, 26); + * cal.set(Calendar.YEAR, 1981); + * cal.set(Calendar.HOUR_OF_DAY, 15); + * cal.set(Calendar.MINUTE, 25); + * cal.set(Calendar.SECOND, 2); + * cal.set(Calendar.MILLISECOND, 435); + * + * Assert.assertEquals(new Date(cal.getTimeInMillis()), new + * StringToTime("1981-10-26T15:26:03.435ZEST", now).toDate()); + * } + */ + + @Test public void test1200Seconds() { Date now = new Date(); Calendar cal = Calendar.getInstance(); cal.setTime(now); - - cal.set(Calendar.SECOND, cal.get(Calendar.SECOND)+1200); - assertTrue(new Date(cal.getTimeInMillis()).equals(new StringToTime("+1200 s", now))); - assertFalse(new Date(cal.getTimeInMillis()).equals(new StringToTime("+1 s", now))); + + cal.set(Calendar.SECOND, cal.get(Calendar.SECOND) + 1200); + Assert.assertTrue(new Date(cal.getTimeInMillis()).equals(StringToTime + .parseDateTime("+1200 s", now).toDate())); + Assert.assertFalse(new Date(cal.getTimeInMillis()).equals(StringToTime + .parseDateTime("+1 s", now).toDate())); } - + + @Test public void testVariousExpressionsOfTimeOfDay() { Date now = new Date(); Calendar cal = Calendar.getInstance(); cal.setTime(now); - + cal.set(Calendar.HOUR_OF_DAY, 23); cal.set(Calendar.MINUTE, 59); cal.set(Calendar.SECOND, 59); cal.set(Calendar.MILLISECOND, 0); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("11:59:59 PM", now)); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("23:59:59", now)); - + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("11:59:59 PM", now).toDate()); + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("23:59:59", now).toDate()); + cal.set(Calendar.SECOND, 0); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("23:59", now)); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("11:59 PM", now)); - + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("23:59", now).toDate()); + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("11:59 PM", now).toDate()); + cal.set(Calendar.MILLISECOND, 123); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("23:59:00.123")); - + Assert.assertEquals(new Date(cal.getTimeInMillis()), + StringToTime.parseDateTime("23:59:00.123")); + cal.set(Calendar.MONTH, Calendar.OCTOBER); cal.set(Calendar.DATE, 26); cal.set(Calendar.YEAR, 1981); @@ -79,240 +90,346 @@ public void testVariousExpressionsOfTimeOfDay() { cal.set(Calendar.MINUTE, 27); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("October 26, 1981 3:27:00 PM", now)); - + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("October 26, 1981 3:27:00 PM", now).toDate()); + cal.set(Calendar.HOUR, 5); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.AM_PM, Calendar.PM); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("10/26/81 5PM", now)); - + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("10/26/81 5PM", now).toDate()); + cal.setTime(now); - cal.set(Calendar.DATE, cal.get(Calendar.DATE)+1); + cal.set(Calendar.DATE, cal.get(Calendar.DATE) + 1); cal.set(Calendar.HOUR, 5); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.AM_PM, Calendar.PM); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("tomorrow 5PM", now)); - - cal.set(Calendar.DATE, cal.get(Calendar.DATE)-2); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("yesterday 5PM", now)); - assertEquals(new StringToTime("yesterday evening", now), new StringToTime("yesterday 5PM", now)); - } - - public void testStaticMethods() { - Date now = new Date(); - - // timestamp - Long time = (Long) StringToTime.time("now", now); - assertEquals(new Date(now.getTime()), new Date(time)); - - // calendar - Calendar cal = (Calendar) StringToTime.cal("now", now); - assertEquals(new Date(now.getTime()), new Date(cal.getTimeInMillis())); - - // date - Date date = (Date) StringToTime.date("now", now); - assertEquals(new Date(now.getTime()), date); + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("tomorrow 5PM", now).toDate()); + + cal.set(Calendar.DATE, cal.get(Calendar.DATE) - 2); + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("yesterday 5PM", now).toDate()); + Assert.assertEquals(StringToTime + .parseDateTime("yesterday evening", now).toDate(), StringToTime + .parseDateTime("yesterday 5PM", now).toDate()); } - + + @Test public void testNow() { Date now = new Date(); - assertEquals(new Date(now.getTime()), new StringToTime("now", now)); + Assert.assertEquals(new Date(now.getTime()), StringToTime + .parseDateTime("now", now).toDate()); } - + + @Test public void testToday() { Date now = new Date(); - assertEquals(new StringToTime("00:00:00.000", now), new StringToTime("today", now)); + Assert.assertEquals(StringToTime.parseDateTime("00:00:00.000", now) + .toDate(), StringToTime.parseDateTime("today", now).toDate()); } - + + @Test public void testThisMorning() { Date now = new Date(); - assertEquals(new StringToTime("07:00:00.000", now), new StringToTime("this morning", now)); - assertEquals(new StringToTime("morning", now), new StringToTime("this morning", now)); + Assert.assertEquals(StringToTime.parseDateTime("07:00:00.000", now) + .toDate(), StringToTime.parseDateTime("this morning", now) + .toDate()); + Assert.assertEquals( + StringToTime.parseDateTime("morning", now).toDate(), + StringToTime.parseDateTime("this morning", now).toDate()); } - + + @Test public void testNoon() { Date now = new Date(); - assertEquals(new StringToTime("12:00:00.000", now), new StringToTime("noon", now)); + Assert.assertEquals(StringToTime.parseDateTime("12:00:00.000", now) + .toDate(), StringToTime.parseDateTime("noon", now).toDate()); } - + + @Test public void testThisAfternoon() { Date now = new Date(); - assertEquals(new StringToTime("13:00:00.000", now), new StringToTime("this afternoon", now)); - assertEquals(new StringToTime("afternoon", now), new StringToTime("this afternoon", now)); + Assert.assertEquals(StringToTime.parseDateTime("13:00:00.000", now) + .toDate(), StringToTime.parseDateTime("this afternoon", now) + .toDate()); + Assert.assertEquals(StringToTime.parseDateTime("afternoon", now) + .toDate(), StringToTime.parseDateTime("this afternoon", now) + .toDate()); } - + + @Test public void testThisEvening() { Date now = new Date(); - assertEquals(new StringToTime("17:00:00.000", now), new StringToTime("this evening", now)); - assertEquals(new StringToTime("evening", now), new StringToTime("this evening", now)); + Assert.assertEquals(StringToTime.parseDateTime("17:00:00.000", now) + .toDate(), StringToTime.parseDateTime("this evening", now) + .toDate()); + Assert.assertEquals( + StringToTime.parseDateTime("evening", now).toDate(), + StringToTime.parseDateTime("this evening", now).toDate()); } - + + @Test public void testTonight() { Date now = new Date(); - assertEquals(StringToTime.time("20:00:00.000", now), StringToTime.time("tonight", now)); + Assert.assertEquals(StringToTime.parseDateTime("20:00:00.000", now) + .toDate(), StringToTime.parseDateTime("tonight", now).toDate()); } - + + @Test public void testIncrements() { Date now = new Date(); - + Calendar cal = Calendar.getInstance(); cal.setTime(now); - cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY)+1); - assertEquals(cal.getTimeInMillis(), StringToTime.time("+1 hour", now)); - + cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) + 1); + Assert.assertEquals(cal.getTimeInMillis(), + StringToTime.parseDateTime("+1 hour", now).toDate()); + cal.setTime(now); - cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR)+52); - assertEquals(cal.getTimeInMillis(), StringToTime.time("+52 weeks", now)); - - assertEquals(new StringToTime("1 year", now), new StringToTime("+1 year", now)); - - assertEquals(new StringToTime("+1 year", now), new StringToTime("+12 months", now)); - - assertEquals(new StringToTime("+1 year 6 months", now), new StringToTime("+18 months", now)); - - assertEquals(new StringToTime("12 months 1 day 60 seconds", now), new StringToTime("1 year 24 hours 1 minute", now)); + cal.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR) + 52); + Assert.assertEquals(cal.getTimeInMillis(), + StringToTime.parseDateTime("+52 weeks", now).toDate()); + + Assert.assertEquals(StringToTime.parseDateTime("1 year", now).toDate(), + StringToTime.parseDateTime("+1 year", now).toDate()); + + Assert.assertEquals( + StringToTime.parseDateTime("+1 year", now).toDate(), + StringToTime.parseDateTime("+12 months", now).toDate()); + + Assert.assertEquals(StringToTime.parseDateTime("+1 year 6 months", now) + .toDate(), StringToTime.parseDateTime("+18 months", now) + .toDate()); + + Assert.assertEquals( + StringToTime.parseDateTime("12 months 1 day 60 seconds", now) + .toDate(), + StringToTime.parseDateTime("1 year 24 hours 1 minute", now) + .toDate()); } - + + @Test public void testDecrements() { Date now = new Date(); - + Calendar cal = Calendar.getInstance(); cal.setTime(now); - cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY)-1); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("-1 hour", now)); + cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) - 1); + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("-1 hour", now).toDate()); } - + + @Test public void testTomorrow() { Date now = new Date(); Calendar cal = Calendar.getInstance(); cal.setTime(now); - cal.set(Calendar.DATE, cal.get(Calendar.DATE)+1); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("tomorrow", now)); - assertEquals(new StringToTime("now +24 hours", now), new StringToTime("tomorrow", now)); + cal.set(Calendar.DATE, cal.get(Calendar.DATE) + 1); + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("tomorrow", now).toDate()); + Assert.assertEquals(StringToTime.parseDateTime("now +24 hours", now) + .toDate(), StringToTime.parseDateTime("tomorrow", now).toDate()); } - + + @Test public void testTomorrowMorning() { Date now = new Date(); - assertEquals(new StringToTime("this morning +24 hours", now), new StringToTime("tomorrow morning", now)); + Assert.assertEquals( + StringToTime.parseDateTime("this morning +24 hours", now) + .toDate(), + StringToTime.parseDateTime("tomorrow morning", now).toDate()); } - + + @Test public void testTomorrowNoon() { Date now = new Date(); - assertEquals(new StringToTime("noon +24 hours", now), new StringToTime("tomorrow noon", now)); - assertEquals(new StringToTime("noon +24 hours", now), new StringToTime("noon tomorrow", now)); + Assert.assertEquals(StringToTime.parseDateTime("noon +24 hours", now) + .toDate(), StringToTime.parseDateTime("tomorrow noon", now) + .toDate()); + Assert.assertEquals(StringToTime.parseDateTime("noon +24 hours", now) + .toDate(), StringToTime.parseDateTime("noon tomorrow", now) + .toDate()); } - + + @Test public void testTomorrowAfternoon() { Date now = new Date(); - assertEquals(new StringToTime("this afternoon +24 hours", now), new StringToTime("tomorrow afternoon", now)); + Assert.assertEquals( + StringToTime.parseDateTime("this afternoon +24 hours", now) + .toDate(), + StringToTime.parseDateTime("tomorrow afternoon", now).toDate()); } - + + @Test public void testTomorrowEvening() { Date now = new Date(); - assertEquals(new StringToTime("this evening +24 hours", now), new StringToTime("tomorrow evening", now)); + Assert.assertEquals( + StringToTime.parseDateTime("this evening +24 hours", now) + .toDate(), + StringToTime.parseDateTime("tomorrow evening", now).toDate()); } - + + @Test public void testTomorrowNight() { Date now = new Date(); - assertEquals(new StringToTime("tonight +24 hours", now), new StringToTime("tomorrow night", now)); + Assert.assertEquals(StringToTime + .parseDateTime("tonight +24 hours", now).toDate(), StringToTime + .parseDateTime("tomorrow night", now).toDate()); } - - // e.g., October 26, 1981, or Oct 26, 1981, or 26 October 1981, or 26 Oct 1981, or 26 Oct 81 + + // e.g., October 26, 1981, or Oct 26, 1981, or 26 October 1981, or 26 Oct + // 1981, or 26 Oct 81 + @Test public void testLongHand() throws Exception { - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("October 26, 1981")); - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("Oct 26, 1981")); - - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("26 October 1981")); - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("26 Oct 1981")); - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("26 Oct 81")); - - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("26 october 1981")); - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("26 oct 1981")); - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("26 oct 81")); - - assertEquals(new SimpleDateFormat("M/d/y").parse("1/1/2000"), new StringToTime("1 Jan 2000")); - assertEquals(new SimpleDateFormat("M/d/y").parse("1/1/2000"), new StringToTime("1 Jan 00")); - - assertEquals(new SimpleDateFormat("M/d/y").parse("1/1/2000"), new StringToTime("1 jan 2000")); - assertEquals(new SimpleDateFormat("M/d/y").parse("1/1/2000"), new StringToTime("1 jan 00")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("October 26, 1981")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("Oct 26, 1981")); + + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("26 October 1981")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("26 Oct 1981")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("26 Oct 81")); + + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("26 october 1981")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("26 oct 1981")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("26 oct 81")); + + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("1/1/2000"), + StringToTime.parseDateTime("1 Jan 2000")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("1/1/2000"), + StringToTime.parseDateTime("1 Jan 00")); + + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("1/1/2000"), + StringToTime.parseDateTime("1 jan 2000")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("1/1/2000"), + StringToTime.parseDateTime("1 jan 00")); } - + // e.g., 10/26/1981 or 10/26/81 + @Test public void testWithSlahesMonthFirst() throws Exception { - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("10/26/1981")); - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("10/26/81")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("10/26/1981")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("10/26/81")); } // e.g., 1981/10/26 + @Test public void testWithSlashesYearFirst() throws Exception { - assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), new StringToTime("1981/10/26")); + Assert.assertEquals(new SimpleDateFormat("M/d/y").parse("10/26/1981"), + StringToTime.parseDateTime("1981/10/26")); } - + // e.g., October 26 and Oct 26 + @Test public void testMonthAndDate() throws Exception { Date now = new Date(); Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, Calendar.OCTOBER); cal.set(Calendar.DATE, 26); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("October 26", now)); - assertEquals(new StringToTime("Oct 26", now), new StringToTime("October 26", now)); + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("October 26", now).toDate()); + Assert.assertEquals(StringToTime.parseDateTime("Oct 26", now).toDate(), + StringToTime.parseDateTime("October 26", now).toDate()); } - + // e.g., 10/26 + @Test public void testWithSlahesMonthAndDate() throws Exception { Calendar cal = Calendar.getInstance(); cal.set(Calendar.MONTH, Calendar.OCTOBER); cal.set(Calendar.DATE, 26); - assertEquals(new Date(cal.getTimeInMillis()), new StringToTime("10/26")); + Assert.assertEquals(new Date(cal.getTimeInMillis()), StringToTime + .parseDateTime("10/26").toDate()); } - + // e.g., October or Oct + @Test public void testMonth() throws Exception { Date now = new Date(); - - assertEquals(new StringToTime("October", now), new StringToTime("Oct", now)); - + + Assert.assertEquals( + StringToTime.parseDateTime("October", now).toDate(), + StringToTime.parseDateTime("Oct", now)); + Calendar cal = Calendar.getInstance(); cal.setTime(now); - + + Calendar cal2 = Calendar.getInstance(); + // it should be this year - assertEquals(cal.get(Calendar.YEAR), new StringToTime("January", now).getCal().get(Calendar.YEAR)); - assertEquals(cal.get(Calendar.YEAR), new StringToTime("December", now).getCal().get(Calendar.YEAR)); + cal2.setTime(StringToTime.parseDateTime("January", now).toDate()); + Assert.assertEquals(cal.get(Calendar.YEAR), cal2.get(Calendar.YEAR)); + cal2.setTime(StringToTime.parseDateTime("December", now).toDate()); + Assert.assertEquals(cal.get(Calendar.YEAR), cal2.get(Calendar.YEAR)); } - + + @Test public void testDayOfWeek() throws Exception { Date now = new Date(); - assertEquals(StringToTime.date("Friday", now), StringToTime.date("Fri", now)); - + Assert.assertEquals(StringToTime.parseDateTime("Friday", now).toDate(), + StringToTime.parseDateTime("Fri", now).toDate()); + Calendar cal = Calendar.getInstance(); cal.setTime(now); - - // if today's day of the week is greater than or equal to our test day of the week (Wednesday) - if (cal.get(Calendar.DAY_OF_WEEK) >= 3) // then the day of the week on the date returned should be next week - assertEquals(cal.get(Calendar.WEEK_OF_YEAR)+1, new StringToTime("Wednesday", now).getCal().get(Calendar.WEEK_OF_YEAR)); - else // otherwise, it should be this year - assertEquals(cal.get(Calendar.WEEK_OF_YEAR), new StringToTime("Wednesday", now).getCal().get(Calendar.WEEK_OF_YEAR)); + + // if today's day of the week is greater than or equal to our test day + // of the week (Wednesday) + Calendar cal2 = Calendar.getInstance(); + if(cal.get(Calendar.DAY_OF_WEEK) >= 3) {// then the day of the week on + // the date returned should be + // next week + cal2.setTime(StringToTime.parseDateTime("Wednesday", now).toDate()); + Assert.assertEquals(cal.get(Calendar.WEEK_OF_YEAR) + 1, + cal2.get(Calendar.WEEK_OF_YEAR)); + } + else { + // otherwise, it should be this year + cal2.setTime(StringToTime.parseDateTime("Wednesday", now).toDate()); + Assert.assertEquals(cal.get(Calendar.WEEK_OF_YEAR), + cal2.get(Calendar.WEEK_OF_YEAR)); + } } - + + @Test public void testNext() { Date now = new Date(); - assertEquals(new StringToTime("next January 15", now), new StringToTime("Jan 15", now)); - assertEquals(new StringToTime("next Dec", now), new StringToTime("December", now)); - assertEquals(new StringToTime("next Sunday", now), new StringToTime("Sun", now)); - assertEquals(new StringToTime("next Sat", now), new StringToTime("Saturday", now)); + Assert.assertEquals(StringToTime.parseDateTime("next January 15", now) + .toDate(), StringToTime.parseDateTime("Jan 15", now).toDate()); + Assert.assertEquals(StringToTime.parseDateTime("next Dec", now) + .toDate(), StringToTime.parseDateTime("December", now).toDate()); + Assert.assertEquals(StringToTime.parseDateTime("next Sunday", now) + .toDate(), StringToTime.parseDateTime("Sun", now).toDate()); + Assert.assertEquals(StringToTime.parseDateTime("next Sat", now) + .toDate(), StringToTime.parseDateTime("Saturday", now).toDate()); } - + + @Test public void testLast() { Date now = new Date(); - assertEquals(new StringToTime("last January 15", now), new StringToTime("Jan 15 -1 year", now)); - assertEquals(new StringToTime("last Dec", now), new StringToTime("December -1 year", now)); - assertEquals(new StringToTime("last Sunday", now), new StringToTime("Sun -1 week", now)); - assertEquals(new StringToTime("last Sat", now), new StringToTime("Saturday -1 week", now)); + Assert.assertEquals(StringToTime.parseDateTime("last January 15", now) + .toDate(), StringToTime.parseDateTime("Jan 15 -1 year", now) + .toDate()); + Assert.assertEquals(StringToTime.parseDateTime("last Dec", now) + .toDate(), StringToTime.parseDateTime("December -1 year", now) + .toDate()); + Assert.assertEquals(StringToTime.parseDateTime("last Sunday", now) + .toDate(), StringToTime.parseDateTime("Sun -1 week", now) + .toDate()); + Assert.assertEquals(StringToTime.parseDateTime("last Sat", now) + .toDate(), StringToTime.parseDateTime("Saturday -1 week", now) + .toDate()); } - - - + }