# Path: src/apscheduler/abc.py
# class Trigger(Iterator[datetime], metaclass=ABCMeta):
#     """Abstract base class that defines the interface that every trigger must implement."""
# 
#     __slots__ = ()
# 
#     @abstractmethod
#     def next(self) -> datetime | None:
#         """
#         Return the next datetime to fire on.
# 
#         If no such datetime can be calculated, ``None`` is returned.
#         :raises apscheduler.exceptions.MaxIterationsReached:
#         """
# 
#     @abstractmethod
#     def __getstate__(self):
#         """Return the (JSON compatible) serializable state of the trigger."""
# 
#     @abstractmethod
#     def __setstate__(self, state):
#         """Initialize an empty instance from an existing state."""
# 
#     def __iter__(self):
#         return self
# 
#     def __next__(self) -> datetime:
#         dateval = self.next()
#         if dateval is None:
#             raise StopIteration
#         else:
#             return dateval
# 
# Path: src/apscheduler/marshalling.py
# @overload
# def marshal_date(value: None) -> None:
#     ...
# 
# def marshal_timezone(value: tzinfo) -> str:
#     if isinstance(value, ZoneInfo):
#         return value.key
#     elif hasattr(value, 'zone'):  # pytz timezones
#         return value.zone
# 
#     raise SerializationError(
#         f'Unserializable time zone: {value!r}\n'
#         f'Only time zones from the zoneinfo or pytz modules can be serialized.')
# 
# @overload
# def unmarshal_date(value: None) -> None:
#     ...
# 
# def unmarshal_timezone(value: str) -> ZoneInfo:
#     return ZoneInfo(value)
# 
# Path: src/apscheduler/util.py
# def timezone_repr(timezone: tzinfo) -> str:
#     if isinstance(timezone, ZoneInfo):
#         return timezone.key
#     else:
#         return repr(timezone)
# 
# Path: src/apscheduler/validators.py
# def as_date(value: date | str | None) -> date | None:
#     """
#     Convert the value to a date.
# 
#     :param value: the value to convert to a date
#     :return: a date object, or ``None`` if ``None`` was given
# 
#     """
#     if value is None:
#         return None
#     elif isinstance(value, str):
#         return date.fromisoformat(value)
#     elif isinstance(value, date):
#         return value
# 
#     raise TypeError(f'Expected string or date, got {value.__class__.__qualname__} instead')
# 
# def as_timezone(value: str | tzinfo | None) -> tzinfo:
#     """
#     Convert the value into a tzinfo object.
# 
#     If ``value`` is ``None`` or ``'local'``, use the local timezone.
# 
#     :param value: the value to be converted
#     :return: a timezone object
# 
#     """
#     if value is None or value == 'local':
#         return get_localzone()
#     elif isinstance(value, str):
#         return ZoneInfo(value)
#     elif isinstance(value, tzinfo):
#         if value is timezone.utc:
#             return ZoneInfo('UTC')
#         else:
#             return value
# 
#     raise TypeError(f'Expected tzinfo instance or timezone name, got '
#                     f'{value.__class__.__qualname__} instead')
# 
# def require_state_version(trigger: Trigger, state: dict[str, Any], max_version: int) -> None:
#     try:
#         if state['version'] > max_version:
#             raise DeserializationError(
#                 f'{trigger.__class__.__name__} received a serialized state with version '
#                 f'{state["version"]}, but it only supports up to version {max_version}. '
#                 f'This can happen when an older version of APScheduler is being used with a data '
#                 f'store that was previously used with a newer APScheduler version.'
#             )
#     except KeyError as exc:
#         raise DeserializationError('Missing "version" key in the serialized state') from exc


from datetime import date, datetime, time, timedelta, tzinfo
from typing import Any
from ..abc import Trigger
from ..marshalling import marshal_date, marshal_timezone, unmarshal_date, unmarshal_timezone
from ..util import timezone_repr
from ..validators import as_date, as_timezone, require_state_version
import attrs
    valid datetime starting from the previous run time is returned, even if it's in the past.

    .. warning:: Be wary of setting a start date near the end of the month (29. – 31.) if you have
        ``months`` specified in your interval, as this will skip the months where those days do not
        exist. Likewise, setting the start date on the leap day (February 29th) and having
        ``years`` defined may cause some years to be skipped.

        Users are also discouraged from  using a time inside the target timezone's DST switching
        period (typically around 2 am) since a date could either be skipped or repeated due to the
        specified wall clock time either occurring twice or not at all.

    :param years: number of years to wait
    :param months: number of months to wait
    :param weeks: number of weeks to wait
    :param days: number of days to wait
    :param hour: hour to run the task at
    :param minute: minute to run the task at
    :param second: second to run the task at
    :param start_date: first date to trigger on (defaults to current date if omitted)
    :param end_date: latest possible date to trigger on
    :param timezone: time zone to use for calculating the next fire time
    """

    years: int = 0
    months: int = 0
    weeks: int = 0
    days: int = 0
    hour: int = 0
    minute: int = 0
    second: int = 0

# Path: src/apscheduler/abc.py
# class Trigger(Iterator[datetime], metaclass=ABCMeta):
#     """Abstract base class that defines the interface that every trigger must implement."""
# 
#     __slots__ = ()
# 
#     @abstractmethod
#     def next(self) -> datetime | None:
#         """
#         Return the next datetime to fire on.
# 
#         If no such datetime can be calculated, ``None`` is returned.
#         :raises apscheduler.exceptions.MaxIterationsReached:
#         """
# 
#     @abstractmethod
#     def __getstate__(self):
#         """Return the (JSON compatible) serializable state of the trigger."""
# 
#     @abstractmethod
#     def __setstate__(self, state):
#         """Initialize an empty instance from an existing state."""
# 
#     def __iter__(self):
#         return self
# 
#     def __next__(self) -> datetime:
#         dateval = self.next()
#         if dateval is None:
#             raise StopIteration
#         else:
#             return dateval
# 
# Path: src/apscheduler/marshalling.py
# @overload
# def marshal_date(value: None) -> None:
#     ...
# 
# def marshal_timezone(value: tzinfo) -> str:
#     if isinstance(value, ZoneInfo):
#         return value.key
#     elif hasattr(value, 'zone'):  # pytz timezones
#         return value.zone
# 
#     raise SerializationError(
#         f'Unserializable time zone: {value!r}\n'
#         f'Only time zones from the zoneinfo or pytz modules can be serialized.')
# 
# @overload
# def unmarshal_date(value: None) -> None:
#     ...
# 
# def unmarshal_timezone(value: str) -> ZoneInfo:
#     return ZoneInfo(value)
# 
# Path: src/apscheduler/util.py
# def timezone_repr(timezone: tzinfo) -> str:
#     if isinstance(timezone, ZoneInfo):
#         return timezone.key
#     else:
#         return repr(timezone)
# 
# Path: src/apscheduler/validators.py
# def as_date(value: date | str | None) -> date | None:
#     """
#     Convert the value to a date.
# 
#     :param value: the value to convert to a date
#     :return: a date object, or ``None`` if ``None`` was given
# 
#     """
#     if value is None:
#         return None
#     elif isinstance(value, str):
#         return date.fromisoformat(value)
#     elif isinstance(value, date):
#         return value
# 
#     raise TypeError(f'Expected string or date, got {value.__class__.__qualname__} instead')
# 
# def as_timezone(value: str | tzinfo | None) -> tzinfo:
#     """
#     Convert the value into a tzinfo object.
# 
#     If ``value`` is ``None`` or ``'local'``, use the local timezone.
# 
#     :param value: the value to be converted
#     :return: a timezone object
# 
#     """
#     if value is None or value == 'local':
#         return get_localzone()
#     elif isinstance(value, str):
#         return ZoneInfo(value)
#     elif isinstance(value, tzinfo):
#         if value is timezone.utc:
#             return ZoneInfo('UTC')
#         else:
#             return value
# 
#     raise TypeError(f'Expected tzinfo instance or timezone name, got '
#                     f'{value.__class__.__qualname__} instead')
# 
# def require_state_version(trigger: Trigger, state: dict[str, Any], max_version: int) -> None:
#     try:
#         if state['version'] > max_version:
#             raise DeserializationError(
#                 f'{trigger.__class__.__name__} received a serialized state with version '
#                 f'{state["version"]}, but it only supports up to version {max_version}. '
#                 f'This can happen when an older version of APScheduler is being used with a data '
#                 f'store that was previously used with a newer APScheduler version.'
#             )
#     except KeyError as exc:
#         raise DeserializationError('Missing "version" key in the serialized state') from exc


# Path: src/apscheduler/triggers/calendarinterval.py
from datetime import date, datetime, time, timedelta, tzinfo
from typing import Any
from ..abc import Trigger
from ..marshalling import marshal_date, marshal_timezone, unmarshal_date, unmarshal_timezone
from ..util import timezone_repr
from ..validators import as_date, as_timezone, require_state_version
import attrs

    valid datetime starting from the previous run time is returned, even if it's in the past.

    .. warning:: Be wary of setting a start date near the end of the month (29. – 31.) if you have
        ``months`` specified in your interval, as this will skip the months where those days do not
        exist. Likewise, setting the start date on the leap day (February 29th) and having
        ``years`` defined may cause some years to be skipped.

        Users are also discouraged from  using a time inside the target timezone's DST switching
        period (typically around 2 am) since a date could either be skipped or repeated due to the
        specified wall clock time either occurring twice or not at all.

    :param years: number of years to wait
    :param months: number of months to wait
    :param weeks: number of weeks to wait
    :param days: number of days to wait
    :param hour: hour to run the task at
    :param minute: minute to run the task at
    :param second: second to run the task at
    :param start_date: first date to trigger on (defaults to current date if omitted)
    :param end_date: latest possible date to trigger on
    :param timezone: time zone to use for calculating the next fire time
    """

    years: int = 0
    months: int = 0
    weeks: int = 0
    days: int = 0
    hour: int = 0
    minute: int = 0
    second: int = 0

    start_date: date = attrs.field(converter=as_date, factory=date.today)