ユーザーが最適なハイキング ルートを見つけるのに役立つアプリを考えてみましょう。ハイキングの予定をカレンダーの予定として追加すると、ユーザーは自動的に整理された状態を維持できます。Google カレンダーで予定を共有し、リマインダーを設定しておけば、ストレスなく準備できます。また、Google サービスがシームレスに統合されているため、Google Now から出発時刻が通知され、Google マップで会議の場所まで時間どおりに案内されます。
この記事では、カレンダーの予定を作成してユーザーのカレンダーに追加する方法について説明します。
イベントの追加
イベントを作成するには、少なくとも次のパラメータを指定して events.insert() メソッドを呼び出します。
calendarIdはカレンダーの識別子です。予定を作成するカレンダーのメールアドレスか、ログインしているユーザーのメインのカレンダーを使用する特別なキーワード'primary'のいずれかになります。使用するカレンダーのメールアドレスがわからない場合は、Google カレンダーのウェブ UI のカレンダー設定([カレンダー アドレス] セクション)で確認するか、calendarList.list()呼び出しの結果で確認します。eventは、開始と終了など、必要な詳細をすべて含めて作成するイベントです。必須フィールドはstartとendの 2 つのみです。イベント フィールドの完全なセットについては、eventリファレンスをご覧ください。
イベントを正常に作成するには、次の操作を行う必要があります。
- ユーザーのカレンダーに対する編集アクセス権を取得できるように、OAuth スコープを 
https://www.googleapis.com/auth/calendarに設定します。 - 認証されたユーザーが、指定した 
calendarIdを使用してカレンダーに書き込みアクセスできることを確認します(たとえば、calendarIdのcalendarList.get()を呼び出してaccessRoleを確認します)。 
イベント メタデータを追加する
カレンダーの予定を作成する際に、必要に応じてイベントのメタデータを追加できます。作成時にメタデータを追加しない場合は、events.update() を使用して多くのフィールドを更新できます。ただし、イベント ID などの一部のフィールドは、events.insert() オペレーション中にのみ設定できます。
- 場所
 - 住所を場所フィールドに追加すると、「出発時刻」や地図とルートの表示などの機能が有効になります。
 - イベント ID
 - イベントを作成する際に、Google の形式要件に準拠した独自のイベント ID を生成することもできます。これにより、ローカル データベース内のエンティティを Google カレンダーのイベントと同期させることができます。また、カレンダー バックエンドでオペレーションが正常に実行された後、どこかの時点で失敗した場合に、重複する予定が作成されるのを防ぎます。イベント ID が指定されていない場合、サーバーによって生成されます。詳細については、イベント ID リファレンスをご覧ください。
 - 参加者
 - 作成した予定は、同じ予定 ID で追加した参加者のメインの Google カレンダーすべてに表示されます。挿入リクエストで 
sendUpdatesを"all"または"externalOnly"に設定すると、対応する参加者にイベントのメール通知が届きます。詳しくは、複数の参加者がいるイベントをご覧ください。 
次の例は、イベントを作成してメタデータを設定する方法を示しています。
Go
// Refer to the Go quickstart on how to setup the environment:
// https://developers.google.com/workspace/calendar/quickstart/go
// Change the scope to calendar.CalendarScope and delete any stored credentials.
event := &calendar.Event{
  Summary: "Google I/O 2015",
  Location: "800 Howard St., San Francisco, CA 94103",
  Description: "A chance to hear more about Google's developer products.",
  Start: &calendar.EventDateTime{
    DateTime: "2015-05-28T09:00:00-07:00",
    TimeZone: "America/Los_Angeles",
  },
  End: &calendar.EventDateTime{
    DateTime: "2015-05-28T17:00:00-07:00",
    TimeZone: "America/Los_Angeles",
  },
  Recurrence: []string{"RRULE:FREQ=DAILY;COUNT=2"},
  Attendees: []*calendar.EventAttendee{
    &calendar.EventAttendee{Email:"lpage@example.com"},
    &calendar.EventAttendee{Email:"sbrin@example.com"},
  },
}
calendarId := "primary"
event, err = srv.Events.Insert(calendarId, event).Do()
if err != nil {
  log.Fatalf("Unable to create event. %v\n", err)
}
fmt.Printf("Event created: %s\n", event.HtmlLink)
Java
// Refer to the Java quickstart on how to setup the environment:
// https://developers.google.com/workspace/calendar/quickstart/java
// Change the scope to CalendarScopes.CALENDAR and delete any stored
// credentials.
Event event = new Event()
    .setSummary("Google I/O 2015")
    .setLocation("800 Howard St., San Francisco, CA 94103")
    .setDescription("A chance to hear more about Google's developer products.");
DateTime startDateTime = new DateTime("2015-05-28T09:00:00-07:00");
EventDateTime start = new EventDateTime()
    .setDateTime(startDateTime)
    .setTimeZone("America/Los_Angeles");
event.setStart(start);
DateTime endDateTime = new DateTime("2015-05-28T17:00:00-07:00");
EventDateTime end = new EventDateTime()
    .setDateTime(endDateTime)
    .setTimeZone("America/Los_Angeles");
event.setEnd(end);
String[] recurrence = new String[] {"RRULE:FREQ=DAILY;COUNT=2"};
event.setRecurrence(Arrays.asList(recurrence));
EventAttendee[] attendees = new EventAttendee[] {
    new EventAttendee().setEmail("lpage@example.com"),
    new EventAttendee().setEmail("sbrin@example.com"),
};
event.setAttendees(Arrays.asList(attendees));
EventReminder[] reminderOverrides = new EventReminder[] {
    new EventReminder().setMethod("email").setMinutes(24 * 60),
    new EventReminder().setMethod("popup").setMinutes(10),
};
Event.Reminders reminders = new Event.Reminders()
    .setUseDefault(false)
    .setOverrides(Arrays.asList(reminderOverrides));
event.setReminders(reminders);
String calendarId = "primary";
event = service.events().insert(calendarId, event).execute();
System.out.printf("Event created: %s\n", event.getHtmlLink());
JavaScript
// Refer to the JavaScript quickstart on how to setup the environment:
// https://developers.google.com/workspace/calendar/quickstart/js
// Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
// stored credentials.
const event = {
  'summary': 'Google I/O 2015',
  'location': '800 Howard St., San Francisco, CA 94103',
  'description': 'A chance to hear more about Google\'s developer products.',
  'start': {
    'dateTime': '2015-05-28T09:00:00-07:00',
    'timeZone': 'America/Los_Angeles'
  },
  'end': {
    'dateTime': '2015-05-28T17:00:00-07:00',
    'timeZone': 'America/Los_Angeles'
  },
  'recurrence': [
    'RRULE:FREQ=DAILY;COUNT=2'
  ],
  'attendees': [
    {'email': 'lpage@example.com'},
    {'email': 'sbrin@example.com'}
  ],
  'reminders': {
    'useDefault': false,
    'overrides': [
      {'method': 'email', 'minutes': 24 * 60},
      {'method': 'popup', 'minutes': 10}
    ]
  }
};
const request = gapi.client.calendar.events.insert({
  'calendarId': 'primary',
  'resource': event
});
request.execute(function(event) {
  appendPre('Event created: ' + event.htmlLink);
});
Node.js
// Refer to the Node.js quickstart on how to setup the environment:
// https://developers.google.com/workspace/calendar/quickstart/node
// Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
// stored credentials.
const event = {
  'summary': 'Google I/O 2015',
  'location': '800 Howard St., San Francisco, CA 94103',
  'description': 'A chance to hear more about Google\'s developer products.',
  'start': {
    'dateTime': '2015-05-28T09:00:00-07:00',
    'timeZone': 'America/Los_Angeles',
  },
  'end': {
    'dateTime': '2015-05-28T17:00:00-07:00',
    'timeZone': 'America/Los_Angeles',
  },
  'recurrence': [
    'RRULE:FREQ=DAILY;COUNT=2'
  ],
  'attendees': [
    {'email': 'lpage@example.com'},
    {'email': 'sbrin@example.com'},
  ],
  'reminders': {
    'useDefault': false,
    'overrides': [
      {'method': 'email', 'minutes': 24 * 60},
      {'method': 'popup', 'minutes': 10},
    ],
  },
};
calendar.events.insert({
  auth: auth,
  calendarId: 'primary',
  resource: event,
}, function(err, event) {
  if (err) {
    console.log('There was an error contacting the Calendar service: ' + err);
    return;
  }
  console.log('Event created: %s', event.htmlLink);
});
PHP
$event = new Google_Service_Calendar_Event(array(
  'summary' => 'Google I/O 2015',
  'location' => '800 Howard St., San Francisco, CA 94103',
  'description' => 'A chance to hear more about Google\'s developer products.',
  'start' => array(
    'dateTime' => '2015-05-28T09:00:00-07:00',
    'timeZone' => 'America/Los_Angeles',
  ),
  'end' => array(
    'dateTime' => '2015-05-28T17:00:00-07:00',
    'timeZone' => 'America/Los_Angeles',
  ),
  'recurrence' => array(
    'RRULE:FREQ=DAILY;COUNT=2'
  ),
  'attendees' => array(
    array('email' => 'lpage@example.com'),
    array('email' => 'sbrin@example.com'),
  ),
  'reminders' => array(
    'useDefault' => FALSE,
    'overrides' => array(
      array('method' => 'email', 'minutes' => 24 * 60),
      array('method' => 'popup', 'minutes' => 10),
    ),
  ),
));
$calendarId = 'primary';
$event = $service->events->insert($calendarId, $event);
printf('Event created: %s\n', $event->htmlLink);
Python
# Refer to the Python quickstart on how to setup the environment:
# https://developers.google.com/workspace/calendar/quickstart/python
# Change the scope to 'https://www.googleapis.com/auth/calendar' and delete any
# stored credentials.
event = {
  'summary': 'Google I/O 2015',
  'location': '800 Howard St., San Francisco, CA 94103',
  'description': 'A chance to hear more about Google\'s developer products.',
  'start': {
    'dateTime': '2015-05-28T09:00:00-07:00',
    'timeZone': 'America/Los_Angeles',
  },
  'end': {
    'dateTime': '2015-05-28T17:00:00-07:00',
    'timeZone': 'America/Los_Angeles',
  },
  'recurrence': [
    'RRULE:FREQ=DAILY;COUNT=2'
  ],
  'attendees': [
    {'email': 'lpage@example.com'},
    {'email': 'sbrin@example.com'},
  ],
  'reminders': {
    'useDefault': False,
    'overrides': [
      {'method': 'email', 'minutes': 24 * 60},
      {'method': 'popup', 'minutes': 10},
    ],
  },
}
event = service.events().insert(calendarId='primary', body=event).execute()
print 'Event created: %s' % (event.get('htmlLink'))
Ruby
event = Google::Apis::CalendarV3::Event.new(
  summary: 'Google I/O 2015',
  location: '800 Howard St., San Francisco, CA 94103',
  description: 'A chance to hear more about Google\'s developer products.',
  start: Google::Apis::CalendarV3::EventDateTime.new(
    date_time: '2015-05-28T09:00:00-07:00',
    time_zone: 'America/Los_Angeles'
  ),
  end: Google::Apis::CalendarV3::EventDateTime.new(
    date_time: '2015-05-28T17:00:00-07:00',
    time_zone: 'America/Los_Angeles'
  ),
  recurrence: [
    'RRULE:FREQ=DAILY;COUNT=2'
  ],
  attendees: [
    Google::Apis::CalendarV3::EventAttendee.new(
      email: 'lpage@example.com'
    ),
    Google::Apis::CalendarV3::EventAttendee.new(
      email: 'sbrin@example.com'
    )
  ],
  reminders: Google::Apis::CalendarV3::Event::Reminders.new(
    use_default: false,
    overrides: [
      Google::Apis::CalendarV3::EventReminder.new(
        reminder_method: 'email',
        minutes: 24 * 60
      ),
      Google::Apis::CalendarV3::EventReminder.new(
        reminder_method: 'popup',
        minutes: 10
      )
    ]
  )
)
result = client.insert_event('primary', event)
puts "Event created: #{result.html_link}"
予定にドライブの添付ファイルを追加する
ドキュメントの会議メモ、スプレッドシートの予算、スライドのプレゼンテーションなど、Google ドライブの関連ファイルをカレンダーの予定に添付できます。events.insert() 以降でイベントを作成するときに、events.patch() などの更新の一部として添付ファイルを追加できます。
Google ドライブのファイルを予定に添付する手順は次の 2 つです。
- 通常は 
files.get()メソッドを使用して、 Drive API Files リソースからファイルのalternateLinkURL、title、mimeTypeを取得します。 - リクエスト本文で 
attachmentsフィールドを設定し、supportsAttachmentsパラメータをtrueに設定して、イベントを作成または更新します。 
次のコード例は、既存のイベントを更新して添付ファイルを追加する方法を示しています。
Java
public static void addAttachment(Calendar calendarService, Drive driveService, String calendarId,
    String eventId, String fileId) throws IOException {
  File file = driveService.files().get(fileId).execute();
  Event event = calendarService.events().get(calendarId, eventId).execute();
  List<EventAttachment> attachments = event.getAttachments();
  if (attachments == null) {
    attachments = new ArrayList<EventAttachment>();
  }
  attachments.add(new EventAttachment()
      .setFileUrl(file.getAlternateLink())
      .setMimeType(file.getMimeType())
      .setTitle(file.getTitle()));
  Event changes = new Event()
      .setAttachments(attachments);
  calendarService.events().patch(calendarId, eventId, changes)
      .setSupportsAttachments(true)
      .execute();
}
PHP
function addAttachment($calendarService, $driveService, $calendarId, $eventId, $fileId) {
  $file = $driveService->files->get($fileId);
  $event = $calendarService->events->get($calendarId, $eventId);
  $attachments = $event->attachments;
  $attachments[] = array(
    'fileUrl' => $file->alternateLink,
    'mimeType' => $file->mimeType,
    'title' => $file->title
  );
  $changes = new Google_Service_Calendar_Event(array(
    'attachments' => $attachments
  ));
  $calendarService->events->patch($calendarId, $eventId, $changes, array(
    'supportsAttachments' => TRUE
  ));
}
Python
def add_attachment(calendarService, driveService, calendarId, eventId, fileId):
    file = driveService.files().get(fileId=fileId).execute()
    event = calendarService.events().get(calendarId=calendarId,
                                         eventId=eventId).execute()
    attachments = event.get('attachments', [])
    attachments.append({
        'fileUrl': file['alternateLink'],
        'mimeType': file['mimeType'],
        'title': file['title']
    })
    changes = {
        'attachments': attachments
    }
    calendarService.events().patch(calendarId=calendarId, eventId=eventId,
                                   body=changes,
                                   supportsAttachments=True).execute()
予定にビデオ会議と電話会議を追加する
予定を Hangoutsや Google Meet の会議に関連付けると、ユーザーは電話やビデオ通話でリモート会議に参加できるようになります。
conferenceData フィールドは、既存の会議の詳細の読み取り、コピー、クリアに使用できます。また、新しい会議の生成をリクエストするためにも使用できます。会議の詳細の作成と変更を許可するには、conferenceDataVersion リクエスト パラメータを 1 に設定します。
現在サポートされている conferenceData には、conferenceData.conferenceSolution.key.type で示されるように、次の 3 種類があります。
- 一般ユーザー向けのハングアウト(
eventHangout) - Google Workspace ユーザー向けの従来のハングアウト
(非推奨、
eventNamedHangout) - Google Meet(
hangoutsMeet) 
ユーザーの特定のカレンダーでサポートされている会議の種類は、calendars コレクションと calendarList コレクションの conferenceProperties.allowedConferenceSolutionTypes を確認することでわかります。settings コレクションの autoAddHangouts 設定を確認して、ユーザーが新しく作成したすべてのイベントでハングアウトを作成することを希望しているかどうかを確認することもできます。
type に加えて、conferenceSolution は、会議ソリューションを表すために使用できる name フィールドと iconUri フィールドも提供します。
JavaScript
const solution = event.conferenceData.conferenceSolution;
const content = document.getElementById("content");
const text = document.createTextNode("Join " + solution.name);
const icon = document.createElement("img");
icon.src = solution.iconUri;
content.appendChild(icon);
content.appendChild(text);
イベントの新しい会議を作成するには、新しく生成された requestId を含む createRequest を指定します。requestId はランダムな string にすることができます。会議は非同期で作成されますが、リクエストのステータスをいつでも確認して、ユーザーに状況を知らせることができます。
たとえば、既存のイベントの会議の生成をリクエストするには:
JavaScript
const eventPatch = {
  conferenceData: {
    createRequest: {requestId: "7qxalsvy0e"}
  }
};
gapi.client.calendar.events.patch({
  calendarId: "primary",
  eventId: "7cbh8rpc10lrc0ckih9tafss99",
  resource: eventPatch,
  sendUpdates: "all",
  conferenceDataVersion: 1
}).execute(function(event) {
  console.log("Conference created for event: %s", event.htmlLink);
});
この呼び出しに対する即時レスポンスには、完全に設定された conferenceData がまだ含まれていない可能性があります。これは、status フィールドのステータス コード pending で示されます。会議情報が入力されると、ステータス コードが success に変わります。entryPoints フィールドには、ユーザーがダイヤルインできる動画と電話の URI に関する情報が含まれます。
同じ会議の詳細で複数のカレンダーの予定をスケジュールする場合は、1 つの予定から別の予定に conferenceData 全体をコピーできます。
コピーは、特定の状況で役立ちます。たとえば、候補者と面接官用に別々のイベントを設定する採用アプリケーションを開発しているとします。面接官の身元を保護しつつ、すべての参加者が同じ電話会議に参加できるようにする必要があります。