/// <summary> /// Returns the value of the requested column as a DateTime /// </summary> /// <returns>The DateTime.</returns> /// <param name="cursor">Cursor.</param> /// <param name="column">Column name.</param> /// <param name="allDay">Whether the event is all-day</param> public static DateTime GetDateTime(this ICursor cursor, string column, bool allDay) { var ms = cursor.GetLong(cursor.GetColumnIndex(column)); var dt = DateConversions.GetDateFromAndroidMS(ms); // All day events should not be affected by time zones, so we simply take the // UTC time and treat it as local (e.g., Christmas doesn't start on the 24th in California...) // return(allDay ? DateTime.SpecifyKind(dt.ToUniversalTime(), DateTimeKind.Local) : dt.ToLocalTime()); }
/// <summary> /// Add new event to a calendar or update an existing event. /// If a new event was added, the ExternalID property will be set on the CalendarEvent object, /// to support future queries/updates. /// </summary> /// <param name="calendar">Destination calendar</param> /// <param name="calendarEvent">Event to add or update</param> /// <exception cref="ArgumentException">Calendar is not specified, does not exist on device, or is read-only</exception> /// <exception cref="UnauthorizedAccessException">Calendar access denied</exception> /// <exception cref="InvalidOperationException">Editing recurring events is not supported</exception> /// <exception cref="Plugin.Calendars.Abstractions.PlatformException">Unexpected platform-specific error</exception> public static async Task AddOrUpdateEventAsync(Calendar calendar, CalendarEvent calendarEvent) { if (string.IsNullOrEmpty(calendar.ExternalID)) { throw new ArgumentException("Missing calendar identifier", nameof(calendar)); } else { // Verify calendar exists (Android actually allows using a nonexistent calendar ID...) // var deviceCalendar = await GetCalendarByIdAsync(calendar.ExternalID).ConfigureAwait(false); if (deviceCalendar == null) { throw new ArgumentException("Specified calendar not found on device"); } } // Validate times if (calendarEvent.End < calendarEvent.Start) { throw new ArgumentException("End time may not precede start time", nameof(calendarEvent)); } bool updateExisting = false; long existingId = -1; CalendarEvent existingEvent = null; await Task.Run(() => { if (long.TryParse(calendarEvent.ExternalID, out existingId)) { if (IsEventRecurring(calendarEvent.ExternalID)) { throw new InvalidOperationException("Editing recurring events is not supported"); } var calendarId = GetCalendarIdForEventId(calendarEvent.ExternalID); if (calendarId.HasValue && calendarId.Value.ToString() == calendar.ExternalID) { updateExisting = true; existingEvent = GetEventById(calendarEvent.ExternalID); } } bool allDay = calendarEvent.AllDay; var start = allDay ? DateTime.SpecifyKind(calendarEvent.Start.Date, DateTimeKind.Utc) : calendarEvent.Start; var end = allDay ? DateTime.SpecifyKind(calendarEvent.End.Date, DateTimeKind.Utc) : calendarEvent.End; var eventValues = new ContentValues(); eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId, calendar.ExternalID); eventValues.Put(CalendarContract.Events.InterfaceConsts.Title, calendarEvent.Title); eventValues.Put(CalendarContract.Events.InterfaceConsts.Description, calendarEvent.Description); eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart, DateConversions.GetDateAsAndroidMS(start)); eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend, DateConversions.GetDateAsAndroidMS(end)); eventValues.Put(CalendarContract.Events.InterfaceConsts.AllDay, allDay ? 1 : 0); eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation, calendarEvent.Location ?? string.Empty); try { if (!string.IsNullOrEmpty(calendarEvent.EventColorString) && calendarEvent.EventColor.A > 0) { eventValues.Put(CalendarContract.Events.InterfaceConsts.EventColor, calendarEvent.EventColor.ToAndroid()); } } catch { } // If we're updating an existing event, don't mess with the existing // time zone (since we don't support explicitly setting it yet). // *Unless* we're toggling the "all day" setting // (because that would mean the time zone is UTC rather than local...). // if (!updateExisting || allDay != existingEvent?.AllDay) { eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone, allDay ? Java.Util.TimeZone.GetTimeZone("UTC")?.ID ?? string.Empty : Java.Util.TimeZone.Default.ID); } var operations = new List <ContentProviderOperation>(); var eventOperation = updateExisting ? ContentProviderOperation.NewUpdate(ContentUris.WithAppendedId(_eventsUri, existingId)) : ContentProviderOperation.NewInsert(_eventsUri); eventOperation = eventOperation.WithValues(eventValues); operations.Add(eventOperation.Build()); operations.AddRange(BuildReminderUpdateOperations(calendarEvent.Reminders, existingEvent)); try { var results = ApplyBatch(operations); if (!updateExisting) { calendarEvent.ExternalID = results[0].Uri.LastPathSegment; } } catch (Exception ex) { ex.ToString(); } }).ConfigureAwait(false); }
/// <summary> /// Gets all events for a calendar within the specified time range. /// </summary> /// <param name="calendar">Calendar containing events</param> /// <param name="start">Start of event range</param> /// <param name="end">End of event range</param> /// <returns>Calendar events</returns> /// <exception cref="ArgumentException">Calendar does not exist on device</exception> /// <exception cref="UnauthorizedAccessException">Calendar access denied</exception> /// <exception cref="Plugin.Calendars.Abstractions.PlatformException">Unexpected platform-specific error</exception> public static async Task <IList <CalendarEvent> > GetEventsAsync(Calendar calendar, DateTime start, DateTime end) { try { var deviceCalendar = await GetCalendarByIdAsync(calendar.ExternalID).ConfigureAwait(false); if (deviceCalendar == null) { throw new ArgumentException("Specified calendar not found on device"); } var eventsUriBuilder = CalendarContract.Instances.ContentUri.BuildUpon(); // Note that this is slightly different from the GetEventById projection // due to the Instances API vs. Event API (specifically, IDs and start/end times) // string[] eventsProjection = { CalendarContract.Instances.EventId, CalendarContract.Events.InterfaceConsts.Title, CalendarContract.Events.InterfaceConsts.DisplayColor, CalendarContract.Events.InterfaceConsts.EventColor, CalendarContract.Events.InterfaceConsts.Description, CalendarContract.Instances.Begin, CalendarContract.Instances.End, CalendarContract.Events.InterfaceConsts.AllDay, CalendarContract.Events.InterfaceConsts.EventLocation }; ContentUris.AppendId(eventsUriBuilder, DateConversions.GetDateAsAndroidMS(start)); ContentUris.AppendId(eventsUriBuilder, DateConversions.GetDateAsAndroidMS(end)); var eventsUri = eventsUriBuilder.Build(); return(await Task.Run(() => { try { var cursor = Query(eventsUri, eventsProjection, string.Format("{0} = {1}", CalendarContract.Events.InterfaceConsts.CalendarId, calendar.ExternalID), null, CalendarContract.Events.InterfaceConsts.Dtstart + " ASC"); var events = IterateCursor(cursor, () => { try { bool allDay = cursor.GetBoolean(CalendarContract.Events.InterfaceConsts.AllDay); var calendarEvent = new CalendarEvent { ExternalID = cursor.GetString(CalendarContract.Instances.EventId), CalendarId = calendar.ExternalID, Title = cursor.GetString(CalendarContract.Events.InterfaceConsts.Title), DisplayColorString = string.Format("#{0:x8}", cursor.GetInt(CalendarContract.Events.InterfaceConsts.DisplayColor)), EventColorString = string.Format("#{0:x8}", cursor.GetInt(CalendarContract.Events.InterfaceConsts.EventColor)), Description = cursor.GetString(CalendarContract.Events.InterfaceConsts.Description), Start = cursor.GetDateTime(CalendarContract.Instances.Begin, allDay), End = cursor.GetDateTime(CalendarContract.Instances.End, allDay), Location = cursor.GetString(CalendarContract.Events.InterfaceConsts.EventLocation), //AccessLevel = cursor.GetInt(CalendarContract.Events.InterfaceConsts.AccessLevel), //tmp = cursor.GetString(CalendarContract.Events.InterfaceConsts.HasExtendedProperties), int mit Count? //tmp = "1" + cursor.GetString(CalendarContract.Events.InterfaceConsts.IsPrimary), AllDay = allDay }; //calendarEvent.Reminders = GetEventReminders(calendarEvent.ExternalID); => Dauert zu lange! return calendarEvent; } catch (Exception ex) { sys.LogException(ex); int rnd = new Random().Next(8); return new CalendarEvent() { Start = DateTime.Today.AddHours(10 + rnd), End = DateTime.Today.AddHours(11 + rnd), Title = ex.Message }; } }); return events; } catch (Exception ex) { sys.LogException(ex); return null; } }).ConfigureAwait(false)); } catch (Exception ex) { sys.LogException(ex); return(null); } }