Microsoft Graphを使ってクラウド上のカレンダーの操作を行うための方法を説明します。ここではカレンダーにイベントを新規作成する処理をユーティリティー的に使えるように静的メソッドとして実装した例をお示ししています。
なお、UWPアプリにおけるユーザー認証については以下の記事をご覧ください。
動作確認環境
- Microsoft.Graph 3.28.0
CreateEventAsyncメソッドを作成する
CreateEventAsyncメソッド (CalendarHelperクラス)
public static async Task<Event> CreateEventAsync(Event newEvent, string calendarId = null)
{
Event createdEvent = null;
try
{
GraphServiceClient graphClient = await AuthenticationHelper.GetAuthenticatedClientAsync();
if (calendarId == null)
{
createdEvent = await graphClient.Me.Calendar.Events.Request().AddAsync(newEvent);
}
else
{
createdEvent = await graphClient.Me.Calendars[calendarId].Events.Request().AddAsync(newEvent);
}
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
return createdEvent;
}
AuthenticationHelperについては以下の記事をご覧ください。
※ APIのアクセス許可スコープに「Calendars.ReadWrite」を追加しておく必要があります。
まず、7行目でユーザー認証を行いGraphServiceClientインスタンスを取得しています。ここで、カレンダーIDが指定されている場合はそのカレンダーに対して、指定されていない場合はデフォルトカレンダーにイベントを追加するので、カレンダーIDの指定の有無で場合分けして考えてみましょう(9-16行目)。
カレンダーIDを指定していない場合はデフォルトカレンダーにイベントを追加するので、11行目でMe、Calendar、Eventsの3つのRequestBuilderからリクエストを構築し、Requestメソッドで完成させましょう(ICalendarEventsCollectionRequest)。リクエストのAddAsyncメソッドの引数にカレンダーに追加するEvent型のインスタンスを指定して、そのイベントを追加します。
await graphClient.Me.Calendar.Events.Request().AddAsync(newEvent);
カレンダーIDをしてしている場合は、15行目でMe、Calendars、Eventsの3つのRequestBuilderからリクエストを構築します(ICalendarEventsCollectionRequest)。この時、CalendarsはIUserCalendarsCollectionRequestBuilder型なので、インデクサでカレンダーIDを指定しましょう。あとはカレンダーIDを指定してない場合と同様です。
await graphClient.Me.Calendars[calendarId].Events.Request().AddAsync(newEvent);
この時、戻り値としては実際に作成されたEvent型のインスタンスが返されます。この戻り値として返されるEvent型のインスタンスは、引数として指定されたインスタンスにイベントIDなどのクラウド側で自動的に付与される情報が付け加えられたインスタンスとなります。
なお、新たなイベントの作成方法は以下のドキュメントもご覧ください。
新しいイベントの基本的な作成方法
イベント名だけで作成する
それでは、試しに「新しいイベント」というイベントをデフォルトカレンダーに追加してみましょう。イベントにタイトルだけ指定して作成すると、現在時刻に近い次のキリのいい時刻(30分単位)に30分のイベントが作成されます。
var ev = new Event { Subject = "新しいイベント" };
var createdEvent = await CalendarHelper.CreateEventAsync(ev);
このようにイベント作成の際に指定するEvent型のインスタンスは最低限の情報を指定していればよく、必要な情報はクラウド側で自動的に付与されます。
開始時刻・終了時刻を指定して作成する
次に開始時刻・終了時刻を指定してイベントを作成しましょう。現在時刻から開始して3時間後に終了する「新しいイベント」という名前のイベントを作成しています。ここで、Microsoft Graphでは内部的にはタイムゾーンをすべてUTCに変換して扱われるので、ToUniversalTimeメソッドでUTCに変換しています。さらに、日時はISO8601形式で指定する必要があるので、DateTimeTimeZoneクラスのFromDateTimeメソッドで変換しています。
var ev = new Event {
Subject = "新しいイベント",
Start = new DateTimeTimeZone
{
DateTime = DateTimeTimeZone.FromDateTime(DateTime.Now.ToUniversalTime()).DateTime,
TimeZone = "UTC"
},
End = new DateTimeTimeZone
{
DateTime = DateTimeTimeZone.FromDateTime(DateTime.Now.AddHours(3).ToUniversalTime()).DateTime,
TimeZone = "UTC"
}
};
var createdEvent = await CalendarHelper.CreateEventAsync(ev);
なお、実際にはToUniversalTimeメソッドでUTCに変換しなくても、指定された日時のタイムゾーンに従って自動的にUTCに変換されます。またこの時、コード上で指定するタイムゾーンよりもISO8601形式の日時に含まれているタイムゾーンが優先されるようです。
終日イベントを作成する
最後にまる1日の終日イベントを作成しましょう。終日イベントではIsAllDayプロパティをtrueに設定しましょう。この時、開始時刻・終了時刻はUTCに変換したときに0時から始まって0時に終わるように指定する必要があります。
ここでは今日1日の終日イベントを「新しい終日イベント」という名前で作成しています。今日の日付をDateTime型のTodayプロパティで取得しそれをUTCに書き換えます。ここで現地時刻からUTCに書き換えるときに、ToUniversalTimeメソッドを用いてしまうとタイムゾーンの時差分だけ元のDateTime型の時刻も変わってしまうので、日時を変えずにタイムゾーンの指定だけを変えるSpecifyKindメソッドを用いています。
var ev = new Event
{
Subject = "新しい終日イベント",
Start = new DateTimeTimeZone
{
DateTime = DateTimeTimeZone.FromDateTime(DateTime.SpecifyKind(DateTime.Today, DateTimeKind.Utc)).DateTime,
TimeZone = "UTC"
},
End = new DateTimeTimeZone
{
DateTime = DateTimeTimeZone.FromDateTime(DateTime.SpecifyKind(DateTime.Today.AddDays(1), DateTimeKind.Utc)).DateTime,
TimeZone = "UTC"
},
IsAllDay = true
};
var createdEvent = await CalendarHelper.CreateEventAsync(ev);
ここで、タイムゾーンを変更するときの終日イベントの挙動は他の時間イベントと異なっているので注意が必要です。
開始時刻と終了時刻とが決まっているイベントはタイムゾーンを移動すると、そのタイムゾーンの差だけ開始時刻と終了時刻とが移動されて表示されますが、終日イベントで同じことをやってしまうと、UTCでは終日イベントだったのに現地時間では終日イベントではなくなってしまうということが起きてしまいます。例えばUTCで「2021/4/10 00:00 ~ 2021/4/11 00:00」と定義された終日イベントについて、日本時間のタイムゾーンに合わせて開始時刻と終了時刻とを変更してしまうと、「2021/4/10 09:00 ~ 2021/4/11 09:00」という風にただ単に9時から始まって翌日の9時に終わる普通のイベントになってしまいます。
このようなことを避けるために、終日イベントはタイムゾーンによらずUTCにおける開始時刻・終了時刻が優先されるということになっています。これによって、どこのタイムゾーンに行ってもカレンダーの終日イベントは終日イベントのままでいられるというわけです。
コメント