1

I need to parse a String into dd/MM/YY hh:mm:ss format.

Suppose if a String has value 09/06/17 05:59:59 then it should be parsed but if a String has value 09/06/2017 05:59:59 then this is also a valid format and getting parsed but in my requirement, a parse exception should be thrown for the later.

Code:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo {

    public static void main(String[] args) {

        String line=" 09/06/17 05:59:59 20170609IT36701706080107 42 103 Output USD 970.20 IT3670";
        //String line=" 09/06/2017 05:59:59 20170609IT36701706080107 42 103 Output USD 970.20 IT3670";

        String dt=null;
        dt=line.substring(1, 19);

        SimpleDateFormat org_format = new SimpleDateFormat("dd/MM/YY hh:mm:ss");
        SimpleDateFormat tgt_format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        try {
              dt=line.substring(1, 19);

              System.out.println(dt);
              Date date = org_format.parse(dt);
              System.out.println(date);

              String tgt_date=tgt_format.format(date);
              System.out.println(tgt_date);
         } catch (ParseException e) {
              System.out.println(line);
         }
    }
}

Problem - In the code, uncommented line variable and commented line variable, both are giving result successfully. but the commented line should throw parsable exception as it's the pattern dd/MM/yyyy, not dd/MM/yy.

fmt.setLenient(false) is not working.

I'm using Java 7. Don't have option to use Java 8 or later so can't use java.time.

Vishal Mishra
  • 59
  • 1
  • 5

3 Answers3

2

Don't have option to use java 8 or later so cant use java.time

The Java 8 date and time classes have been backported to Java 6 and 7, so yes, you can use them in your Java 7. Get ThreeTen Backport. This is also the futureproof investment: if and when eventually you upgrade to Java 8 or 9, you will only have to modify your import declarations and your code will work with the java.time classes.

So I recommend you throw the outdated classes SimpleDateFormat and Date over the shoulder. It’s very typical for SimpleDateFormat to give you a result (very often an incorrect one) in a situation where you would want an exception. As you noted, sometimes org_format.setLenient(false); helps, but not in your case.

Using ThreeTen Backport:

    DateTimeFormatter originalFormat = DateTimeFormatter.ofPattern("dd/MM/uu HH:mm:ss");
    ParsePosition pos = new ParsePosition(1); // skip leading space
    LocalDateTime ldt = LocalDateTime.from(originalFormat.parse(line, pos));

This parses your line with 2-digit year into

2017-01-02 05:59:59

For the line with 4-digit year for which “in my requirement, parse exception should be thrown”, we get

Exception in thread "main" java.time.format.DateTimeParseException: Text ' 09/06/2017 05:59:59 20170609IT36701706080107 42 103 Output USD ...' could not be parsed at index 9

It says index 9, that’s at the 17 in 2017, that is, exactly where the third digit of the year is when there were only supposed to be two digits.

A couple of points to be aware of:

  • Use capital HH in the format pattern for hour of day (small hh is for hour with AM or PM, only useful with an AM/PM marler). Use lowercase for the year, either uu or yy (not uppercase YY, it’s for weekbased year, only useful with a week number). BTW, again SimpleDateFormat let you get away with these bugs and will sometimes give you incorrect results; the modern classes will object by throwing an exception.
  • My code will parse into a year from 2000 through 2099. Please check whether this is what you want. You may want to impose an additional restriction, for example, that the date-time should be in the past and not more than 5 years ago, for enhanced validation. You know better than I.

To convert into your target format:

    DateTimeFormatter targetFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
    String targetDate = ldt.format(targetFormat);

With the former of your lines the result is

2017-01-02 05:59:59
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

You can use regex to check if year contains 4 digits and if so throw new ParseException. The program is:

public static void main(String[] args) throws ParseException {

        String date = "09/06/17 05:59:59";

        if (date.matches("\\d{1,2}[/.-]\\d{1,2}[/.-]\\d{4} .*"))
            throw new ParseException("date has wrong format");
        else {

        }

    }
Jay Smith
  • 2,331
  • 3
  • 16
  • 27
0

Regex to match any of these date formats

String regex = "^(([0]?[1-9]|1[0-2])/([0-2]?[0-9]|3[0-1])/[1-2]\d{3}) (20|21|22|23|[0-1]?\d{1}):([0-5]?\d{1})$";
Pattern pattern = Pattern.compile(regex);

Matcher matcher = pattern.matcher("09/06/17 05:59:59");

if(matcher.matches()){
    //your next code
}
ZeroOne
  • 8,996
  • 4
  • 27
  • 45