o
    .j                     @  s2  d Z ddlmZ ddlZddlmZ ddlmZmZm	Z	m
Z
 ddlmZ er6ddlmZ ddlmZmZmZ dTddZdUddZdVddZdWddZdXddZdXddZdXd d!ZdYd#d$ZdZd&d'Zd[d+d,Z	-d\d]d3d4Zd^d7d8Zd_d:d;ZdXd<d=Z d`dAdBZ!dadDdEZ"dbdIdJZ#dcdddQdRZ$g dSZ%dS )ezUtility functions.    )annotationsN)wraps)TYPE_CHECKINGCallableOptionalSequence)PeriodEndBeforeStart)ComponentAdapter)RecurrenceIDsTime	Timestampdtdatetime.datetimereturnr   c                 C  s   |   S )z#Return the time stamp of a datetime)	timestamp)r    r   O/home/thesage/.local/lib/python3.10/site-packages/recurring_ical_events/util.pyr      s   r   dater   datetime.datec                 C  s   t | j| j| jS )z%Converts a date or datetime to a date)datetimer   yearmonthday)r   r   r   r   convert_to_date   s   r   tzinfodatetime.tzinfo | Timec                 C  s
   t | dS )zWhether the time zone requires localize() and normalize().

    pytz requires these funtions to be used in order to correctly use the
    time zones after operations.
    localize)hasattrr   r   r   r   is_pytz   s   
r   timec                 C  s   t | r
| j| S | S )zAWe have to normalize the time after a calculation if we use pytz.)
is_pytz_dtr   	normalizer    r   r   r   normalize_pytz#   s   r$   boolc                 C  s   t | tjot | tj S )z*Whether this is a date and not a datetime.)
isinstancer   r   r#   r   r   r   is_date*   s   r'   c                 C  s   t | tjS )z*Whether this is a datetime and not a date.)r&   r   r#   r   r   r   is_datetime/   s   r(   c                 C  s   t | o| jduS )z*Whether this date/datetime has a timezone.N)r(   r   r#   r   r   r   has_timezone4   s   r)   Optional[datetime.tzinfo]c                 C  s|   t | rt| j| j| j} t| tjr<| jdu r.|dur,t|r&|| S | j	|dS | S |du r:t
| j	ddS | S | S )a*  Converts a date to a datetime.

    Dates are converted to datetimes with tzinfo.
    Datetimes loose their timezone if tzinfo is None.
    Datetimes receive tzinfo as a timezone if they do not have a timezone.
    Datetimes retain their timezone if they have one already (tzinfo is not None).
    Nr   )r'   r   r   r   r   r&   r   r   r   replacer$   )r   r   r   r   r   convert_to_datetime9   s   


r,   +tuple[datetime.datetime, datetime.datetime]c                 C  s2   t | r| n| jddddd}||tjdd fS )zConvert the datetime to a start and end date in between it occurs.

    Returns:
        (start, end) where start <= dt < end
    r   )hourmicrosecondminutesecond   )days)r'   r+   r   	timedelta)r   startr   r   r   convert_to_date_rangeQ   s   r6   datesSequence[Time]
list[Time]c                   sJ   d d}| D ]}t |sd}t|r|j  nq|r| S  fdd| D S )zEMake an list or tuple of dates comparable.

    Returns an list.
    NTFc                   s   g | ]}t | qS r   )r,   ).0r   r   r   r   
<listcomp>j   s    z#make_comparable.<locals>.<listcomp>)r'   r)   r   )r7   	all_datesr   r   r   r   make_comparable[   s   r=   F
span_start	span_stopevent_start
event_stop
comparablec                 C  s   |st | |||f\} }}}||krtd| d| d||| |kr0td|  d| d| |||krH| |kr<|| kS | |  koE|k S   S | |krX||   koU|k S   S ||k o_| |k S )a{  Return whether an event should is included within a time span.

    - span_start and span_stop define the time span
    - event_start and event_stop define the event time
    - comparable indicates whether the dates can be compared.
        You can set it to True if you are sure you have timezones and
        date/datetime correctly or used make_comparable() before.

    Note that the stops are exlusive but the starts are inclusive.

    This is an essential function of the module. It should be tested in
    test/test_time_span_contains_event.py.

    This raises a PeriodEndBeforeStart exception if a start is after an end.
    z+the event must start before it ends(start: z end: )z/the time span must start before it ends(start: )r=   r   )r>   r?   r@   rA   rB   r   r   r   time_span_contains_eventm   s>   
rD   date1date2c                 C  s   t | |f\} }| |kS )zCCompare two dates if date1 > date2 and make them comparable before.r=   rE   rF   r   r   r   compare_greater   s   rI   intc                 C  s    t | |f\} }| |k| |k  S )zCompare two dates, like cmp().

    Returns
    -------
        -1 if date1 < date2
         0 if date1 = date2
         1 if date1 > date2

    rG   rH   r   r   r   cmp   s   rK   c                 C  s   t | tjo
t| jS )zWhether the time requires localize() and normalize().

    pytz requires these funtions to be used in order to correctly use the
    time zones after operations.
    )r&   r   r   r   r#   r   r   r   r!      s   r!   funcr   propertyc                   s4   d j  t tt d fdd}|S )z&Cache the property value for speed up._cached_selfobjectc                   s,   | j }|u r |  | j < }|S N)__dict__get)rO   valuerL   name	not_foundr   r   cached_property   s   z(cached_property.<locals>.cached_propertyN)rO   rP   )__name__rP   rM   r   )rL   rX   r   rU   r   rX      s   rX   r
   c                 C  sJ   t | tjst| dfS | jdu r| fS | tjjjdd| jddfS )zConvert the time to a recurrence id so it can be hashed and recognized.

    The first value should be used to identify a component as it is a datetime in UTC.
    The other values can be used to look the component up.
    Nr   )r&   r   r,   r   
astimezonetimezoneutcr+   r#   r   r   r   to_recurrence_ids   s   

r]   adapter1ComponentAdapter | Noneadapter2c                 C  s   t | |dd dS )z)Return the one with the highest sequence.c                 S  s   | d u rdS | j S )Ng    _)sequence)adapterr   r   r   <lambda>   s    z'with_highest_sequence.<locals>.<lambda>)key)max)r^   r`   r   r   r   with_highest_sequence   s
   rf   
dictionarydictkeysSequence[object]defaultrP   c                 C  s   |}|D ]}|  ||}q|S )z)Get any item from the keys and return it.)rS   )rg   ri   rk   resultrd   r   r   r   get_any   s   rm   )r   rK   r6   r,   rm   r)   r'   r(   r   r!   r=   r$   rD   r]   rf   )r   r   r   r   )r   r   r   r   )r   r   )r    r   r   r   )r    r   r   r%   )r   r   r   r*   r   r   )r   r   r   r-   )r7   r8   r   r9   )F)r>   r   r?   r   r@   r   rA   r   rB   r%   r   r%   )rE   r   rF   r   r   r%   )rE   r   rF   r   r   rJ   )rL   r   r   rM   )r    r   r   r
   )r^   r_   r`   r_   rQ   )rg   rh   ri   rj   rk   rP   )&__doc__
__future__r   r   	functoolsr   typingr   r   r   r   recurring_ical_events.errorsr   (recurring_ical_events.adapters.componentr	   recurring_ical_events.typesr
   r   r   r   r   r   r$   r'   r(   r)   r,   r6   r=   rD   rI   rK   r!   rX   r]   rf   rm   __all__r   r   r   r   <module>   s:    



	







5


	

