GeekFactory

int128.hatenablog.com

Google Tasks APIでタスクの期限を設定する

Google Tasks APIでタスクの期限を設定するとき、タイムゾーンに注意する必要があります。Google Tasks上ではタスクの期限は日付(タイムゾーンUTC固定、時刻は00:00:00固定)で扱うのが無難です。

注意すべき仕様

Taskモデルのdueプロパティはタイムゾーン付き日時(RFC3339)と定義されています。API Explorerで試したところでは以下のようになりました。

  • APIからタスクを取得すると、dueプロパティはUTCで返される。
  • APIでタスクを更新するとき、dueプロパティはどのタイムゾーンでも指定できる。ただし、指定された日時をUTCに変換して時間を切り捨てた値が保存される。

ややこしいので例で考えます。

APIに以下のリクエストを渡してタスクを更新します。ここでは日本時間の10月2日を指定しています。

{
 "due": "2011-10-02T00:00:00.000+09:00",
 "id": "MTExxxxxxxxxxx"
}

すると、APIは更新後のタスクとして以下のレスポンスを返します。

{
 /* 中略 */
 "due": "2011-10-01T00:00:00.000Z"
}

APIからタスクを取得するとUTCの10月1日が返ります。Googleカレンダーで確認するとタスクの期限は10月1日になっています。

対策

タスクの期限はUTCで指定するようにします。ユーザが指定する日付は(通常は)ローカルタイムなので、UTCに変換してからAPIに渡すようにします。

例えば、こんな感じになるでしょう。

var date;   // 新しい期限
task.dueTime = date.getTime() - date.getTimezoneOffset() * 60 * 1000;   // UTCに変換
$.ajax({
  type: 'POST',
  url: '/tasks/update/dueTime',
  data: task,
  dataType: 'json',
  success: success,
  error: error
});
import com.google.api.client.util.DateTime;
import com.google.api.services.tasks.Tasks.TasksOperations.Patch;
import com.google.api.services.tasks.model.Task;

public void doPost() {
  // parameters
  String id;
  String tasklistID;
  long dueTime;

  Task task = new Task();
  task.setId(id);
  task.setDue(new DateTime(dueTime, 0));    // 時差は0を指定
  Patch patch = tasksService.tasks.patch(tasklistID, task.getId(), task);
  Task patched = patch.execute();
}