Shreya Bhat
Shreya Bhat

Reputation: 341

Parsing a string to date format in java defaults date to 1 and month to January

I am trying to accept a user input of date in the format like : "2000 hrs, Thursday, July 20, 2015". I will then convert this to a date format to do operations on it. But the convertion from string to date is defaulting month to January and date to 1. Here is the code snippet :

    String userDateFormat = "HHmm 'hrs', EEEE, MMMM dd, YYYY";
    SimpleDateFormat userDateFormatter = new SimpleDateFormat(userDateFormat);
    String reference_date = "2000 hrs, Thursday, July 20, 2015";

    Date date = null;
    try {
        date = userDateFormatter.parse(reference_date);
    } catch (ParseException e) {
        System.out.println("Date must be in the format " + userDateFormat);
    }

    System.out.println(userDateFormatter.format(date));

The following method block prints : 2000 hrs, Thursday, January 01, 2015. Any clue why?

Upvotes: 2

Views: 2599

Answers (2)

Anonymous
Anonymous

Reputation: 86276

java.time

    DateTimeFormatter userDateTimeFormatter
            = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH);
    String referenceDate = "2000 hrs, Monday, July 20, 2015";
    LocalDateTime dateTime = LocalDateTime.parse(referenceDate, userDateTimeFormatter);
    System.out.println(dateTime.format(userDateTimeFormatter));

Output is:

2000 hrs, Monday, July 20, 2015

The answer by Elliott Frisch is correct. I am contributing the modern answer using java.time, the modern Java date and time API. When this question was asked, it had been out for one and a half years. Now it’s four years old and widespread. I am furthermore giving an explicit locale. Your date-time is in English, and while your default locale probably is too, code that relies on that will break if one day you run it on a computer in a different locale or you just change your own locale setting.

You’re far from the only one making the mistake of using incorrect case in a format pattern string. Questions about this are being asked on Stack Overflow all the time. SimpleDateFormat is renowned for acting up: it gives you an incorrect result and pretends all is fine, where you would really have expected it to notify you that something was wrong, for example by throwing an exception.

The modern API does throw an exception when you give it incorrect input that it can detect. For example:

    DateTimeFormatter userDateTimeFormatter
            = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, YYYY", Locale.ENGLISH);
    String referenceDate = "2000 hrs, Thursday, July 20, 2015";

Result:

java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {MonthOfYear=7, DayOfWeek=4, WeekBasedYear[WeekFields[SUNDAY,1]]=2015, DayOfMonth=20},ISO resolved to 20:00 of type java.time.format.Parsed

It’s not very readable. The thing to notice is “WeekBasedYear”. A week-based year is only useful with a week number, so it’s wrong here. And the docs will tell you that it was uppercase YYYY that gave you this. Let’s fix:

    DateTimeFormatter userDateTimeFormatter
            = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH);

With DateTimeFormatter it’s customary to use uuuu for year. yyyy works too for years after year 0. We’re not done, though:

java.time.DateTimeException: Conflict found: Field DayOfWeek 1 differs from DayOfWeek 4 derived from 2015-07-20

The modern API also refuses to accept an incorrect day of week, so you get full validation of your date (there’s a trick to persuade it, though, if you don’t want this validation). As Elliott Frisch already said, July 20, 2015, was a Monday (day 1 of the week), not a Thursday. In my first snippet above I have also fixed this error, so that works.

Link: Oracle tutorial: Date Time explaining how to use java.time.

Upvotes: 3

Elliott Frisch
Elliott Frisch

Reputation: 201447

Because you used YYYY when you needed yyyy and July 20, 2015 was a Monday. You wanted something like

String userDateFormat = "HHmm 'hrs', EEEE, MMMM dd, yyyy";
SimpleDateFormat userDateFormatter = new SimpleDateFormat(
        userDateFormat);
String reference_date = "2000 hrs, Monday, July 20, 2015";

which then outputs

2000 hrs, Monday, July 20, 2015

Then SimpleDateFormat Javadoc says (in part)

Letter    Date or Time Component  Presentation    Examples
G         Era designator          Text            AD
y         Year                    Year            1996; 96
Y         Week year               Year            2009; 09

Upvotes: 5

Related Questions