2

I am using the following lines of code to parse a String as a Date:

String displayBirthday;
...
java.util.Date  ss1=new Date(displayBirthday);
SimpleDateFormat formatter5=new SimpleDateFormat("yyyy-MM-dd");
displayBirthday = formatter5.format(ss1);
li.add(displayBirthday);

It works fine for many dates, but when I want to parse a date like: 0001-03-10

It gives me the following error:

java.lang.IllegalArgumentException: Parse error: 0001-03-10

I am using a prefix of 0001 for dates which dont have a year as an internal representation. How to overcome this?

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
User3
  • 2,465
  • 8
  • 41
  • 84
  • If it is the only case, adding an if condition helps ? – Suresh Atta Aug 01 '14 at 08:51
  • 2
    what is `displayBirthday`? Is is string if yes then don't use deprecated constructor of Date class. – Braj Aug 01 '14 at 08:52
  • Its a string. I could have used if else conditions but the type of date I get is unpredictable. The various formats returned through various API's are different. – User3 Aug 01 '14 at 08:53
  • @user3218114 can you please elaborate more on that? – User3 Aug 01 '14 at 08:53
  • Can you give a link or something? – User3 Aug 01 '14 at 08:54
  • 2
    Please put more effort into formatting your code when you post - you've asked enough questions that you should really know how to format code by now, and it doesn't take long to make it nicer for *everyone* reading the question. – Jon Skeet Aug 01 '14 at 08:54
  • what is the value of `displayBirthday`? is it 0001-03-10? – Ruchira Gayan Ranaweera Aug 01 '14 at 08:54
  • @JonSkeet I will takecare of that in future am Sorry for the inconvenience. – User3 Aug 01 '14 at 08:54
  • 4
    Why are you using the deprecated `Date(String)` constructor at all? Why aren't you using a `SimpleDateFormat` to parse it? If you receive multiple formats, you can try with multiple instances of `SimpleDateFormat`. – Jon Skeet Aug 01 '14 at 08:55
  • isn't minimum year in SimpleDateformat 1970? – nafas Aug 01 '14 at 08:57
  • @nafas - 1970 minimum. Do u have any article as reference? – Pramod S. Nikam Aug 01 '14 at 09:02
  • @Orion I'm sure I've seen this year somewhere, but I don't remember if it was SimpleDateFormat or some other date related classes. – nafas Aug 01 '14 at 09:04
  • 1
    Java 8 offers [more](http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html) like `MonthDay date = MonthDay.of(Month.FEBRUARY, 29);` and thread-safe formatters (which SimpleDateFormat is not). – Joop Eggen Aug 01 '14 at 09:26
  • For new readers to this question: (1) I strongly recommend you don’t use `Date`. That class is poorly designed and long outdated. Instead use `LocalDate`, `MonthDay`, `DateTimeFormatter` and/or `DateTimeFormatterBuilder`, all from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). (2) Even if you insist on `Date`, stay far away from the deprecated string-arg constructor. I know you said *the type of date I get is unpredictable*; but the behaviour of that constructor is at least as unpredictable, so that would be a match made in hell. – Ole V.V. Jan 01 '23 at 14:52

2 Answers2

3

Date(java.lang.String)' is deprecated , just use SimpleDateFormat

Just like follows

   SimpleDateFormat formatter5=new SimpleDateFormat("yyyy-MM-dd");
   String displayBirthday = formatter5.format(formatter5.parse("0001-03-10"));
   System.out.println(displayBirthday);

Out put:

   0001-03-10
Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
  • Parse error at listjava.text.ParseException: Unparseable date: "Aug 24, 1990" (at offset 0) – User3 Aug 01 '14 at 09:18
  • You can't pass `Aug 24, 1990"` with this `SimpleDateFormat`, You need new one. – Ruchira Gayan Ranaweera Aug 01 '14 at 09:22
  • How do I detect the pattern of a Date so that I pass them to different parsers? – User3 Aug 01 '14 at 09:23
  • *How do I detect the pattern of a Date so that I pass them to different parsers?* @User3 See for example [Parse any date in Java](https://stackoverflow.com/questions/3389348/parse-any-date-in-java). This question has been asked and answered a number of times, so search for much more. – Ole V.V. Jan 01 '23 at 14:56
0

java.time

In Mar 2014 (months before the question was posted), the java.util date-time API and their formatting API, SimpleDateFormat were supplanted by the modern date-time API. Since then, it is highly recommended to stop using the legacy date-time API.

Using java.time, the modern date-time API:

You do not need a DateTimeFormatter: java.time API is based on ISO 8601 and therefore you do not need a DateTimeFormatter to parse a date-time string which is already in ISO 8601 format e.g. your date string, 0001-03-10 which can be parsed directly into a LocalDate instance which contains just date units.

Demo:

import java.time.LocalDate;

class Main {
    public static void main(String args[]) {
        String strDateTime = "0001-03-10";
        LocalDate date = LocalDate.parse(strDateTime);
        System.out.println(date);
    }
}

Output:

0001-03-10

ONLINE DEMO

I am using a prefix of 0001 for dates which dont have a year as an internal representation. How to overcome this?

As suggested by Ole V.V., a MonthDay is probably a good answer to it. Note that the default pattern used by MonthDay#parse is --MM-dd. If your string is not in this format, you can build a custom DateTimeFormatter.

An alternative to parsing to MonthDay is building a DateTimeFormatter with default year which will allow your string to be parsed directly into a LocalDate.

Demo:

class Main {
    public static void main(String args[]) {
        // If your string is in --MM-dd format
        MonthDay monthDay = MonthDay.parse("--03-10");
        // If you want the current year, replace 1 with Year.now().getValue()
        LocalDate date = monthDay.atYear(1);
        System.out.println(date);

        // If your string is in MM-dd format
        DateTimeFormatter monthDayFormatter = DateTimeFormatter.ofPattern("MM-dd", Locale.ENGLISH);
        monthDay = MonthDay.parse("03-10", monthDayFormatter);
        // If you want the current year, replace 1 with Year.now().getValue()
        date = monthDay.atYear(1);
        System.out.println(date);

        // An alternative solution
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                .appendPattern("MM-dd")
                // If you want the current year, replace 1 with Year.now().getValue()
                .parseDefaulting(ChronoField.YEAR, 1)
                .toFormatter(Locale.ENGLISH);
        date = LocalDate.parse("03-10", dtf);
        System.out.println(date);
    }
}

Output:

0001-03-10
0001-03-10
0001-03-10

ONLINE DEMO

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • 1
    it’s hard to write a good and complete answer to this question since the comments say that the OP is trying to parse a number of different formats that we don’t know, and also *I am using a prefix of 0001 for dates which dont have a year as an internal representation. How to overcome this?* A `MonthDay` is probably a good answer to the latter. Under all circumstances you have set the basics straight, which cannot but be helpful. – Ole V.V. Jan 01 '23 at 13:06
  • Thanks, @OleV.V. for your encouraging words and valuable feedback. I had missed the requirement, *I am using a prefix of 0001 for dates which don't have a year as an internal representation. How to overcome this?*. Based on your suggestion, I have extended my answer to address this requirement. – Arvind Kumar Avinash Jan 01 '23 at 14:00
  • 1
    Nice. Can I upvote again? ;-) If the format is `0001-03-10`, you don’t need a custom formatter. You just need to detect whether the prefix is `0001` (use `"0001-03-10".startsWith("0001")`). Then `MonthDay.parse("0001-03-10", DateTimeFormatter.ISO_LOCAL_DATE)` yields `--03-10`. – Ole V.V. Jan 01 '23 at 14:05
  • Thanks again, @OleV.V. I learned this new technique today and I find it very useful e.g. using this technique, one can do something like `LocalDate.parse("2023-01-01T10:20:30", DateTimeFormatter.ISO_LOCAL_DATE_TIME)`. Since I have already used `LocalDate.parse("0001-03-10")` in my original answer, I leave the answer in its current state. I will figure out how I let others know about this new technique that I have learnt from you. – Arvind Kumar Avinash Jan 01 '23 at 14:22
  • 1
    I understand that you didn’t learn before since I would normally recommend against it. I prefer parsing all information from the string even if on short sight I only need some of it. Only in this case where we already know that the `0001` is a dumb marker that does not signify a real year, I am happy with ignoring it already in parsing. – Ole V.V. Jan 01 '23 at 14:35