I would like my app to insert all day events into the calendar. I started off with the example given at https://developer.android.com/guide/topics/providers/calendar-provider.html. To make it all-day, I add the ALL_DAY
content value and set the time zone to UTC. I end up with the folowing code:
long calID = 3;
long startMillis = 0;
long endMillis = 0;
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 9, 14, 7, 30);
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 9, 14, 8, 45);
endMillis = endTime.getTimeInMillis();
ContentResolver cr = getContentResolver();
values.put(Events.ALL_DAY, 1)
ContentValues values = new ContentValues();
values.put(Events.DTSTART, startMillis);
values.put(Events.DTEND, endMillis);
values.put(Events.TITLE, "Jazzercise");
values.put(Events.DESCRIPTION, "Group workout");
values.put(Events.CALENDAR_ID, calID);
values.put(Events.EVENT_TIMEZONE, "UTC");
Uri uri = cr.insert(Events.CONTENT_URI, values);
Now, this actually does the job but the DTEND
time seems redundant and setting start and end times meaningless when really only the date is needed. When I remove the DTEND
value, I get an exception java.lang.IllegalArgumentException: DTEND and DURATION cannot both be null for an event.
. What would be the proper values? Just arbitrary as above or could/should this actually be done with meaningful information?
DTEND
is not redundant as it specifies the end of the event. all-day doesn't mean that it's just one day long. It could span any number of days. all-day means start and end of the event have no time component. In particular, the event always begins when the day begins, no matter in which time zone you're actually located at that time. A common example is your birthday. You usually celebrate it on a specific calendar day, no matter where exactly you are.
Note that in Android's calendar database DTSTART
and DTEND
should represent midnight of that specific day in UTC.
So a better way of deriving the start and end dates would be:
TimeZone utc = TimeZone.getTimeZone("UTC");
Calendar beginTime = Calendar.getInstance(utc);
// set all values to 0
beginTime.clear();
beginTime.set(2012, 9, 14);
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance(utc);
// the event ends right before the next day begins
endTime.clear();
endTime.set(2012, 9, 15);
endMillis = endTime.getTimeInMillis();
Also note that DTEND
is non-inclusive (it points to the first moment after the event). For a one day all-day event that means, DTEND
is the start of the next day.
Another way of determining the end of the event is by adding the duration of the event to DTSTART
like so:
// Add the duration of 1 day to startMillis to get the end
endMillis = startMillis + TimeUnit.DAYS.toMillis(1);
The result is the same as above.
Be aware that this is how to create non-recurring events. If you create a recurring event you must not set DTEND
but DURATION
.