Google Apps 脚本:event.setTime 错误和时间格式

Google Apps Script: event.setTime error and time format

我正在创建一个即将完成的预订系统。目前我正在从表单中收集数据,将其传递给 sheet,然后使用其中的一些信息来创建日历事件。这一切都很好。

在创建事件时,我还收集了 eventID,以便我可以使用它来识别事件并从传播中更新它sheet。这些更新也有效,除了更新 start/end 日期和时间会导致以下错误:

类型错误:在对象 CalendarEventSeries 中找不到函数 setTime。

这是我正在使用的代码:

var eventStart =  sh.getRange("D"+rowNumber).getValues();
var eventEnd =  sh.getRange("E"+rowNumber).getValues();
event.setTime(eventStart, eventEnd);

我对 setLocation 和 setTitle 做了完全相同的事情,没有问题。

我是新手,我不知道对象是什么,所以错误消息对我来说意义不大!但我可以看到 setTime 是 class 'CalendarEvent' (https://developers.google.com/apps-script/reference/calendar/calendar-event#setTime(Date,Date)) 中概述的方法,但不是 'CalendarEventSeries' 中的方法。反正我所有的事件都是开关事件?

提前感谢您的指点。

更新

我集成了Mogsdad的高级日历服务代码,之后

"var endTime = parseDate(event.end.date||event.end.dateTime);"

我是checking/logging'startTime'和'event'。 'startTime' 作为 'invalid date' 回来了(坏事?)并且 'event' 回来了我能想象到的所有日历条目信息(我希望是好事?!)。

parseDate 函数应该去哪里?也许我把它放错地方了(我到处都试过了!)而且它没有被使用?

此外,现在我要编辑的事件已经确定,日期是否已解析并用于搜索我已经找到的事件,以便 return 我最终可以使用 setTime 的日历事件在?这就是重点吗?

谢谢你的包容

更新 2 - 无效日期?

如果我跳过解析并像这样记录变量:

var 开始时间 = event.start.dateTime;

结果是 2015-05-24T02:00:00+01:00 我认为是正确的。因此,无效日期肯定是解析函数期间出现问题的情况,因为它只是 returns 'invalid date'。

下面上下文中的代码。

function onOpen() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var menuEntries = [{name: "Create Event Document Manually", functionName: "addSheet"},{name: "Update Calendar Entry", functionName: "getEventById"}
  ];


  ss.addMenu("Select Row & Click Here", menuEntries);
}



/**
 * Retrieve a CalendarApp CalendarEvent object from IDs.
 * This version utilizes the Advanced Calendar Service, which must be
 * enabled before use.
 *
 * @param {string} calendarId   ID of calendar to be searched
 * @param {string} eventId      Event ID to match
 *
 * @returns {CalendarEvent}     CalendarApp CalendarEvent object or null
 */


function getEventById(calendarId, eventId) {

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sh = ss.getActiveSheet();
  var rowNumber = sh.getActiveRange().getRowIndex();
  var myEventId = "q8q533oioluipirksmno88qv2g";
  var calendarId = "mydomain.tv_q9608ku2min78rasgt2s2n233c@group.calendar.google.com";


  // Get event by ID.
  var event = Calendar.Events.get(calendarId, myEventId);
  // This isn't a CalendarApp CalendarEvent though, so use the info
  // in the event to find it AGAIN as the right type.




  // Get start & end times of event. All-day events start at start.date,
  // while other events start at start.datetime. Likewise for end.

  var startTime = parseDate(event.start.date||event.start.dateTime);
  var endTime = parseDate(event.end.date||event.end.dateTime);



   Logger.log('Variables: ' + startTime + ' and ' + endTime);

  // Get array of events that fall between startTime & endTime
  var calEvents = CalendarApp.getEvents(startTime, endTime);

  // Search through those events, looking for a match by ID
  for (var i=0; i<calEvents.length; i++) {
    var curId = calEvents[i].getId().split('@')[0];  // extract id from id@calendar.google.com
    if (curId == eventId) {
      // Mission accomplished; we have an Event object with given id!
      return calEvents[i];

    }
  }
  // We did not find matching event
  return null;


}




  function parseDate(string) {
  var parts = string.split('T');
  parts[0] = parts[0].replace(/-/g, '/');
  return new Date(parts.join(' '));
}

当您从事件 ID 检索事件时,您(很可能)正在使用方法 getEventSerieById(ID) which returns a CalendarEventSeries, not a CalendarEvent

如果您查看这 3 个参考文档,您会注意到 CalendarEventSeries class 没有 setTime() 方法。

在这种情况下,您收到的错误消息实际上非常明确。

你应该找到一些处理这个问题的帖子,例如这个:Create Google Calendar Events from Spreadsheet but prevent duplicates

Serge 说得对 - 问题是您检索了一个 CalendarEventSeries object, not a CalendarEvent. Since the only method in the service that will look for an event by ID is getEventSeriesById(iCalId),您有点卡住了。

一种选择是使用 Advanced Calendar Service 代替:

var event = Calendar.Events.get(calendarId, eventId);

对于新代码,这是一个很好的选择,特别是对于已经习惯了 Javascript API 的开发人员。但是,如果您是初学者或不熟悉高级服务,您会发现学习曲线比日历服务更陡峭。

在那种情况下,这些实用程序应该可以帮助您坚持使用 CalendarApp 及其 Classes 和方法,满足对 getEventById() 函数的需求。

后台高级日历服务

getEventById()有两个版本。第一个使用高级日历服务,它必须是 enabled before use。代码相当简单。您必须明确提供日历 ID,因为这不是 Class 方法。示例:

var calendarId = CalendarApp.getDefaultCalendar().getId();
var eventId = "smmd8h1dfe9lo9bip52hidnqk0";
var event = getEventById(calendarId, eventId);

代码:

/**
 * Retrieve a CalendarApp CalendarEvent object from IDs.
 * This version utilizes the Advanced Calendar Service, which must be
 * enabled before use.
 *
 * @param {string} calendarId   ID of calendar to be searched
 * @param {string} eventId      Event ID to match
 *
 * @returns {CalendarEvent}     CalendarApp CalendarEvent object or null
 */
function getEventById(calendarId, eventId) {
  // Get event by ID.
  var event = Calendar.Events.get(calendarId, eventId);
  // This isn't a CalendarApp CalendarEvent though, so use the info
  // in the event to find it AGAIN as the right type.

  // Get start & end times of event. All-day events start at start.date,
  // while other events start at start.datetime. Likewise for end.
  var startTime = parseDate(event.start.date||event.start.dateTime);
  var endTime = parseDate(event.end.date||event.end.dateTime);

  // Get array of events that fall between startTime & endTime
  var calEvents = CalendarApp.getEvents(startTime, endTime);

  // Search through those events, looking for a match by ID
  for (var i=0; i<calEvents.length; i++) {
    var curId = calEvents[i].getId().split('@')[0];  // extract id from id@calendar.google.com
    if (curId == eventId) {
      // Mission accomplished; we have an Event object with given id!
      return calEvents[i];
    }
  }
  // We did not find matching event
  return null;
}

日历 API 通过 UrlFetchApp

此版本通过 UrlFetchApp 使用日历 API,不需要任何特殊启用。不过代码比之前的版本复杂多了。

/**
 * Retrieve a CalendarApp CalendarEvent object from IDs.
 * This version utilizes the Calendar API via UrlFetchApp, so
 * requires no enablement. However, it's more complex.
 *
 * @param {string} calendarId   ID of calendar to be searched
 * @param {string} eventId      Event ID to match
 *
 * @returns {CalendarEvent}     CalendarApp CalendarEvent object or null
 */
function getEventById(calendarId, eventId) {
  // Prepare a GET request to API URL, to Get event by ID.
  var url = "https://www.googleapis.com/calendar/v3/calendars/calendarId/events/eventId"
            .replace("calendarId",calendarId)
            .replace("eventId",eventId);

  var options = {
    headers: {
      'Authorization': 'Bearer ' +  ScriptApp.getOAuthToken()
    }
  }

  // Send request
  var response = UrlFetchApp.fetch(url, options);
  var rc = response.getResponseCode();
  var text = response.getContentText();

  // If result code is 200OK, process response text
  if (rc == 200) {
    // The event is contained in the response text; parse it into an object
    var event = JSON.parse(text);
    // This isn't a CalendarApp CalendarEvent though, so use the info
    // in the event to find it AGAIN as the right type.

    // Get start & end times of event. All-day events start at start.date,
    // while other events start at start.datetime. Likewise for end.
    var startTime = parseDate(event.start.date||event.start.dateTime);
    var endTime = parseDate(event.end.date||event.end.dateTime);

    // Get array of events that fall between startTime & endTime
    var calEvents = CalendarApp.getEvents(startTime, endTime);

    // Search through those events, looking for a match by ID
    for (var i=0; i<calEvents.length; i++) {
      var curId = calEvents[i].getId().split('@')[0];  // extract id from id@calendar.google.com
      var desc = calEvents[i].getDescription();
      if (curId == eventId) {
        // Mission accomplished; we have an Event object with given id!
        return calEvents[i];
      }
    }
    // We did not find matching event
    return null;
  }
  else
    // An error in fetch, anything BUT 200
    throw new Error( ""+rc+JSON.parse(text).message );
}

辅助函数

getEventById() 的两个版本都需要 Google's documentation 中提供的辅助函数。

/**
 * From https://developers.google.com/apps-script/advanced/calendar#listing_events
 *
 * Parses an RFC 3339 date or datetime string and returns a corresponding Date
 * object. This function is provided as a workaround until Apps Script properly
 * supports RFC 3339 dates. For more information, see
 * https://code.google.com/p/google-apps-script-issues/issues/detail?id=3860
 * @param {string} string The RFC 3339 string to parse.
 * @return {Date} The parsed date.
 */
function parseDate(string) {
  var parts = string.split('T');
  parts[0] = parts[0].replace(/-/g, '/');
  return new Date(parts.join(' '));
}