2

I need to convert a String containing a date into a date object.

The String will be in the format "yyyy-mm-dd HH:mm:ss" and I want the "MM/dd/yyyy HH:mm:ss a " format as result.

String dateString = "2018-03-20 09:31:31";

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss a", 
                                                           Locale.ENGLISH);

LocalDate date = LocalDate.parse(dateString , formatter);

The code above is throwing an exception.

ngdn
  • 23
  • 4
Ban
  • 339
  • 1
  • 5
  • 16
  • 1
    "I want the "MM/dd/yyyy HH:mm:ss a "format in an date object." There's no such thing. A `LocalDate` value doesn't have a format. You can parse to a `LocalDate` (by providing the format of your input string when you parse) but then it's just a `LocalDate`. If you want a particular text representation later, you format the value with an appropriate formatter. – Jon Skeet Mar 27 '18 at 09:10
  • 1
    Your string pattern and your parser pattern don't match – jhamon Mar 27 '18 at 09:11
  • 2
    LocalDate doesn't contain time info. So you have to use LocalDateTime instead. – Omoro Mar 27 '18 at 09:11

5 Answers5

3

You have to use two Formatter, one to covert String to LocalDateTime and the other to format this date as you want :

From String to LocalDateTime :

String dateString = "2018-03-20 09:31:31";

LocalDateTime date = LocalDateTime.parse(
        dateString,
        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH)
);

Now From LocalDateTime to String :

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
        "MM/dd/yyyy HH:mm:ss a", Locale.ENGLISH
);

String newDate = date.format(formatter);
System.out.println(newDate);// 03/20/2018 09:31:31 AM

Note : You have to use LocalDateTime instead of just LocalDate, your format contain both date and time, not just date, else you will get an error :

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
2

That's a common error, based on the misconception that dates have formats - but they actually don't.

Date/time objects have only values, and those values - usually numerical - represent the concept of a date (a specific point in the calendar) and a time (a specific moment of the day).

If you have a String, then you don't actually have a date. You have a text (a sequence of characters) that represents a date. Note that all of the strings below are different (they have a different sequence of characters), but all represent the same date (the same values, the same point in the calendar):

  • 2018-03-20 09:31:31
  • 03/20/2018 9:31:31 AM (using USA's format: month/day/year)
  • Tuesday, March 20th 2018, 09:31:31 am
  • and many others...

What you want to do is to get one format (one String, one text representing a date) and transform it to another format (anoter String, another different sequence of characters that represents the same date).

In Java (and in many other languages - if not all - btw) you must do it in 2 steps:

  1. convert the String to a date/time object (convert the text to the numerical values) - that's what the parse method does
  2. convert the date/time object to another format (convert the numerical values to another text)

That said, when you call the parse method, you're trying to transform a String (a text, a sequence of characters) into a date/time object. This means that the DateTimeFormatter must have a pattern that matches the input.

The input is 2018-03-20 09:31:31, which is year-month-day hour:minute:second. And the formatter you used to parse it has the pattern MM/dd/yyyy HH:mm:ss a (month/day/year hour:minute:second am/pm).

You used the output pattern (the one that should be used in step 2) to parse the input. That's why you've got an exception: the formatter tried to parse a month with 2 digits followed by a / when the input actually contains a year with 4 digits followed by a -.

You must use a different DateTimeFormatter for each step, using the correct pattern for each case. YCF_L's answer has the code that does the job, I'd just like to add one little detail. The formatter used for the output (step 2) is:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
        "MM/dd/yyyy HH:mm:ss a", Locale.ENGLISH
);

Note that HH is used for the hours. Take a look at the javadoc and you'll see that uppercase HH represents the hour-of-day fields (values from 0 to 23 - so 1 AM is printed as 01 and 1 PM is printed as 13).

But you're also printing the AM/PM field (the a in the pattern), so maybe what you need is actually the lowercase hh, which is the clock-hour-of-am-pm (values from 1 to 12) or even KK (hour-of-am-pm (values from 0 to 11)).

ngdn
  • 23
  • 4
0
String dateString = "2018-03-20 09:31:31";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

try {
    Date date = formatter.parse(dateInString);

    DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
    String reportDate = df.format(date );
} catch (ParseException e) {
        e.printStackTrace();
}
Moinul Islam
  • 469
  • 2
  • 9
0

You need to do a 2 steps conversion:

  1. from your String date time in the wrong format to a (tempoary) LocalDateTime object.
  2. if you still want to only extract the date (Year-Month-day) do a LocalDateTime.toLocalDate()
  3. From this LocalDateTime object into the your String object in the right format

        String dateString = "2018-03-20 09:31:31";
    
        DateTimeFormatter formatterForWrongFormat = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral(" ")
                .append(DateTimeFormatter.ISO_LOCAL_TIME)
                .toFormatter();
    
        //1- from String(wrong format) into datetime object
        LocalDateTime dateTime = LocalDateTime.parse(dateString , formatterForWrongFormat);
    
        // 1.1 extract date object (Optional)
        LocalDate myDate =  dateTime.toLocalDate();
    
        // 2- now from your  LocalDateTime to the String in the RIGHT format
        DateTimeFormatter formatterForRightFormat =  DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss a",
                Locale.ENGLISH);
    
        System.out.println("right format: "+dateTime.format(formatterForRightFormat));
    

you can test this code here

arthur
  • 3,245
  • 4
  • 25
  • 34
-1

You can use the SimpleDateFormatter which is easier to implement and permit you to change the format of your date easily.

More here : What are the date formats available in SimpleDateFormat class?

Hope this will help you !

Tekateyy
  • 81
  • 1
  • 1
  • 8
  • How exactly is `SimpleDateFormat` easier than `DateTimeFormatter`? – lexicore Mar 27 '18 at 09:12
  • 1
    `DateTimeFormatter` and the new `java.time` APIs are *much* better than the old `SimpleDateFormatter`/`Date`/`Calendar` APIs. The fundamental problem would still remain: the OP is expecting to parse a value with the wrong format, and expecting the value to "know" its format. That would be just as problematic in the old APIs. – Jon Skeet Mar 27 '18 at 09:12
  • Oh ok for the DateTimeFormatter it may be much better ! But (for me) the SimpleDateFormat is easier to use and it will work. And yes in this case he has to use 2 formatter like YCF_L said, and make sure you have the same format in input... – Tekateyy Mar 27 '18 at 09:30