-5

I am trying to convert dates of the format

07/Mar/2004:16:56:39 -0800

to a date object. I'm not sure what that format's name even is but its used in tomcat access logs. Can someone please help me out?

SimpleDateFormat f = new SimpleDateFormat("dd-MMM-yyyy:HH:mm:ss");
Date d = f.parse("07/Mar/2004:16:56:39 -0800"); // Throws exception.
System.out.println(d.getTime());
newToScala
  • 397
  • 4
  • 16
  • also a duplicate of [this](https://stackoverflow.com/q/11527451/642706) and [this](https://stackoverflow.com/q/882420/642706), and [this](https://stackoverflow.com/q/21042484/642706) and many more. – Basil Bourque Aug 13 '17 at 20:20
  • 1
    Just for the record, this "negative number" is a [UTC offset](https://en.wikipedia.org/wiki/ISO_8601?oldformat=true#Time_offsets_from_UTC) –  Aug 13 '17 at 22:21

3 Answers3

2

The format string should match the input. In particular, the separator must match.

Also, your format string is missing the time zone part to match against the -0800.

Since your input uses English month name, you should explicitly specify that, e.g. using Locale.US.

SimpleDateFormat f = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z", Locale.US);
Date d = f.parse("07/Mar/2004:16:56:39 -0800");
System.out.println(d);

Since I'm in Eastern time zone, that prints:

Sun Mar 07 19:56:39 EST 2004


You should however use the new java.time classes instead.

Since the input string has a time zone offset, that means you should parse the string to an OffsetDateTime, using a DateTimeFormatter:

DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MMM/uuuu:HH:mm:ss Z", Locale.US);
OffsetDateTime dt = OffsetDateTime.parse("07/Mar/2004:16:56:39 -0800", f);
System.out.println(dt);

Output is:

2004-03-07T16:56:39-08:00

Andreas
  • 154,647
  • 11
  • 152
  • 247
0

You need to add the time zone to your date format and change the format to your input string (/ instead of -):

SimpleDateFormat f = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z", Locale.US);

See the docs: https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html

bish
  • 3,381
  • 9
  • 48
  • 69
  • 1
    the `-` should be `/` – luk2302 Aug 13 '17 at 16:41
  • @luk2302 Yeah saw that too in the moment I answered. – bish Aug 13 '17 at 16:42
  • f.parse("07/Mar/2004:16:56:39 /0800"); throws an exception though. – newToScala Aug 13 '17 at 16:43
  • Still unparseable – Robin Topper Aug 13 '17 at 16:43
  • 1
    And you need to set the appropriate Locale, too. – JB Nizet Aug 13 '17 at 16:43
  • @newToScala why is there a `/` in front of `0800`? – luk2302 Aug 13 '17 at 16:43
  • How should "07/Mar/2004:16:56:39 -0800" be reformated to be parseable? – newToScala Aug 13 '17 at 16:44
  • 3
    @newToScala `SimpleDateFormat f = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z", Locale.US);`. You need to read the documentation. – JB Nizet Aug 13 '17 at 16:45
  • I appreciate the help, and have looked at docs. This code still throws an exception: ```SimpleDateFormat f = new SimpleDateFormat("dd-MMM-yyyy:HH:mm:ss Z", Locale.US); Date d = f.parse("07/Mar/2004:16:56:39 -0800"); System.out.println(d.getTime());``` – newToScala Aug 13 '17 at 16:48
  • 1
    Don't use `SimpleDateFormat` and don't use `Date`. Use the new [`DateTimeFormatter`](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) and [`OffsetDateTime`](https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html) instead: `OffsetDateTime.parse("07/Mar/2004:16:56:39 -0800", DateTimeFormatter.ofPattern("dd/MMM/uuuu:HH:mm:ss Z", Locale.US))` – Andreas Aug 13 '17 at 16:49
  • @newToScala Because your format has `-` between date and month, and your string has `/`. – Andreas Aug 13 '17 at 16:50
  • Doh. THat works now. THank you very much. – newToScala Aug 13 '17 at 16:51
  • @bish OP says the string to parse is `07/Mar/2004:16:56:39 -0800`, so give a date format that matches that, don't tell OP to change the input. Down-voted until you fix answer. – Andreas Aug 13 '17 at 16:51
  • @Andreas edited the slashes – bish Aug 14 '17 at 09:39
-1

You have a typo in the line:

Date d = f.parse("07/Mar/2004:16:56:39 -0800");

The format for the date is "dd-MMM-yyyy:HH:mm:ss". You need to replace the "/" with "-". Additionally, you need to surround your parse function with a try-catch block as follows:

SimpleDateFormat f = new SimpleDateFormat("dd-MMM-yyyy:HH:mm:ss");
    Date d;
    try {
        d = f.parse("07-Mar-2004:16:56:39");
        System.out.println(d.getTime());
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 

Check out this link to learn more about the SimpleDateFormat Class: http://www.xyzws.com/javafaq/how-to-use-simpledateformat-class-formating-parsing-date-and-time/142

  • 1
    No. The format of the date uses `/` and has a time zone. The requirement is to find out the right format string so the given input can be parsed, not the other way around. – Andreas Aug 13 '17 at 16:53