4

I'm looking for an easy way to generate a MySQL DATETIME from any type of time input a user may enter. PHP makes it easy with its strtotime() function that can do:

strtotime(’2004-02-12T15:19:21+00:00′);

strtotime(’Thu, 21 Dec 2000 16:01:07 +0200′);

strtotime(’Monday, January 1st’);

strtotime(’tomorrow’);

strtotime(’-1 week 2 days 4 hours 2 seconds’);

Outputs:

2004-02-12 07:02:21

2000-12-21 06:12:07

2009-01-01 12:01:00

2009-02-12 12:02:00

2009-02-06 09:02:41

I want this in Java!

Kirk Ouimet
  • 27,280
  • 43
  • 127
  • 177
  • possible duplicate of [PHP's strtotime() in Java](http://stackoverflow.com/questions/1268174/phps-strtotime-in-java) – nawfal Jan 30 '14 at 11:38

2 Answers2

0

I tried to implement a simple (static) class that emulates some of the patterns of PHP's strtotime. This class is designed to be open for modification (simply add a new Matcher via registerMatcher):

public final class strtotime {

    private static final List<Matcher> matchers;

    static {
        matchers = new LinkedList<Matcher>();
        matchers.add(new NowMatcher());
        matchers.add(new TomorrowMatcher());
        matchers.add(new DateFormatMatcher(new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z")));
        matchers.add(new DateFormatMatcher(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")));
        matchers.add(new DateFormatMatcher(new SimpleDateFormat("yyyy MM dd")));
        // add as many format as you want 
    }

    // not thread-safe
    public static void registerMatcher(Matcher matcher) {
        matchers.add(matcher);
    }

    public static interface Matcher {

        public Date tryConvert(String input);
    }

    private static class DateFormatMatcher implements Matcher {

        private final DateFormat dateFormat;

        public DateFormatMatcher(DateFormat dateFormat) {
            this.dateFormat = dateFormat;
        }

        public Date tryConvert(String input) {
            try {
                return dateFormat.parse(input);
            } catch (ParseException ex) {
                return null;
            }
        }
    }

    private static class NowMatcher implements Matcher {

        private final Pattern now = Pattern.compile("now");

        public Date tryConvert(String input) {
            if (now.matcher(input).matches()) {
                return new Date();
            } else {
                return null;
            }
        }
    }

    private static class TomorrowMatcher implements Matcher {

        private final Pattern tomorrow = Pattern.compile("tomorrow");

        public Date tryConvert(String input) {
            if (tomorrow.matcher(input).matches()) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_YEAR, +1);
                return calendar.getTime();
            } else {
                return null;
            }
        }
    }

    public static Date strtotime(String input) {
        for (Matcher matcher : matchers) {
            Date date = matcher.tryConvert(input);

            if (date != null) {
                return date;
            }
        }

        return null;
    }

    private strtotime() {
        throw new UnsupportedOperationException();
    }
}

Usage

Basic usage:

 Date now = strtotime("now");
 Date tomorrow = strtotime("tomorrow");
Wed Aug 12 22:18:57 CEST 2009
Thu Aug 13 22:18:57 CEST 2009

Extending

For example let's add days matcher:

strtotime.registerMatcher(new Matcher() {

    private final Pattern days = Pattern.compile("[\\-\\+]?\\d+ days");

    public Date tryConvert(String input) {

        if (days.matcher(input).matches()) {
            int d = Integer.parseInt(input.split(" ")[0]);
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_YEAR, d);
            return calendar.getTime();
        }

        return null;
    }
});

then you can write:

System.out.println(strtotime("3 days"));
System.out.println(strtotime("-3 days"));

(now is Wed Aug 12 22:18:57 CEST 2009)

Sat Aug 15 22:18:57 CEST 2009
Sun Aug 09 22:18:57 CEST 2009
Yuseferi
  • 7,931
  • 11
  • 67
  • 103
-3

Thanks for the quick reply ChssPly76. Here's my solution, although it's hard coded to handle dates coming in this format: "5 Aug 2009 07:27:51 GMT". Perhaps there is a way to allow it to easily handle other formats in case of a parse exception?

public static String stringToDateTime(String string) {
    SimpleDateFormat sdf = new SimpleDateFormat("d MMM yyyy HH:mm:ss z");
    Date date;
    String sqlDate;
    try {
        date = sdf.parse(string);
        SimpleDateFormat sqlFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sqlDate = sqlFormat.format(date);
    }
    catch(ParseException ex) {
        sqlDate = string;
    }

    return sqlDate;
}
Kirk Ouimet
  • 27,280
  • 43
  • 127
  • 177
  • 1
    You could add all possible formats your users may enter to a list and iterate through it, attempting to parse and catching an exception until parse is successful or list ends. Note of caution: based on your code sample it looks like you're trying to convert date to a string MySQL expects in order to dynamically build a SQL statement? That's not a good approach, you should use a PreparedStatement instead and pass date parameter as Date object. – ChssPly76 Aug 06 '09 at 02:54