Search code examples
androidexceptioncalendarnumberformatexception

NumberFormatException Invalid Long with Calendar


I am having problems with this NumberFormatException Invalid Long. The log cat is showing that the error is coming from the Long.parseLong part of the method.

  public static String getDateTimeStr(String p_time_in_millis) {
    SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
    Date l_time = new Date(Long.parseLong(p_time_in_millis));
    return sdf.format(l_time);
}

Can someone tell me why this code works fine when I fetch and display the data in certain calendars then in other calendars on my device I get this NumberFormatException Invalid Long please?

Edit: Here is the rest of the code…

private void getEvents() {

    Uri l_eventUri;
    ArrayList<Map<String, String>> allStudents = new ArrayList<Map<String, String>>();

    if (Build.VERSION.SDK_INT >= 8) {
        l_eventUri = Uri.parse("content://com.android.calendar/events");
    } else {
        l_eventUri = Uri.parse("content://calendar/events");
    }

    String[] l_projection = new String[]{"title", "dtstart", "dtend"};

    @SuppressWarnings("deprecation")
    Cursor l_managedCursor = this.managedQuery(l_eventUri, l_projection, "calendar_id=" + m_selectedCalendarId, null, "dtstart DESC, dtend DESC");

    if (l_managedCursor.moveToFirst()) {


        int l_colTitle = l_managedCursor.getColumnIndex(l_projection[0]);
        int l_colBegin = l_managedCursor.getColumnIndex(l_projection[1]);
        int l_colEnd = l_managedCursor.getColumnIndex(l_projection[2]);

        String l_title = String.valueOf(l_colTitle);
        String l_begin = Integer.toString(l_colBegin);
        String l_end = Integer.toString(l_colEnd);

        do {

            Map<String, String> map = new HashMap<String, String>();    

            l_title = l_managedCursor.getString(l_colTitle);
            l_begin = getDateTimeStr(l_managedCursor.getString(l_colBegin));
            l_end = getDateTimeStr(l_managedCursor.getString(l_colEnd));

            map.put("eventTitles", l_title);
            map.put("event_begin", l_begin);
            map.put("event_end", l_end);
            allStudents.add(map);


        } while (l_managedCursor.moveToNext());

        l_managedCursor.close();

        SimpleAdapter adapter = new SimpleAdapter(this, allStudents, R.layout.notice_layout, new String[] { "eventTitles", "event_begin", "event_end" }, new int[] { R.id.tvTitle, R.id.tvBody, R.id.tvTeacherCode}); 
        listViewCalendar.setAdapter(adapter);

    }


}

Edit 2:

For some reason the code works fine without this line of code so I've nailed it down to this line of code.

l_end = getDateTimeStr(l_managedCursor.getString(l_colEnd));

Why does the l_colEnd get caught up in an NumberFormatExcetion? When the following line of code could be also caught up in the same NumberFormatException because it is enquiring about the same int format?

l_begin = getDateTimeStr(l_managedCursor.getString(l_colBegin));

Thank you too all who have helped. The other interesting thing also is when I add this

int l_cnt = 0;
do {
   ++l_cnt;
} while (l_managedCursor.moveToNext() && l_cnt < 100);

to the while clause as shown below at the end of the following code the app works fine with no lines of code throwing a NumberFormatException..

if (l_managedCursor.moveToFirst()) {

        int l_cnt = 0;

        int l_colTitle = l_managedCursor.getColumnIndex(l_projection[0]);
        int l_colBegin = l_managedCursor.getColumnIndex(l_projection[1]);
        int l_colEnd = l_managedCursor.getColumnIndex(l_projection[2]);

        String l_title = String.valueOf(l_colTitle);
        String l_begin = Integer.toString(l_colBegin);
        String l_end = Integer.toString(l_colEnd);

        do {

            Map<String, String> map = new HashMap<String, String>();    

            l_title = l_managedCursor.getString(l_colTitle);
            l_begin = getDateTimeStr(l_managedCursor.getString(l_colBegin));
            l_end = getDateTimeStr(l_managedCursor.getString(l_colEnd));

            map.put("eventTitles", l_title);
            map.put("event_begin", l_begin);
            map.put("event_end", l_end);
            allStudents.add(map);

            ++l_cnt;

        } while (l_managedCursor.moveToNext() && l_cnt < 100);

Solution

  • Can someone tell me why this code works fine when I fetch and display the data in certain calendars then in other calendars on my device I get this NumberFormatException Invalid Long please?

    Date l_time = new Date(Long.parseLong(p_time_in_millis));

    IMO. This code is "bad" code.

    Why? You try to fetch unknown data from unchecked sources

    "content://com.android.calendar/events" and "content://calendar/events"

    Almost everybody can access calendars and save whatever he like... Sadly there is no rule there for using this! So making a wild guess an app is using this event column to save data in another that your expected format.

    Regarding the check l_cnt < 100, where fail stops

    It's not failing because the error happens to 101 event or later!


    My solution would to check my data, and never trust that other apps will act as I expected or as they should.

    So I suggest to change getDateTimeStr method as follows:

       public static String getDateTimeStr(String p_time_in_millis) {
          SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
          long timestamp = 0;
          try {
             timestamp = Long.parseLong(p_time_in_millis)
          } catch(NumberFormatException e) {
             Log.w("getDateTimeStr", "Cannot convert '"+p_time_in_millis+"' to long");
             e.printStackTrace(); // Prints full error exception
          }
          Date l_time = new Date(timestamp);
          return sdf.format(l_time);
       }
    

    Remove the l_cnt < 100 check and leave the code to run checking your logcat! You will now have a better overview of what is happening and also your bad data dates will be 1/1/1970 (due to 0 timestamp) code can be changed responsively in order to handle that dates which does not have the expected format.

    Some ideas for handling errors:

    • Make getDateTimeStr throw an exception to the getEvents() which could catch it and ignore the event with the unexpected data. (Handling logic, ignoring what I cannot understand.)
    • Recognize the format of the p_time_in_millis in each different case and use different DATE_TIME_FORMAT types regarding the exact format of each event. Okey, that's needs a lot of investigation and still can fail. Also you have to add the case that the format is still unknown so maybe ignore it or use a default value in order not to crash.

    Generally, you always try to write a stable app that will not fail if another app saves data in a different format (because it like so or due to its own bug)