| from datetime import date, datetime | |
| from typing import Union, List | |
| from beautiful_date import BeautifulDate | |
| from dateutil.relativedelta import relativedelta | |
| from tzlocal import get_localzone_name | |
| from gcsa._services.base_service import BaseService | |
| from gcsa.free_busy import FreeBusy, FreeBusyQueryError | |
| from gcsa.serializers.free_busy_serializer import FreeBusySerializer | |
| from gcsa.util.date_time_util import to_localized_iso | |
| class FreeBusyService(BaseService): | |
| def get_free_busy( | |
| self, | |
| resource_ids: Union[str, List[str]] = None, | |
| *, | |
| time_min: Union[date, datetime, BeautifulDate] = None, | |
| time_max: Union[date, datetime, BeautifulDate] = None, | |
| timezone: str = get_localzone_name(), | |
| group_expansion_max: int = None, | |
| calendar_expansion_max: int = None, | |
| ignore_errors: bool = False | |
| ) -> FreeBusy: | |
| """Returns free/busy information for a set of calendars and/or groups. | |
| :param resource_ids: | |
| Identifier or list of identifiers of calendar(s) and/or group(s). | |
| Default is `default_calendar` specified in `GoogleCalendar`. | |
| :param time_min: | |
| The start of the interval for the query. | |
| :param time_max: | |
| The end of the interval for the query. | |
| :param timezone: | |
| Timezone formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich". By default, | |
| the computers local timezone is used if it is configured. UTC is used otherwise. | |
| :param group_expansion_max: | |
| Maximal number of calendar identifiers to be provided for a single group. | |
| An error is returned for a group with more members than this value. | |
| Maximum value is 100. | |
| :param calendar_expansion_max: | |
| Maximal number of calendars for which FreeBusy information is to be provided. | |
| Maximum value is 50. | |
| :param ignore_errors: | |
| Whether errors related to calendars and/or groups should be ignored. | |
| If `False` :py:class:`~gcsa.free_busy.FreeBusyQueryError` is raised in case of query related errors. | |
| If `True`, related errors are stored in the resulting :py:class:`~gcsa.free_busy.FreeBusy` object. | |
| Default is `False`. | |
| Note, request related errors (e.x. authentication error) will not be ignored regardless of | |
| the `ignore_errors` value. | |
| :return: | |
| :py:class:`~gcsa.free_busy.FreeBusy` object. | |
| """ | |
| time_min = time_min or datetime.now() | |
| time_max = time_max or time_min + relativedelta(weeks=2) | |
| time_min = to_localized_iso(time_min, timezone) | |
| time_max = to_localized_iso(time_max, timezone) | |
| if resource_ids is None: | |
| resource_ids = [self.default_calendar] | |
| elif not isinstance(resource_ids, (list, tuple, set)): | |
| resource_ids = [resource_ids] | |
| body = { | |
| "timeMin": time_min, | |
| "timeMax": time_max, | |
| "timeZone": timezone, | |
| "groupExpansionMax": group_expansion_max, | |
| "calendarExpansionMax": calendar_expansion_max, | |
| "items": [ | |
| { | |
| "id": r_id | |
| } for r_id in resource_ids | |
| ] | |
| } | |
| free_busy_json = self.service.freebusy().query(body=body).execute() | |
| free_busy = FreeBusySerializer.to_object(free_busy_json) | |
| if not ignore_errors and (free_busy.groups_errors or free_busy.calendars_errors): | |
| raise FreeBusyQueryError(groups_errors=free_busy.groups_errors, | |
| calendars_errors=free_busy.calendars_errors) | |
| return free_busy | |