Question

I am querying the ContactsContract.Data.CONTENT_URI with the following arguments, in order to get all of the device contacts' birthdays

 final static Uri CONTENT_URI =
                ContactsContract.Data.CONTENT_URI;
    String SELECTION_ARGS = new String[] {
                        ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE,
                        String.valueOf(ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY)
                };
     String SELECTION =
                    ContactsContract.Data.MIMETYPE + " = ? AND "
                            + ContactsContract.CommonDataKinds.Event.TYPE + " = ? AND "
                            + ContactsContract.CommonDataKinds.Event.START_DATE + " NOT NULL";
String[] PROJECTION = {
            Data._ID,
            Data.CONTACT_ID,
            Data.LOOKUP_KEY,
            Utils.hasHoneycomb() ? Data.DISPLAY_NAME_PRIMARY : Data.DISPLAY_NAME,
            Utils.hasHoneycomb() ? Data.PHOTO_THUMBNAIL_URI : Data.CONTACT_ID,
            ContactsContract.CommonDataKinds.Event.START_DATE,
            SORT_ORDER,
    };
cur = getContext().getContentResolver().query(CONTENT_URI ,
                ContactsQuery.PROJECTION,
                SELECTION,
                SELECTION_ARGS,
                SORT_ORDER);

problem is that the START_DATE field might have different formatting in some cases. Some of the values returned are:

 1990-08-11
 --08-13
 Jan 1, 1970

For some reason, all contacts fetched from Skype seems to be have their birthdays set to Jan 1, 1970.

Currently, I am parsing the dates like this:

    private final static SimpleDateFormat yearFull = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
    private final static SimpleDateFormat yearLess = new SimpleDateFormat("--MM-dd", Locale.US);
    Calendar signCal = Calendar.getInstance();
    Date date = null;

    try {
        date = yearFull.parse(birthday);
    } catch (ParseException e) {
        // e.printStackTrace();
        Log.w(TAG, "No year in " + birthday);
        // throw new IllegalArgumentException("Error parsing " + birthday);
        try {
            date = yearLess.parse(birthday);
        } catch (ParseException e1) {
            Log.e(TAG, "Couldn't parse yearLess " + birthday);
            e1.printStackTrace();
        }
    }
    signCal.setTime(date);

but it misses the Jan 1, 1970 case.

How many different formats are there? What is the best practice to use the START_DATE value of the Contacts table?

Is it possible to have a piece of code that handles all formats?

Was it helpful?

Solution

I don't think it's possible to parse any kind of date without specifying its format first but a good idea to make your parsing more extensible, would be to create an array or list of SimpleDateFormat objects and iterate all of them, until one of them parses the string successfully.

In your case:

private final static SimpleDateFormat[] formats = new SimpleDateFormat[] {
    new SimpleDateFormat("yyyy-MM-dd", Locale.US),
    new SimpleDateFormat("--MM-dd", Locale.US)
};

Calendar signCal = Calendar.getInstance();

boolean dateParsedSuccessfully = false;

for(SimpleDateFormat format : formats) {

    try {

        signCal.setTime(format.parse(birthday));

        dateParsedSuccessfully = true;

        break;

    } catch (ParseException e) {

    }
}

if(!dateParsedSuccessfully) {
    throw new SomeKindOfException("Can't parse birthdate");
}

So each time you want to add a new date format you have just to add a new object to the array.

Keep in mind that the "Jan 1, 1970" format is the default format of Date#toString, it's not necessarily the format used by Skype.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top