tags:

views:

51

answers:

1

My database contains URLs stored as text fields and each URL contains a representation of the date of a report, which is missing from the report itself.

So I need to parse the date from the URL field to a String representation such as:

2010-10-12
2007-01-03
2008-02-07

What's the best way to extract the dates?

Some are in this format:

http://e.com/data/invoices/2010/09/invoices-report-wednesday-september-1st-2010.html

http://e.com/data/invoices/2010/09/invoices-report-thursday-september-2-2010.html

http://e.com/data/invoices/2010/09/invoices-report-wednesday-september-15-2010.html

http://e.com/data/invoices/2010/09/invoices-report-monday-september-13th-2010.html

http://e.com/data/invoices/2010/08/invoices-report-monday-august-30th-2010.html

http://e.com/data/invoices/2009/05/invoices-report-friday-may-8th-2009.html

http://e.com/data/invoices/2010/10/invoices-report-wednesday-october-6th-2010.html

http://e.com/data/invoices/2010/09/invoices-report-tuesday-september-21-2010.html

Note the inconsistent use of th following the day of the month in cases such as these two:

http://e.com/data/invoices/2010/09/invoices-report-wednesday-september-15-2010.html

http://e.com/data/invoices/2010/09/invoices-report-monday-september-13th-2010.html

Others are in this format (with three hyphens before the date starts, no year at the end and an optional use of invoices- before report):

http://e.com/data/invoices/2010/09/invoices-report---wednesday-september-1.html

http://e.com/data/invoices/2010/09/invoices-report---thursday-september-2.html

http://e.com/data/invoices/2010/09/invoices-report---wednesday-september-15.html

http://e.com/data/invoices/2010/09/invoices-report---monday-september-13.html

http://e.com/data/invoices/2010/08/report---monday-august-30.html

http://e.com/data/invoices/2009/05/report---friday-may-8.html

http://e.com/data/invoices/2010/10/report---wednesday-october-6.html

http://e.com/data/invoices/2010/09/report---tuesday-september-21.html
+5  A: 

You want a regex like this:

"^http://e.com/data/invoices/(\\d{4})/(\\d{2})/\\D+(\\d{1,2})"

This exploits that everything up through the /year/month/ part of the URL is always the same, and that no number follows till the day of the month. After you have that, you don't care about anything else.

The first capture group is the year, the second the month, and the third the day. The day might not have a leading zero; convert from string to integer and format as needed, or just grab the string length and, if it's not two, then concatenate it to the string "0".

As an example:

import java.util.regex.*;

class URLDate {
  public static void
  main(String[] args) {
    String text = "http://e.com/data/invoices/2010/09/invoices-report-wednesday-september-1st-2010.html";
    String regex = "http://e.com/data/invoices/(\\d{4})/(\\d{2})/\\D+(\\d{1,2})";
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(text);
    if (m.find()) {
      int count = m.groupCount();
      System.out.format("matched with groups:\n", count);
      for (int i = 0; i <= count; ++i) {
          String group = m.group(i);
          System.out.format("\t%d: %s\n", i, group);
      }
    } else {
      System.out.println("failed to match!");
    }
  }
}

gives the output:

matched with groups:
    0: http://e.com/data/invoices/2010/09/invoices-report-wednesday-september-1st-2010.html
    1: 2010
    2: 09
    3: 1

(Note that to use Matcher.matches() instead of Matcher.find(), you would have to make the pattern eat the entire input string by appending .*$ to the pattern.)

Jeremy W. Sherman
Perfect. Thanks for warning about `matches()` vs. `find()`.
snoopy