Simpledateformat unparseable date
Asked Answered
R

7

10

I have a String in a database (match.getDate) that has the following date format:

01/04/2018

This is the date I want to format, stored as day/month/year. I want to format this for my Android app.

I want to format the date into:

Sun 01 Apr 2018

My code below:

SimpleDateFormat fDate = new SimpleDateFormat("dd/MM/yyyy");
try {
    textViewDate.setText(fDate.parse(match.getDate()).toString());
} catch (ParseException ex) {
    System.out.println(ex.toString());
}

This outputs:

Sun Apr 08 00:00:00 GMT+00:00 2018.

I have also tried "EE, MM d, yyyy", but it gives me:

java.text.ParseException: Unparseable date: "01/04/2018"

Ratcliffe answered 9/3, 2018 at 11:4 Comment(9)
what is the format of the date you want to parse? post date format from what to what format you want to parse.Botticelli
I've highlighted the date that its stored as to make it easier to read, 01/04/2018 which is the date I want to parseRatcliffe
Possible duplicate of How do I convert the date from one format to another date object in another format without using any deprecated classes?Podophyllin
check this link, #19929257Geelong
As an aside consider throwing away the long outmoded and notoriously troublesome SimpleDateFormat and friends, and adding ThreeTenABP to your Android project in order to use java.time, the modern Java date and time API. It is so much nicer to work with.Fulgent
Possible duplicate of Change date format in a Java stringFulgent
Similar questions have been asked and answered lots of times. Please search, and you will find a good answer faster than anyone can type one here. And for the benefit of future Stack Overflow users all the information will be in one place.Fulgent
In a good design I don’t think match.getDate() should return a String. When retrieving from your database, retrieve a LocalDate, keep it in your match object and return it in getDate. That will eliminate every parsing problem.Fulgent
FYI, the troublesome old date-time classes such as java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat are now legacy, supplanted by the java.time classes. Much of the java.time functionality is back-ported to Java 6 & Java 7 in the ThreeTen-Backport project. Further adapted for earlier Android in the ThreeTenABP project. See How to use ThreeTenABP….Lauryn
H
6

Use this date formatter method I have created

    public static String dateFormater(String dateFromJSON, String expectedFormat, String oldFormat) {
    SimpleDateFormat dateFormat = new SimpleDateFormat(oldFormat);
    Date date = null;
    String convertedDate = null;
    try {
        date = dateFormat.parse(dateFromJSON);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(expectedFormat);
        convertedDate = simpleDateFormat.format(date);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return convertedDate;
}

and call this method like

dateFormater(" 01/04/2018" , "EE dd MMM yyyy" , "dd/MM/yyyy") 

and you will get the desired output

Histiocyte answered 9/3, 2018 at 11:11 Comment(1)
FYI, the terribly flawed date-time classes such as java.util.Date, java.util.Calendar, & java.text.SimpleDateFormat are now legacy, supplanted by java.time classes. Most java.time functionality is back-ported to Java 6 & Java 7 in the ThreeTen-Backport project. Further adapted for earlier Android (<26) in ThreeTenABP. See How to use ThreeTenABP….Lauryn
S
9

The other answers solved your problem, but I think it's important to know some concepts and why your first attempt didn't work.

There's a difference between a date and a text that represents a date.

Example: today's date is March 9th 2018. That date is just a concept, an idea of "a specific point in our calendar system".

The same date, though, can be represented in many formats. It can be "graphical", in the form of a circle around a number in a piece of paper with lots of other numbers in some specific order, or it can be in plain text, such as:

  • 09/03/2018 (day/month/year)
  • 03/09/2018 (monty/day/year)
  • 2018-03-09 (ISO8601 format)
  • March, 9th 2018
  • 9 de março de 2018 (in Portuguese)
  • 2018年3月5日 (in Japanese)
  • and so on...

Note that the text representations are different, but all of them represent the same date (the same value).

With that in mind, let's see how Java works with these concepts.

  • a text is represented by a String. This class contains a sequence of characters, nothing more. These characters can represent anything; in this case, it's a date
  • a date was initially represented by java.util.Date, and then by java.util.Calendar, but those classes are full of problems and you should avoid them if possible. Today we have a better API for that.

In Android, you can use the java.time classes if available in the API level you're using, or the threeten backport for API levels lower than that (check here how to use it). You'll have easier and more reliable tools to deal with dates.

In your case, you have a String (a text representing a date) and you want to convert it to another format. You must do it in 2 steps:

  1. convert the String to some date-type (transform the text to numerical day/month/year values) - that's called parsing
  2. convert this date-type value to some format (transform the numerical values to text in a specific format) - that's called formatting

Why your attempts didn't work:

  • the first attempt gave you the wrong format because you called Date::toString() method, which produces an output (a text representation) in that format (Sun Apr 08 00:00:00 GMT+00:00 2018) - so the parsing was correct, but the formatting wasn't
  • in the second attempt, you used the output pattern (EE dd MMM yyyy, the one you should use for formatting) to parse the date (which caused the ParseException).

For step 1, you can use a LocalDate, a type that represents a date (day, month and year, without hours and without timezone), because that's what your input is:

String input = "01/04/2018";
DateTimeFormatter inputParser = DateTimeFormatter.ofPattern("dd/MM/yyyy");
// parse the input
LocalDate date = LocalDate.parse(input, inputParser);

That's more reliable than SimpleDateFormat because it solves lots of strange bugs and problems of the old API.

Now that we have our LocalDate object, we can do step 2:

// convert to another format
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EE dd MMM yyyy", Locale.ENGLISH);
String output = date.format(formatter);

Note that I used a java.util.Locale. That's because the output you want has the day of week and month name in English, and if you don't specify a locale, it'll use the JVM's default (and who guarantees it'll always be English? it's better to tell the API which language you're using instead of relying on the default configs, because those can be changed anytime, even by other applications running in the same JVM).

And how do I know which letters must be used in DateTimeFormatter? Well, I've just read the javadoc.

Sophistry answered 9/3, 2018 at 12:38 Comment(3)
Why the downvote, please? This is a very well explained and fully correct answer. While changing to using java.time may not be what the OP asked for (to tell the truth, that’s not clear), it is warranted and may very well in the end be what the OP wants.Fulgent
Finally, an answer regarding dates in Java that actually explains things correctly. Here is a simplified snippet to format the current time in this manner. LocalDateTime now = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formattedDate = now.format(formatter); println("Formatted : " + formattedDate);Dumbhead
In android DateTimeFormatter class is supported from APi level 26 or above.Styria
H
6

Use this date formatter method I have created

    public static String dateFormater(String dateFromJSON, String expectedFormat, String oldFormat) {
    SimpleDateFormat dateFormat = new SimpleDateFormat(oldFormat);
    Date date = null;
    String convertedDate = null;
    try {
        date = dateFormat.parse(dateFromJSON);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(expectedFormat);
        convertedDate = simpleDateFormat.format(date);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return convertedDate;
}

and call this method like

dateFormater(" 01/04/2018" , "EE dd MMM yyyy" , "dd/MM/yyyy") 

and you will get the desired output

Histiocyte answered 9/3, 2018 at 11:11 Comment(1)
FYI, the terribly flawed date-time classes such as java.util.Date, java.util.Calendar, & java.text.SimpleDateFormat are now legacy, supplanted by java.time classes. Most java.time functionality is back-ported to Java 6 & Java 7 in the ThreeTen-Backport project. Further adapted for earlier Android (<26) in ThreeTenABP. See How to use ThreeTenABP….Lauryn
I
2

You need two date formatters here. One to parse the input, and a different formatter to format the output.

SimpleDateFormat inDateFmt = new SimpleDateFormat("dd/MM/yyyy");
SimpleDateFormat outDateFmt = new SimpleDateFormat("EEE dd MMM yyyy");
try {
    Date date = inDateFmt.parse(match.getDate());
    textViewDate.setText(outDateFmt.format(date));
} catch (ParseException ex) {
    System.out.println(ex.toString());
}
Izard answered 9/3, 2018 at 11:15 Comment(0)
P
1

Try with new SimpleDateFormat("EEE dd MMM yyyy", Locale.ENGLISH);

Sample Code:

DateFormat originalFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
DateFormat targetFormat = new SimpleDateFormat("EEE dd MMM yyyy", Locale.ENGLISH);
Date date = originalFormat.parse("01/04/2018");
String formattedDate = targetFormat.format(date);  // Sun 01 Apr 2018
Podophyllin answered 9/3, 2018 at 11:10 Comment(0)
S
1

Try this, you can create any date format you want with this

        public String parseTime(String date){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-dd-MM HH:mm:ss");
        try {
            Date date1 = format.parse(date.replace("T"," "));
            String d= new SimpleDateFormat("yyyy/dd/MM HH:mm:ss").format(date1);
            return d;
        }catch (Exception e){
            e.printStackTrace();
        }
        return "";
    }
Selfgratification answered 9/3, 2018 at 11:13 Comment(1)
Wow. Can't believe the last un-voted answer worked for my use case. Thanks @akshayBloodyminded
L
1

tl;dr

LocalDate
.parse( 
    "01/04/2018"  ,
    DateTimeFormatter            // Parses & generates text in various formats
    .ofPattern( "dd/MM/uuuu" )   // Define a formatting pattern to match your input.
)                                // Returns a `LocalDate` object.
.toString()                      // Generates text in standard ISO 8601 format.

2018-04-01

Use data types appropriately

I have a String in a database (match.getDate) that has the following date format:

Do not store date-time values as text.

You should be storing date-time values in a database using date-time data types. In standard SQL, a date-only value without time-of-day and without time zone is stored in a column of type DATE.

Another problem is that you are trying to represent a date-only value in Java class that represents a moment, a date with time-of-day in context of time zone or offset-from-UTC. Square peg, round hole. Using a date-only data types makes your problems go away.

java.time

The other Answers used outmoded classes, years ago supplanted by the modern java.time classes built into Java 8 and later, and built into Android 26 and later. For earlier Java & Android, see links below.

In Java, a date-only value without time-of-day and without time zone is represented by the LocalDate class.

LocalDate ld = LocalDate.parse( "2020-01-23" ) ;  // Parsing a string in standard ISO 8601 format.

For a custom formatting pattern, use DateTimeFormatter.

String input = "01/04/2018" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) ;
LocalDate ld = LocalDate.parse( input , f ) ;

Generate a string in standard ISO 8601 format.

String output = ld.toString() ;

Generate a string in your custom format.

String output = ld.format( f ) ;

Tip: Use DateTimeFormatter.ofLocalizedDate to automatically localize your output.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

Lauryn answered 8/2, 2020 at 22:17 Comment(0)
R
0

first of check your match.getDate() method which format given date if is given above define format date then used below code and show date in define above format ...

String date="09/03/2018";
    SimpleDateFormat parseDateFormat = new SimpleDateFormat("dd/MM/yyyy"); // if your match.getDate() given this format date.and if is given different format that time define that format.
    DateFormat formatdate = new SimpleDateFormat("EEE dd MMM yyyy");

    try {
        Date date1=parseDateFormat.parse(date);
        Log.d("New Date",formatdate.format(date1));
    } catch (ParseException e) {
        e.printStackTrace();
    }

output:: Fri 09 Mar 2018

Rood answered 9/3, 2018 at 11:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.