0

I have a text file from which I am reading and setting transaction POJO class data, to get the difference between start and end time I need to parse the time information in date object.

DateFormat format = new SimpleDateFormat(dateFormat);
System.out.println("Date format in play:"+dateFormat);
Transaction transaction = storageRepositroy.getTransaction(key);
Date start = format.parse(transaction.getStartDate() + " " + transaction.getStartTime());//line no. 29
Date end = format.parse(transaction.getEndDate() + " " + transaction.getEndTime());

I am getting exception while running this code

Exception is

Date format in play:yyyy-MM-dd hh:mm a
java.text.ParseException: Unparseable date: "2020–03–01 03:15 PM"
    at java.text.DateFormat.parse(DateFormat.java:366)
    at dc.tech.transaction.util.TimeUtil.calculateAverageTime(TimeUtil.java:29)

yyyy-MM-dd hh:mm a is the date format which I am passing to SimleDateFormat constructor. I am unable to understand and debug why I am getting this error.

halfer
  • 19,824
  • 17
  • 99
  • 186
Rishi
  • 1,646
  • 2
  • 15
  • 34
  • 2
    I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `LocalDateTime` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Nov 01 '20 at 17:14
  • 2
    you have hyphen character issue in your file, if you manually type the hyphen for test your code works – Ajeetkumar Nov 01 '20 at 17:22
  • 3
    both of them are other characters. hyphen should have ascii 45 but your character gives ascii 8211. hyphen in 2020–03–01 . notice here only – and - – Ajeetkumar Nov 01 '20 at 18:15
  • Quick and dirty approach would be to use "yyyy–MM–dd hh:mm a" as dateFormat since your data itself has hyphen as – – Ajeetkumar Nov 01 '20 at 18:20
  • 1
    I didn’t downvote (I did the opposite). Your code example is not complete/self-contained, and you may improve your question by [providing one that is](https://stackoverflow.com/help/minimal-reproducible-example). It was good enough that @Ajeetkumar was able to spot what was wrong, though. – Ole V.V. Nov 01 '20 at 20:03

2 Answers2

3

java.time

I recommend that you use java.time, the modern Java date and time API, for your date and time work.

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu\u2013MM\u2013dd");
    DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH);
    
    String dateString = "2020–03–01";
    String timeString = "03:15 PM";
    
    LocalDate date = LocalDate.parse(dateString, dateFormatter);
    LocalTime time = LocalTime.parse(timeString, timeFormatter);
    LocalDateTime dateTime = date.atTime(time);
    
    System.out.println(dateTime);

Output:

2020-03-01T15:15

With java.time it is straightforward to combine date and time after parsing, so I prefer to parse them individually.

What went wrong in your code?

Credits go to Ajeetkumar for noticing and reporting in comments: The hyphen in your date string is not a usual minus sign or hyphen with character value 2D hexadecimal (45 decimal), but a en dash with character value 2013 hexadecimal (8211 decimal). So when you specify a usual hyphen in your format pattern string, they don’t match, and parsing fails. Instead I am using a Unicode escape for putting the en dash into the format pattern string. Simply pasting it in there would have worked too (provided that you save your .java file with a character encoding that supports it), but I wanted to make the reader aware that something special was going on here, so I preferred the Unicode escape with \u.

There is another problem with your code: You are not providing any locale for your formatter. So it uses the default locale of your JVM. As long as that locale expects PM, parsing will work. If one day you change your locale setting or run your code on a computer or JVM with a different default locale, parsing will suddenly fail, at you may have a hard time figuring out why. I have specified English locale for parsing the time. Some would prefer doing it for the date too even though technically it isn’t necessary.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
2

I always stick to this mantra: use exactly the same format as your date-time string.

In the solutions given below, I have copied your date-time string into the pattern that I've specified for SimpleDateFormat and DateTimeFormatter and replaced the numbers with the corresponding letters e.g. 2020 with yyyy while keeping the rest of things (symbols, space etc.) intact.

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

public class Main {
    public static void main(String[] args) throws ParseException {
        DateFormat sdf = new SimpleDateFormat("yyyy–MM–dd hh:mm a", Locale.ENGLISH);// Make sure to use Locale
        String dateTimeString = "2020–03–01 03:15 PM";// The string copied from the exception you have got
        Date date = sdf.parse(dateTimeString);
        System.out.println(sdf.format(date));
    }
}

Output:

2020–03–01 03:15 PM

Note: The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. I suggest you should stop using them completely and switch to the modern date-time API.

Using the modern date-time API:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy–MM–dd hh:mm a", Locale.ENGLISH);// Make sure to use Locale
        String dateTimeString = "2020–03–01 03:15 PM";// The string copied from the exception you have got
        System.out.println(LocalDateTime.parse(dateTimeString, dtf));
    }
}

Output:

2020-03-01T15:15

Learn more about the modern date-time API at Trail: Date Time.

If you are doing it for your Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110