U
    j                     @  s  d Z ddlmZ ddlZddlZddlZddlmZmZmZm	Z	 ddl
mZ ddlmZ ddlmZ ddlmZmZmZ dd	lmZmZmZmZmZ d
dlmZmZmZ edZedZ G dd dZ!G dd de"Z#G dd de$Z%G dd de$Z&G dd de'Z(G dd de"Z)G dd dZ*G dd dZ+G dd dZ,G d d! d!e,Z-G d"d# d#e,Z.G d$d% d%e,Z/G d&d' d'e,Z0G d(d) d)e,Z1G d*d+ d+e$Z2G d,d- d-e$Z3G d.d/ d/e"Z4G d0d1 d1e%eZ5G d2d3 d3eZ6G d4d5 d5e,Z7G d6d7 d7e$Z8G d8d9 d9Z9G d:d; d;Z:G d<d= d=e$Z;G d>d? d?eZ<d@dd?dAdBdddddd!d#d%d'dd-d9d=dd/d)d3dd5d;d7d+dCd1gZ=dS )Da
  This module contains the parser/generators (or coders/encoders if you
prefer) for the classes/datatypes that are used in iCalendar:

###########################################################################

# This module defines these property value data types and property parameters

4.2 Defined property parameters are:

.. code-block:: text

     ALTREP, CN, CUTYPE, DELEGATED-FROM, DELEGATED-TO, DIR, ENCODING, FMTTYPE,
     FBTYPE, LANGUAGE, MEMBER, PARTSTAT, RANGE, RELATED, RELTYPE, ROLE, RSVP,
     SENT-BY, TZID, VALUE

4.3 Defined value data types are:

.. code-block:: text

    BINARY, BOOLEAN, CAL-ADDRESS, DATE, DATE-TIME, DURATION, FLOAT, INTEGER,
    PERIOD, RECUR, TEXT, TIME, URI, UTC-OFFSET

###########################################################################

iCalendar properties have values. The values are strongly typed. This module
defines these types, calling val.to_ical() on them will render them as defined
in rfc5545.

If you pass any of these classes a Python primitive, you will have an object
that can render itself as iCalendar formatted date.

Property Value Data Types start with a 'v'. they all have an to_ical() and
from_ical() method. The to_ical() method generates a text string in the
iCalendar format. The from_ical() method can parse this format and return a
primitive Python datatype. So it should always be true that:

.. code-block:: python

    x == vDataType.from_ical(VDataType(x).to_ical())

These types are mainly used for parsing and file generation. But you can set
them directly.
    )annotationsN)datedatetimetime	timedelta)Union)CaselessDict)Enum)
Parametersescape_charunescape_char)DEFAULT_ENCODING	ICAL_TYPESEQUENCE_TYPESfrom_unicode
to_unicode   )tzid_from_dttzid_from_tzinfotzpzF([-+]?)P(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$z=(?P<signal>[+-]?)(?P<relative>[\d]{0,2})(?P<weekday>[\w]{2})$c                   @  sF   e Zd ZU dZded< dd Zdd Zdd	 Zed
d Z	dd Z
dS )vBinaryz+Binary property values are base 64 encoded.r
   paramsc                 C  s   t || _tddd| _d S )NBASE64ZBINARY)encodingvalue)r   objr
   r   )selfr    r   2/tmp/pip-unpacked-wheel-g40nyxg1/icalendar/prop.py__init__P   s    
zvBinary.__init__c                 C  s   d|    dS )NzvBinary()to_icalr   r   r   r   __repr__T   s    zvBinary.__repr__c                 C  s   t | jdd d S )Nutf-8)binascii
b2a_base64r   encoder#   r   r   r   r"   W   s    zvBinary.to_icalc              	   C  s2   zt | W S  ttfk
r,   tdY nX d S )NzNot valid base 64 encoding.)base64	b64decode
ValueErrorUnicodeErroricalr   r   r   	from_icalZ   s    zvBinary.from_icalc                 C  s   t |to| j|jkS self == other)
isinstancer   r   r   otherr   r   r   __eq__a   s    zvBinary.__eq__N)__name__
__module____qualname____doc____annotations__r   r$   r"   staticmethodr0   r6   r   r   r   r   r   K   s   

r   c                      sR   e Zd ZU dZded< edddZi d fdd	
Zd
d Ze	dd Z
  ZS )vBooleana  Boolean

    Value Name:  BOOLEAN

    Purpose:  This value type is used to identify properties that contain
      either a "TRUE" or "FALSE" Boolean value.

    Format Definition:  This value type is defined by the following
      notation:

    .. code-block:: text

        boolean    = "TRUE" / "FALSE"

    Description:  These values are case-insensitive text.  No additional
      content value encoding is defined for this value type.

    Example:  The following is an example of a hypothetical property that
      has a BOOLEAN value type:

    .. code-block:: python

        TRUE

    .. code-block:: pycon

        >>> from icalendar.prop import vBoolean
        >>> boolean = vBoolean.from_ical('TRUE')
        >>> boolean
        True
        >>> boolean = vBoolean.from_ical('FALSE')
        >>> boolean
        False
        >>> boolean = vBoolean.from_ical('True')
        >>> boolean
        True
    r
   r   TF)truefalser   c                  s"   t  j| f||}t||_|S Nsuper__new__r
   r   clsr   argskwargsr   	__class__r   r   rD      s    
zvBoolean.__new__c                 C  s   | rdS dS )Ns   TRUEs   FALSEr   r#   r   r   r   r"      s    zvBoolean.to_icalc                 C  s4   z| j | W S  tk
r.   td| Y nX d S )Nz Expected 'TRUE' or 'FALSE'. Got )BOOL_MAP	Exceptionr,   rF   r/   r   r   r   r0      s    zvBoolean.from_ical)r7   r8   r9   r:   r;   r   rK   rD   r"   classmethodr0   __classcell__r   r   rI   r   r=   f   s   
&r=   c                      sr   e Zd ZU dZded< ei f fdd	Zdddd	Zd
dddZe	ddddZ
ddlmZmZmZ   ZS )vTextzSimple text.r
   r   c                   s.   t ||d}t | |}||_t||_|S Nr   )r   rC   rD   r   r
   r   rF   r   r   r   r   rI   r   r   rD      s
    
zvText.__new__strreturnc                 C  s   d|   dS )NzvText(r    r!   r#   r   r   r   r$      s    zvText.__repr__bytesc                 C  s   t | | jS rA   )r   r)   r   r#   r   r   r   r"      s    zvText.to_icalr   r.   c                 C  s   t |}| |S rA   )r   )rF   r/   Z
ical_unescr   r   r   r0      s    zvText.from_icalr   )ALTREPLANGUAGERELTYPE)r7   r8   r9   r:   r;   r   rD   r$   r"   rN   r0   icalendar.paramrX   rY   rZ   rO   r   r   rI   r   rP      s   
rP   c                      s   e Zd ZU dZded< ei f fdd	Zdd Zdd	 Ze	d
d Z
eddddZddlmZmZmZmZmZmZmZmZmZmZ eZ  ZS )vCalAddressa  Calendar User Address

    Value Name:
        CAL-ADDRESS

    Purpose:
        This value type is used to identify properties that contain a
        calendar user address.

    Description:
        The value is a URI as defined by [RFC3986] or any other
        IANA-registered form for a URI.  When used to address an Internet
        email transport address for a calendar user, the value MUST be a
        mailto URI, as defined by [RFC2368].

    Example:
        ``mailto:`` is in front of the address.

        .. code-block:: text

            mailto:jane_doe@example.com

        Parsing:

        .. code-block:: pycon

            >>> from icalendar import vCalAddress
            >>> cal_address = vCalAddress.from_ical('mailto:jane_doe@example.com')
            >>> cal_address
            vCalAddress('mailto:jane_doe@example.com')

        Encoding:

        .. code-block:: pycon

            >>> from icalendar import vCalAddress, Event
            >>> event = Event()
            >>> jane = vCalAddress("mailto:jane_doe@example.com")
            >>> jane.name = "Jane"
            >>> event["organizer"] = jane
            >>> print(event.to_ical())
            BEGIN:VEVENT
            ORGANIZER;CN=Jane:mailto:jane_doe@example.com
            END:VEVENT
    r
   r   c                   s(   t ||d}t | |}t||_|S rQ   r   rC   rD   r
   r   rS   rI   r   r   rD      s    
zvCalAddress.__new__c                 C  s   d|  dS )NzvCalAddress('z')r   r#   r   r   r   r$      s    zvCalAddress.__repr__c                 C  s
   |  tS rA   r)   r   r#   r   r   r   r"      s    zvCalAddress.to_icalc                 C  s   | |S rA   r   rM   r   r   r   r0      s    zvCalAddress.from_icalrT   rU   c                 C  s"   |   dr| dd S t| S )z/The email address without mailto: at the start.zmailto:   N)lower
startswithrT   r#   r   r   r   email   s    zvCalAddress.emailr   )
CNCUTYPEDELEGATED_FROMDELEGATED_TODIRrY   PARTSTATROLERSVPSENT_BY)r7   r8   r9   r:   r;   r   rD   r$   r"   rN   r0   propertyrb   r[   rc   rd   re   rf   rg   rY   rh   ri   rj   rk   namerO   r   r   rI   r   r\      s   
.
0r\   c                      sD   e Zd ZU dZded< i d fdd
Zdd Zed	d
 Z  Z	S )vFloata  Float

    Value Name:
        FLOAT

    Purpose:
        This value type is used to identify properties that contain
        a real-number value.

    Format Definition:
        This value type is defined by the following notation:

        .. code-block:: text

            float      = (["+"] / "-") 1*DIGIT ["." 1*DIGIT]

    Description:
        If the property permits, multiple "float" values are
        specified by a COMMA-separated list of values.

        Example:

        .. code-block:: text

            1000000.0000001
            1.333
            -3.14

        .. code-block:: pycon

            >>> from icalendar.prop import vFloat
            >>> float = vFloat.from_ical('1000000.0000001')
            >>> float
            1000000.0000001
            >>> float = vFloat.from_ical('1.333')
            >>> float
            1.333
            >>> float = vFloat.from_ical('+1.333')
            >>> float
            1.333
            >>> float = vFloat.from_ical('-3.14')
            >>> float
            -3.14
    r
   r   r@   c                  s"   t  j| f||}t||_|S rA   rB   rE   rI   r   r   rD   C  s    
zvFloat.__new__c                 C  s   t | dS Nr%   rT   r)   r#   r   r   r   r"   H  s    zvFloat.to_icalc                 C  s2   z
| |W S  t k
r,   td| Y nX d S )NzExpected float value, got: rL   r,   rM   r   r   r   r0   K  s    
zvFloat.from_ical
r7   r8   r9   r:   r;   rD   r"   rN   r0   rO   r   r   rI   r   rn     s   
-rn   c                      sP   e Zd ZU dZded< i d fdd
Zddd	d
ZeddddZ  Z	S )vInta  Integer

    Value Name:
        INTEGER

    Purpose:
        This value type is used to identify properties that contain a
        signed integer value.

    Format Definition:
        This value type is defined by the following notation:

        .. code-block:: text

            integer    = (["+"] / "-") 1*DIGIT

    Description:
        If the property permits, multiple "integer" values are
        specified by a COMMA-separated list of values.  The valid range
        for "integer" is -2147483648 to 2147483647.  If the sign is not
        specified, then the value is assumed to be positive.

        Example:

        .. code-block:: text

            1234567890
            -1234567890
            +1234567890
            432109876

        .. code-block:: pycon

            >>> from icalendar.prop import vInt
            >>> integer = vInt.from_ical('1234567890')
            >>> integer
            1234567890
            >>> integer = vInt.from_ical('-1234567890')
            >>> integer
            -1234567890
            >>> integer = vInt.from_ical('+1234567890')
            >>> integer
            1234567890
            >>> integer = vInt.from_ical('432109876')
            >>> integer
            432109876
    r
   r   r@   c                  s"   t  j| f||}t||_|S rA   rB   rE   rI   r   r   rD     s    
zvInt.__new__rW   rU   c                 C  s   t | dS ro   rp   r#   r   r   r   r"     s    zvInt.to_icalr   r.   c                 C  s2   z
| |W S  t k
r,   td| Y nX d S )NzExpected int, got: rq   rM   r   r   r   r0     s    
zvInt.from_icalrr   r   r   rI   r   rs   S  s   
0rs   c                   @  sP   e Zd ZU dZded< ded< dd Zdd	 ZedddZdd Z	dd Z
d
S )	vDDDListszA list of vDDDTypes values.r
   r   listdtsc                 C  sl   t |ds|g}g }d }|D ]*}t|}|| d|jkr|jd }qi }|rX||d< t|| _|| _d S )N__iter__TZID)hasattr	vDDDTypesappendr   r
   rv   )r   Zdt_listZvDDDtziddtr   r   r   r   r     s    



zvDDDLists.__init__c                 C  s   dd | j D }d|S )Nc                 s  s   | ]}t | V  qd S rA   )r   r"   ).0r}   r   r   r   	<genexpr>  s     z$vDDDLists.to_ical.<locals>.<genexpr>   ,)rv   join)r   Zdts_icalr   r   r   r"     s    zvDDDLists.to_icalNc                 C  s0   g }|  d}|D ]}|tj||d q|S )N,timezone)splitr{   rz   r0   )r/   r   outZ
ical_datesZical_dtr   r   r   r0     s
    
zvDDDLists.from_icalc                 C  s4   t |tr| j|jkS t |ttfr0| j|gkS dS NF)r3   rt   rv   TimeBaser   r4   r   r   r   r6     s
    
zvDDDLists.__eq__c                 C  s   | j j d| j dS )String representation.(r    )rJ   r7   rv   r#   r   r   r   r$     s    zvDDDLists.__repr__)Nr7   r8   r9   r:   r;   r   r"   r<   r0   r6   r$   r   r   r   r   rt     s   
rt   c                   @  sL   e Zd ZU ded< i fddddZdd Zd	d
 Zedd Zdd Z	dS )	vCategoryr
   r   zlist[str] | str)c_listc                 C  s8   t |drt|tr|g}dd |D | _t|| _d S )Nrw   c                 S  s   g | ]}t |qS r   )rP   r~   cr   r   r   
<listcomp>  s     z&vCategory.__init__.<locals>.<listcomp>)ry   r3   rT   catsr
   r   )r   r   r   r   r   r   r     s    zvCategory.__init__c                 C  s   t t|  S rA   )iterr   r0   r"   r#   r   r   r   rw     s    zvCategory.__iter__c                 C  s   d dd | jD S )Nr   c                 S  s*   g | ]"}t |d r| n
t| qS r!   )ry   r"   rP   r   r   r   r   r     s   z%vCategory.to_ical.<locals>.<listcomp>)r   r   r#   r   r   r   r"     s
    zvCategory.to_icalc                 C  s   t | } t| d}|S )Nr   )r   r   r   )r/   r   r   r   r   r0     s    zvCategory.from_icalc                 C  s   t |to| j|jkS r1   )r3   r   r   r4   r   r   r   r6     s    zvCategory.__eq__N)
r7   r8   r9   r;   r   rw   r"   r<   r0   r6   r   r   r   r   r     s   

r   c                   @  sN   e Zd ZU dZded< ddhZdd Zdd	 Zd
dlm	Z	m
Z
mZ dd ZdS )r   z-Make classes with a datetime/date comparable.r
   r   rx   ZVALUEc                 C  s   t |tr| j|kS t |trt }t| jt|jB | j D ]:}|dd  dkr>| j	|||j	||kr> dS q>| j|jkS t |t
r|| kS dS )r2   N   zx-F)r3   r   r}   r   objectsetr   ignore_for_equalityr`   getrt   )r   r5   defaultkeyr   r   r   r6     s$    


 
zTimeBase.__eq__c                 C  s
   t | jS rA   )hashr}   r#   r   r   r   __hash__  s    zTimeBase.__hash__r   )RANGERELATEDrx   c                 C  s   | j j d| j d| j dS )r   r   , r    )rJ   r7   r}   r   r#   r   r   r   r$     s    zTimeBase.__repr__N)r7   r8   r9   r:   r;   r   r6   r   r[   r   r   rx   r$   r   r   r   r   r     s   
r   c                   @  s8   e Zd ZU dZded< dd Zdd Zedd	d
ZdS )rz   zA combined Datetime, Date or Duration parser/generator. Their format
    cannot be confused, and often values can be of either types.
    So this is practical.
    r
   r   c                 C  s   t |tttttfstdt |ttfr4t | _nBt |trNtddi| _n(t |trhtddi| _ntddi| _t |ttfrt	|nd }|d k	r|dkr| j
d|i || _d S )NzCYou must use datetime, date, timedelta, time or tuple (for periods)r   DATETIMEPERIODUTCrx   )r3   r   r   r   r   tupler,   r
   r   r   updater}   )r   r}   r|   r   r   r   r     s    


zvDDDTypes.__init__c                 C  s   | j }t|trt| S t|tr2t| S t|trHt| S t|t	r^t
| S t|trt|dkrt| S tdt| d S )Nr   zUnknown date type: )r}   r3   r   	vDatetimer"   r   vDater   	vDurationr   vTimer   lenvPeriodr,   typer   r}   r   r   r   r"   #  s    



zvDDDTypes.to_icalNc                 C  s   t || r|jS | }|dr,t|S d|krBtj||dS t|dkr\tj||dS t|dkrrt	|S t|dkrt
|S td| dd S )	N)Pz-Pz+P/r   )         )   r_   z(Expected datetime, date, or time, got: '')r3   r}   upperra   r   r0   r   r   r   r   r   r,   )rF   r/   r   ur   r   r   r0   2  s    




zvDDDTypes.from_ical)N)	r7   r8   r9   r:   r;   r   r"   rN   r0   r   r   r   r   rz     s   
rz   c                   @  s6   e Zd ZU dZded< dd Zdd Zedd	 Zd
S )r   a  Date

    Value Name:
        DATE

    Purpose:
        This value type is used to identify values that contain a
        calendar date.

    Format Definition:
        This value type is defined by the following notation:

        .. code-block:: text

            date               = date-value

            date-value         = date-fullyear date-month date-mday
            date-fullyear      = 4DIGIT
            date-month         = 2DIGIT        ;01-12
            date-mday          = 2DIGIT        ;01-28, 01-29, 01-30, 01-31
                                               ;based on month/year

    Description:
        If the property permits, multiple "date" values are
        specified as a COMMA-separated list of values.  The format for the
        value type is based on the [ISO.8601.2004] complete
        representation, basic format for a calendar date.  The textual
        format specifies a four-digit year, two-digit month, and two-digit
        day of the month.  There are no separator characters between the
        year, month, and day component text.

    Example:
        The following represents July 14, 1997:

        .. code-block:: text

            19970714

        .. code-block:: pycon

            >>> from icalendar.prop import vDate
            >>> date = vDate.from_ical('19970714')
            >>> date.year
            1997
            >>> date.month
            7
            >>> date.day
            14
    r
   r   c                 C  s*   t |tstd|| _tddi| _d S )NzValue MUST be a date instancer   r   )r3   r   r,   r}   r
   r   r   r   r   r   r   {  s    
zvDate.__init__c                 C  s,   | j jd| j jd| j jd}|dS )N0402r%   )r}   yearmonthdayr)   )r   sr   r   r   r"     s    "zvDate.to_icalc                 C  s`   z8t | d d t | dd t | dd f}t| W S  tk
rZ   td|  Y nX d S )N   r   r   zWrong date format )intr   rL   r,   r/   	timetupler   r   r   r0     s    
zvDate.from_icalN	r7   r8   r9   r:   r;   r   r"   r<   r0   r   r   r   r   r   F  s   
2r   c                   @  s<   e Zd ZU dZded< i fddZdd Zedd	d
ZdS )r   a  Render and generates icalendar datetime format.

    vDatetime is timezone aware and uses a timezone library.
    When a vDatetime object is created from an
    ical string, you can pass a valid timezone identifier. When a
    vDatetime object is created from a python datetime object, it uses the
    tzinfo component, if present. Otherwise a timezone-naive object is
    created. Be aware that there are certain limitations with timezone naive
    DATE-TIME components in the icalendar standard.
    r
   r   c                 C  s   || _ t|| _d S rA   )r}   r
   r   )r   r}   r   r   r   r   r     s    zvDatetime.__init__c                 C  st   | j }t|}|jd|jd|jdd|jd|jd|jd}|dkrV|d7 }n|rj| j	d|i |
dS )Nr   r   Tr   Zrx   r%   )r}   r   r   r   r   hourminutesecondr   r   r)   )r   r}   r|   r   r   r   r   r"     s    6
zvDatetime.to_icalNc              
   C  s  d}t |trt|}n|dk	r&|}zt| dd t| dd t| dd t| dd t| dd t| dd f}|rtt| |W S | dd st| W S | dd	 d
krtt| W S t| W n4 t	k
r
 } ztd|  |W 5 d}~X Y nX dS )a  Create a datetime from the RFC string.

        Format:

        .. code-block:: text

            YYYYMMDDTHHMMSS

        .. code-block:: pycon

            >>> from icalendar import vDatetime
            >>> vDatetime.from_ical("20210302T101500")
            datetime.datetime(2021, 3, 2, 10, 15)

            >>> vDatetime.from_ical("20210302T101500", "America/New_York")
            datetime.datetime(2021, 3, 2, 10, 15, tzinfo=ZoneInfo(key='America/New_York'))

            >>> from zoneinfo import ZoneInfo
            >>> timezone = ZoneInfo("Europe/Berlin")
            >>> vDatetime.from_ical("20210302T101500", timezone)
            datetime.datetime(2021, 3, 2, 10, 15, tzinfo=ZoneInfo(key='Europe/Berlin'))
        Nr   r   r   	         r   r   r   zWrong datetime format: )
r3   rT   r   r   r   Zlocalizer   Zlocalize_utcr,   rL   )r/   r   tzinfor   er   r   r   r0     s,    

zvDatetime.from_ical)Nr   r   r   r   r   r     s   
r   c                   @  sL   e Zd ZU dZded< i fddZdd Zedd	 Ze	d
dddZ
dS )r   a	  Duration

    Value Name:
        DURATION

    Purpose:
        This value type is used to identify properties that contain
        a duration of time.

    Format Definition:
        This value type is defined by the following notation:

        .. code-block:: text

            dur-value  = (["+"] / "-") "P" (dur-date / dur-time / dur-week)

            dur-date   = dur-day [dur-time]
            dur-time   = "T" (dur-hour / dur-minute / dur-second)
            dur-week   = 1*DIGIT "W"
            dur-hour   = 1*DIGIT "H" [dur-minute]
            dur-minute = 1*DIGIT "M" [dur-second]
            dur-second = 1*DIGIT "S"
            dur-day    = 1*DIGIT "D"

    Description:
        If the property permits, multiple "duration" values are
        specified by a COMMA-separated list of values.  The format is
        based on the [ISO.8601.2004] complete representation basic format
        with designators for the duration of time.  The format can
        represent nominal durations (weeks and days) and accurate
        durations (hours, minutes, and seconds).  Note that unlike
        [ISO.8601.2004], this value type doesn't support the "Y" and "M"
        designators to specify durations in terms of years and months.
        The duration of a week or a day depends on its position in the
        calendar.  In the case of discontinuities in the time scale, such
        as the change from standard time to daylight time and back, the
        computation of the exact duration requires the subtraction or
        addition of the change of duration of the discontinuity.  Leap
        seconds MUST NOT be considered when computing an exact duration.
        When computing an exact duration, the greatest order time
        components MUST be added first, that is, the number of days MUST
        be added first, followed by the number of hours, number of
        minutes, and number of seconds.

    Example:
        A duration of 15 days, 5 hours, and 20 seconds would be:

        .. code-block:: text

            P15DT5H0M20S

        A duration of 7 weeks would be:

        .. code-block:: text

            P7W

        .. code-block:: pycon

            >>> from icalendar.prop import vDuration
            >>> duration = vDuration.from_ical('P15DT5H0M20S')
            >>> duration
            datetime.timedelta(days=15, seconds=18020)
            >>> duration = vDuration.from_ical('P7W')
            >>> duration
            datetime.timedelta(days=49)
    r
   r   c                 C  s&   t |tstd|| _t|| _d S )Nz"Value MUST be a timedelta instancer3   r   r,   tdr
   r   r   r   r   r   r   r   r   )  s    
zvDuration.__init__c                 C  s   d}| j }|jdk rd}| }d}|jrd}|jd }|jd d }|jd }|r`|| d7 }|sl|rz|rz|| d7 }|r|| d	7 }|jdkr|rt|d
d t|d
 S t|d
d tt|jd
 d t|d
 S d S )N r   -r     <   HMSr%      P   D)r   dayssecondsrT   r)   abs)r   signr   Ztimeparthoursminutesr   r   r   r   r"   /  s:    


 zvDuration.to_icalc           	      C  s|   t | }|std|  | \}}}}}}tt|p:dt|pDdt|pNdt|pXdt|pbdd}|dkrx| }|S )NzInvalid iCalendar duration: r   )weeksr   r   r   r   r   )DURATION_REGEXmatchr,   groupsr   r   )	r/   r   r   r   r   r   r   r   r   r   r   r   r0   L  s    





zvDuration.from_icalr   rU   c                 C  s   | j S )z!The time delta for compatibility.r   r#   r   r   r   r}   `  s    zvDuration.dtN)r7   r8   r9   r:   r;   r   r"   r<   r0   rl   r}   r   r   r   r   r     s   
D
r   c                   @  sf   e Zd ZU dZded< ddddZdd	 Zd
d ZedddZ	dd Z
edd ZddlmZ dS )r   a"	  Period of Time

    Value Name:
        PERIOD

    Purpose:
        This value type is used to identify values that contain a
        precise period of time.

    Format Definition:
        This value type is defined by the following notation:

        .. code-block:: text

            period     = period-explicit / period-start

           period-explicit = date-time "/" date-time
           ; [ISO.8601.2004] complete representation basic format for a
           ; period of time consisting of a start and end.  The start MUST
           ; be before the end.

           period-start = date-time "/" dur-value
           ; [ISO.8601.2004] complete representation basic format for a
           ; period of time consisting of a start and positive duration
           ; of time.

    Description:
        If the property permits, multiple "period" values are
        specified by a COMMA-separated list of values.  There are two
        forms of a period of time.  First, a period of time is identified
        by its start and its end.  This format is based on the
        [ISO.8601.2004] complete representation, basic format for "DATE-
        TIME" start of the period, followed by a SOLIDUS character
        followed by the "DATE-TIME" of the end of the period.  The start
        of the period MUST be before the end of the period.  Second, a
        period of time can also be defined by a start and a positive
        duration of time.  The format is based on the [ISO.8601.2004]
        complete representation, basic format for the "DATE-TIME" start of
        the period, followed by a SOLIDUS character, followed by the
        [ISO.8601.2004] basic format for "DURATION" of the period.

    Example:
        The period starting at 18:00:00 UTC, on January 1, 1997 and
        ending at 07:00:00 UTC on January 2, 1997 would be:

        .. code-block:: text

            19970101T180000Z/19970102T070000Z

        The period start at 18:00:00 on January 1, 1997 and lasting 5 hours
        and 30 minutes would be:

        .. code-block:: text

            19970101T180000Z/PT5H30M

        .. code-block:: pycon

            >>> from icalendar.prop import vPeriod
            >>> period = vPeriod.from_ical('19970101T180000Z/19970102T070000Z')
            >>> period = vPeriod.from_ical('19970101T180000Z/PT5H30M')
    r
   r   z+tuple[datetime, Union[datetime, timedelta]])perc                 C  s   |\}}t |ts$t |ts$tdt |tsJt |tsJt |tsJtdd}t |trjd}|}|| }n|}|| }||krtdtddi| _t|}|r|| jd< || _|| _	|| _
|| _d S )	Nz/Start value MUST be a datetime or date instancez>end_or_duration MUST be a datetime, date or timedelta instancer   r   z#Start time is greater than end timer   r   rx   )r3   r   r   r,   r   r
   r   r   startendby_durationduration)r   r   r   end_or_durationr   r   r   r|   r   r   r   r     s:    


zvPeriod.__init__c                 C  s<   | j |j kr|| S | j |j   kr0| jk r8n ndS dS )NTF)r   overlapsr   r4   r   r   r   r     s
    
zvPeriod.overlapsc                 C  sF   | j r&t| j d t| j  S t| j d t| j  S )N   /)r   r   r   r"   r   r   r   r#   r   r   r   r"     s    zvPeriod.to_icalNc                 C  s\   z4|  d\}}tj||d}tj||d}||fW S  tk
rV   td|  Y nX d S )Nr   r   zExpected period format, got: )r   rz   r0   rL   r,   )r/   r   r   r   r   r   r   r0     s    
zvPeriod.from_icalc                 C  s,   | j r| j| jf}n| j| jf}d|dS )NzvPeriod(r    )r   r   r   r   )r   pr   r   r   r$     s    zvPeriod.__repr__c                 C  s   | j | jr| jn| jfS )z-Make this cooperate with the other vDDDTypes.)r   r   r   r   r#   r   r   r   r}     s    z
vPeriod.dtr   )FBTYPE)N)r7   r8   r9   r:   r;   r   r   r"   r<   r0   r$   rl   r}   r[   r   r   r   r   r   r   f  s   
?#		
r   c                	      s\   e Zd ZU dZded< edddddd	d
dZei f fdd	Zdd Z	e
dd Z  ZS )vWeekdaya5  Either a ``weekday`` or a ``weekdaynum``

    .. code-block:: pycon

        >>> from icalendar import vWeekday
        >>> vWeekday("MO") # Simple weekday
        'MO'
        >>> vWeekday("2FR").relative # Second friday
        2
        >>> vWeekday("2FR").weekday
        'FR'
        >>> vWeekday("-1SU").relative # Last Sunday
        -1

    Definition from `RFC 5545, Section 3.3.10 <https://www.rfc-editor.org/rfc/rfc5545#section-3.3.10>`_:

    .. code-block:: text

        weekdaynum = [[plus / minus] ordwk] weekday
        plus        = "+"
        minus       = "-"
        ordwk       = 1*2DIGIT       ;1 to 53
        weekday     = "SU" / "MO" / "TU" / "WE" / "TH" / "FR" / "SA"
        ;Corresponding to SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
        ;FRIDAY, and SATURDAY days of the week.

    r
   r   r   r   r      r      r   )ZSUZMOZTUZWEZTHZFRZSAc           	        s   t ||d}t | |}t|}|d kr:td| | }|d }|d }|d }|tjksl|dkrztd| |pd |_	|rt
|pd |_|dkr|jr| jd9  _t||_|S )	NrR   #Expected weekday abbrevation, got: signalweekdayrelativez+-r   r&   )r   rC   rD   WEEKDAY_RULEr   r,   	groupdictr   	week_daysr   r   r   r
   r   )	rF   r   r   r   r   r   r   r   r   rI   r   r   rD     s"    


zvWeekday.__new__c                 C  s   |  t S rA   r)   r   r   r#   r   r   r   r"   2  s    zvWeekday.to_icalc                 C  s6   z| |  W S  tk
r0   td| Y nX d S )Nr   r   rL   r,   rM   r   r   r   r0   5  s    zvWeekday.from_ical)r7   r8   r9   r:   r;   r   r   r   rD   r"   rN   r0   rO   r   r   rI   r   r     s    
r   c                	      s\   e Zd ZU dZded< edddddd	d
dZei f fdd	Zdd Z	e
dd Z  ZS )
vFrequencyz+A simple class that catches illegal values.r
   r   SECONDLYMINUTELYHOURLYDAILYWEEKLYMONTHLYYEARLY)r   r   r   r   r   r   r   c                   s@   t ||d}t | |}|tjkr2td| t||_|S )NrR   Expected frequency, got: )r   rC   rD   r   frequenciesr,   r
   r   rS   rI   r   r   rD   N  s    

zvFrequency.__new__c                 C  s   |  t S rA   r   r#   r   r   r   r"   V  s    zvFrequency.to_icalc                 C  s6   z| |  W S  tk
r0   td| Y nX d S )Nr   r   rM   r   r   r   r0   Y  s    zvFrequency.from_ical)r7   r8   r9   r:   r;   r   r  r   rD   r"   rN   r0   rO   r   r   rI   r   r   =  s    
r   c                      s   e Zd ZU dZded< i fdd fddZdd	d
dZeddddZdd Z	e
f e	 Z	dd	ddZdd	ddZ  ZS )vMonthaf  The number of the month for recurrence.

    In :rfc:`5545`, this is just an int.
    In :rfc:`7529`, this can be followed by `L` to indicate a leap month.

    .. code-block:: pycon

        >>> from icalendar import vMonth
        >>> vMonth(1) # first month January
        vMonth('1')
        >>> vMonth("5L") # leap month in Hebrew calendar
        vMonth('5L')
        >>> vMonth(1).leap
        False
        >>> vMonth("5L").leap
        True

    Definition from RFC:

    .. code-block:: text

        type-bymonth = element bymonth {
           xsd:positiveInteger |
           xsd:string
        }
    r
   r   zUnion[str, int])r   c                   s   t |tr| |  S t |trz| r:t|}d}q|d dkrd|d d  rdtd|t|d d }d}nd}t|}t 	| |}||_
t||_|S )NFr&   LzInvalid month: T)r3   r  r"   decoderT   isdigitr   r,   rC   rD   leapr
   r   )rF   r   r   Zmonth_indexr  r   rI   r   r   rD     s     


zvMonth.__new__rW   rU   c                 C  s   t | dS )zThe ical representation.r%   rp   r#   r   r   r   r"     s    zvMonth.to_icalrT   r.   c                 C  s   | |S rA   r   rM   r   r   r   r0     s    zvMonth.from_icalc                  C  s(   d} dddd}ddddd	}t  S )
NzWhether this is a leap month.boolrU   c                 S  s   | j S rA   Z_leapr#   r   r   r   fget  s    zvMonth.leap.<locals>.fgetNone)r   rV   c                 S  s
   || _ d S rA   r  )r   r   r   r   r   fset  s    zvMonth.leap.<locals>.fset)locals)docr	  r  r   r   r   r    s    zvMonth.leapc                 C  s   | j j dt| dS )
repr(self)r   r    )rJ   r7   rT   r#   r   r   r   r$     s    zvMonth.__repr__c                 C  s   t |  | jrdnd S )z	str(self)r  r   )r   r  r#   r   r   r   __str__  s    zvMonth.__str__)r7   r8   r9   r:   r;   rD   r"   rN   r0   r  rl   r$   r  rO   r   r   rI   r   r  a  s   
r  c                   @  s*   e Zd ZdZdZdZdZejZdd Z	dS )vSkipaK  Skip values for RRULE.

    These are defined in :rfc:`7529`.

    OMIT  is the default value.

    Examples:

    .. code-block:: pycon

        >>> from icalendar import vSkip
        >>> vSkip.OMIT
        vSkip('OMIT')
        >>> vSkip.FORWARD
        vSkip('FORWARD')
        >>> vSkip.BACKWARD
        vSkip('BACKWARD')
    OMITFORWARDBACKWARDc                 C  s   | j j d| jdS )Nr   r    )rJ   r7   _name_r#   r   r   r   r$     s    zvSkip.__repr__N)
r7   r8   r9   r:   r  r  r  r	   __reduce_ex__r$   r   r   r   r   r    s   r  c                      s   e Zd ZU dZded< dddddd	d
gZdZeeeeeeeeee	e
eeeeeedZi d fdd
Zdd Zedd ZeddddZ  ZS )vRecura  Recurrence definition.

    Property Name:
        RRULE

    Purpose:
        This property defines a rule or repeating pattern for recurring events, to-dos,
        journal entries, or time zone definitions.

    Value Type:
        RECUR

    Property Parameters:
        IANA and non-standard property parameters can be specified on this property.

    Conformance:
        This property can be specified in recurring "VEVENT", "VTODO", and "VJOURNAL"
        calendar components as well as in the "STANDARD" and "DAYLIGHT" sub-components
        of the "VTIMEZONE" calendar component, but it SHOULD NOT be specified more than once.
        The recurrence set generated with multiple "RRULE" properties is undefined.

    Description:
        The recurrence rule, if specified, is used in computing the recurrence set.
        The recurrence set is the complete set of recurrence instances for a calendar component.
        The recurrence set is generated by considering the initial "DTSTART" property along
        with the "RRULE", "RDATE", and "EXDATE" properties contained within the
        recurring component. The "DTSTART" property defines the first instance in the
        recurrence set. The "DTSTART" property value SHOULD be synchronized with the
        recurrence rule, if specified. The recurrence set generated with a "DTSTART" property
        value not synchronized with the recurrence rule is undefined.
        The final recurrence set is generated by gathering all of the start DATE-TIME
        values generated by any of the specified "RRULE" and "RDATE" properties, and then
        excluding any start DATE-TIME values specified by "EXDATE" properties.
        This implies that start DATE- TIME values specified by "EXDATE" properties take
        precedence over those specified by inclusion properties (i.e., "RDATE" and "RRULE").
        Where duplicate instances are generated by the "RRULE" and "RDATE" properties,
        only one recurrence is considered. Duplicate instances are ignored.

        The "DTSTART" property specified within the iCalendar object defines the first
        instance of the recurrence. In most cases, a "DTSTART" property of DATE-TIME value
        type used with a recurrence rule, should be specified as a date with local time
        and time zone reference to make sure all the recurrence instances start at the
        same local time regardless of time zone changes.

        If the duration of the recurring component is specified with the "DTEND" or
        "DUE" property, then the same exact duration will apply to all the members of the
        generated recurrence set. Else, if the duration of the recurring component is
        specified with the "DURATION" property, then the same nominal duration will apply
        to all the members of the generated recurrence set and the exact duration of each
        recurrence instance will depend on its specific start time. For example, recurrence
        instances of a nominal duration of one day will have an exact duration of more or less
        than 24 hours on a day where a time zone shift occurs. The duration of a specific
        recurrence may be modified in an exception component or simply by using an
        "RDATE" property of PERIOD value type.

    Examples:
        The following RRULE specifies daily events for 10 occurrences.

        .. code-block:: text

            RRULE:FREQ=DAILY;COUNT=10

        Below, we parse the RRULE ical string.

        .. code-block:: pycon

            >>> from icalendar.prop import vRecur
            >>> rrule = vRecur.from_ical('FREQ=DAILY;COUNT=10')
            >>> rrule
            vRecur({'FREQ': ['DAILY'], 'COUNT': [10]})

        You can choose to add an rrule to an :class:`icalendar.cal.Event` or
        :class:`icalendar.cal.Todo`.

        .. code-block:: pycon

            >>> from icalendar import Event
            >>> event = Event()
            >>> event.add('RRULE', 'FREQ=DAILY;COUNT=10')
            >>> event.rrules
            [vRecur({'FREQ': ['DAILY'], 'COUNT': [10]})]
    r
   r   r   r   r   r   r   r   r   )ZRSCALEFREQUNTILCOUNTINTERVALBYSECONDBYMINUTEBYHOURBYDAY	BYWEEKDAY
BYMONTHDAY	BYYEARDAYBYWEEKNOBYMONTHBYSETPOSWKSTSKIP)r  r  r  r  r  r"  r   r!  r#  r  r$  r%  r  r  r  r&  r@   c                  sp   |r.t |d tr.| |d f|dd   }| D ]\}}t |ts6|g||< q6t j|| t|| _d S )Nr   r   )	r3   rT   r0   itemsr   rC   r   r
   r   )r   r   rG   rH   kvrI   r   r   r   Z  s    
zvRecur.__init__c                   sr   g }|   D ]Z\}}| j|t t|ts2|g}d fdd|D }|t}|	|d |  qd|S )Nr   c                 3  s   | ]} |  V  qd S rA   r!   )r~   valtypr   r   r   j  s     z!vRecur.to_ical.<locals>.<genexpr>   =   ;)
Zsorted_itemstypesr   rP   r3   r   r   r)   r   r{   )r   resultr   valsr   r+  r   r"   d  s    

zvRecur.to_icalc                   s&   | j |t  fdd|dD S )Nc                   s   g | ]}  |qS r   )r0   )r~   r)  parserr   r   r   v  s     z%vRecur.parse_type.<locals>.<listcomp>r   )r/  r   rP   r   )rF   r   valuesr   r2  r   
parse_typer  s    zvRecur.parse_typerT   r.   c              	   C  s   t || r|S z\|  }|dD ]@}z|d\}}W n tk
rN   Y q Y nX | ||||< q | |W S  tk
r    Y n   td| Y nX d S )N;=zError in recurrence rule: )r3   r   r,   r5  )rF   r/   recurpairsr   r1  r   r   r   r0   x  s    


zvRecur.from_ical)r7   r8   r9   r:   r;   r  Zcanonical_orderr   rs   r  rz   r   r   r  r/  r   r"   rN   r5  r0   rO   r   r   rI   r   r    sH   
S

r  c                   @  s,   e Zd ZdZdd Zdd Zedd ZdS )	r   a  Time

    Value Name:
        TIME

    Purpose:
        This value type is used to identify values that contain a
        time of day.

    Format Definition:
        This value type is defined by the following notation:

        .. code-block:: text

            time         = time-hour time-minute time-second [time-utc]

            time-hour    = 2DIGIT        ;00-23
            time-minute  = 2DIGIT        ;00-59
            time-second  = 2DIGIT        ;00-60
            ;The "60" value is used to account for positive "leap" seconds.

            time-utc     = "Z"

    Description:
        If the property permits, multiple "time" values are
        specified by a COMMA-separated list of values.  No additional
        content value encoding (i.e., BACKSLASH character encoding, see
        vText) is defined for this value type.

        The "TIME" value type is used to identify values that contain a
        time of day.  The format is based on the [ISO.8601.2004] complete
        representation, basic format for a time of day.  The text format
        consists of a two-digit, 24-hour of the day (i.e., values 00-23),
        two-digit minute in the hour (i.e., values 00-59), and two-digit
        seconds in the minute (i.e., values 00-60).  The seconds value of
        60 MUST only be used to account for positive "leap" seconds.
        Fractions of a second are not supported by this format.

        In parallel to the "DATE-TIME" definition above, the "TIME" value
        type expresses time values in three forms:

        The form of time with UTC offset MUST NOT be used.  For example,
        the following is not valid for a time value:

        .. code-block:: text

            230000-0800        ;Invalid time format

        **FORM #1 LOCAL TIME**

        The local time form is simply a time value that does not contain
        the UTC designator nor does it reference a time zone.  For
        example, 11:00 PM:

        .. code-block:: text

            230000

        Time values of this type are said to be "floating" and are not
        bound to any time zone in particular.  They are used to represent
        the same hour, minute, and second value regardless of which time
        zone is currently being observed.  For example, an event can be
        defined that indicates that an individual will be busy from 11:00
        AM to 1:00 PM every day, no matter which time zone the person is
        in.  In these cases, a local time can be specified.  The recipient
        of an iCalendar object with a property value consisting of a local
        time, without any relative time zone information, SHOULD interpret
        the value as being fixed to whatever time zone the "ATTENDEE" is
        in at any given moment.  This means that two "Attendees", may
        participate in the same event at different UTC times; floating
        time SHOULD only be used where that is reasonable behavior.

        In most cases, a fixed time is desired.  To properly communicate a
        fixed time in a property value, either UTC time or local time with
        time zone reference MUST be specified.

        The use of local time in a TIME value without the "TZID" property
        parameter is to be interpreted as floating time, regardless of the
        existence of "VTIMEZONE" calendar components in the iCalendar
        object.

        **FORM #2: UTC TIME**

        UTC time, or absolute time, is identified by a LATIN CAPITAL
        LETTER Z suffix character, the UTC designator, appended to the
        time value.  For example, the following represents 07:00 AM UTC:

        .. code-block:: text

            070000Z

        The "TZID" property parameter MUST NOT be applied to TIME
        properties whose time values are specified in UTC.

        **FORM #3: LOCAL TIME AND TIME ZONE REFERENCE**

        The local time with reference to time zone information form is
        identified by the use the "TZID" property parameter to reference
        the appropriate time zone definition.

        Example:
            The following represents 8:30 AM in New York in winter,
            five hours behind UTC, in each of the three formats:

        .. code-block:: text

            083000
            133000Z
            TZID=America/New_York:083000
    c                 G  sX   t |dkr<t|d ttfs0td|d  |d | _n
t| | _tddi| _d S )Nr   r   zExpected a datetime.time, got: r   r   )r   r3   r   r   r,   r}   r
   r   )r   rG   r   r   r   r     s    
zvTime.__init__c                 C  s   | j dS )Nz%H%M%S)r}   strftimer#   r   r   r   r"     s    zvTime.to_icalc                 C  s`   z8t | d d t | dd t | dd f}t| W S  tk
rZ   td|  Y nX d S )Nr   r   r   zExpected time, got: )r   r   rL   r,   r   r   r   r   r0   	  s
    .
zvTime.from_icalN)r7   r8   r9   r:   r   r"   r<   r0   r   r   r   r   r     s
   o	r   c                      sD   e Zd ZU dZded< ei f fdd	Zdd Zedd	 Z	  Z
S )
vUria  URI

    Value Name:
        URI

    Purpose:
        This value type is used to identify values that contain a
        uniform resource identifier (URI) type of reference to the
        property value.

    Format Definition:
        This value type is defined by the following notation:

        .. code-block:: text

            uri = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

    Description:
        This value type might be used to reference binary
        information, for values that are large, or otherwise undesirable
        to include directly in the iCalendar object.

        Property values with this value type MUST follow the generic URI
        syntax defined in [RFC3986].

        When a property parameter value is a URI value type, the URI MUST
        be specified as a quoted-string value.

        Example:
            The following is a URI for a network file:

            .. code-block:: text

                http://example.com/my-report.txt

            .. code-block:: pycon

                >>> from icalendar.prop import vUri
                >>> uri = vUri.from_ical('http://example.com/my-report.txt')
                >>> uri
                'http://example.com/my-report.txt'
    r
   r   c                   s(   t ||d}t | |}t||_|S rQ   r]   rS   rI   r   r   rD   A  s    
zvUri.__new__c                 C  s
   |  tS rA   r^   r#   r   r   r   r"   G  s    zvUri.to_icalc                 C  s2   z
| |W S  t k
r,   td| Y nX d S )NzExpected , got: rq   rM   r   r   r   r0   J  s    
zvUri.from_icalr7   r8   r9   r:   r;   r   rD   r"   rN   r0   rO   r   r   rI   r   r;    s   
+r;  c                   @  sP   e Zd ZU dZded< i fddddZdd	 Zed
d Zdd Z	dd Z
dS )vGeoa  Geographic Position

    Property Name:
        GEO

    Purpose:
        This property specifies information related to the global
        position for the activity specified by a calendar component.

    Value Type:
        FLOAT.  The value MUST be two SEMICOLON-separated FLOAT values.

    Property Parameters:
        IANA and non-standard property parameters can be specified on
        this property.

    Conformance:
        This property can be specified in "VEVENT" or "VTODO"
        calendar components.

    Description:
        This property value specifies latitude and longitude,
        in that order (i.e., "LAT LON" ordering).  The longitude
        represents the location east or west of the prime meridian as a
        positive or negative real number, respectively.  The longitude and
        latitude values MAY be specified up to six decimal places, which
        will allow for accuracy to within one meter of geographical
        position.  Receiving applications MUST accept values of this
        precision and MAY truncate values of greater precision.

        Example:

        .. code-block:: text

            GEO:37.386013;-122.082932

        Parse vGeo:

        .. code-block:: pycon

            >>> from icalendar.prop import vGeo
            >>> geo = vGeo.from_ical('37.386013;-122.082932')
            >>> geo
            (37.386013, -122.082932)

        Add a geo location to an event:

        .. code-block:: pycon

            >>> from icalendar import Event
            >>> event = Event()
            >>> latitude = 37.386013
            >>> longitude = -122.082932
            >>> event.add('GEO', (latitude, longitude))
            >>> event['GEO']
            vGeo((37.386013, -122.082932))
    r
   r   z+tuple[float | str | int, float | str | int])geoc              
   C  sn   z&|d |d  }}t |}t |}W n, tk
rR } ztd|W 5 d}~X Y nX || _|| _t|| _dS )zCreate a new vGeo from a tuple of (latitude, longitude).

        Raises:
            ValueError: if geo is not a tuple of (latitude, longitude)
        r   r   z7Input must be (float, float) for latitude and longitudeN)floatrL   r,   latitude	longituder
   r   )r   r>  r   r@  rA  r   r   r   r   r     s    zvGeo.__init__c                 C  s   | j  d| j S )Nr6  )r@  rA  r#   r   r   r   r"     s    zvGeo.to_icalc              
   C  sX   z |  d\}}t|t|fW S  tk
rR } ztd|  |W 5 d }~X Y nX d S )Nr6  zExpected 'float;float' , got: )r   r?  rL   r,   )r/   r@  rA  r   r   r   r   r0     s
    zvGeo.from_icalc                 C  s   |   |  kS rA   r!   r4   r   r   r   r6     s    zvGeo.__eq__c                 C  s   | j j d| j d| j dS )r  z((r   z)))rJ   r7   r@  rA  r#   r   r   r   r$     s    zvGeo.__repr__Nr   r   r   r   r   r=  R  s   
:
r=  c                   @  sV   e Zd ZU dZded< dZi fddZdd Zed	d
 Z	dd Z
dd Zdd ZdS )
vUTCOffsetai  UTC Offset

    Value Name:
        UTC-OFFSET

    Purpose:
        This value type is used to identify properties that contain
        an offset from UTC to local time.

    Format Definition:
        This value type is defined by the following notation:

        .. code-block:: text

            utc-offset = time-numzone

            time-numzone = ("+" / "-") time-hour time-minute [time-second]

    Description:
        The PLUS SIGN character MUST be specified for positive
        UTC offsets (i.e., ahead of UTC).  The HYPHEN-MINUS character MUST
        be specified for negative UTC offsets (i.e., behind of UTC).  The
        value of "-0000" and "-000000" are not allowed.  The time-second,
        if present, MUST NOT be 60; if absent, it defaults to zero.

        Example:
            The following UTC offsets are given for standard time for
            New York (five hours behind UTC) and Geneva (one hour ahead of
            UTC):

        .. code-block:: text

            -0500

            +0100

        .. code-block:: pycon

            >>> from icalendar.prop import vUTCOffset
            >>> utc_offset = vUTCOffset.from_ical('-0500')
            >>> utc_offset
            datetime.timedelta(days=-1, seconds=68400)
            >>> utc_offset = vUTCOffset.from_ical('+0100')
            >>> utc_offset
            datetime.timedelta(seconds=3600)
    r
   r   Fc                 C  s&   t |tstd|| _t|| _d S )Nz)Offset value MUST be a timedelta instancer   r   r   r   r   r     s    
zvUTCOffset.__init__c                 C  s   | j tdk r"d}td| j  }n
d}| j }|j|j }}t|d |d  }t|d d }t|d }|r|d|d|d}n|d|d}|| S )Nr   z-%sz+%s   r   r   r   )r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r"     s    zvUTCOffset.to_icalc                 C  s   t || r|jS zV|dd t|dd t|dd t|dd pHdf\}}}}t|||d}W n" tk
r   td| Y nX | js|tdd	krtd
| |dkr| S |S )Nr   r   r   r   r_   )r   r   r   zExpected utc offset, got: rC  )r   z'Offset must be less than 24 hours, was r   )r3   r   r   r   rL   r,   ignore_exceptions)rF   r/   r   r   r   r   offsetr   r   r   r0     s     

zvUTCOffset.from_icalc                 C  s   t |tsdS | j|jkS r   )r3   rB  r   r4   r   r   r   r6     s    
zvUTCOffset.__eq__c                 C  s
   t | jS rA   )r   r   r#   r   r   r   r     s    zvUTCOffset.__hash__c                 C  s   d| j dS )NzvUTCOffset(r    r   r#   r   r   r   r$   "  s    zvUTCOffset.__repr__N)r7   r8   r9   r:   r;   rD  r   r"   rN   r0   r6   r   r$   r   r   r   r   rB    s   
/
rB  c                      sD   e Zd ZU dZded< ei f fdd	Zdd Zedd	 Z	  Z
S )
vInlinezThis is an especially dumb class that just holds raw unparsed text and
    has parameters. Conversion of inline values are handled by the Component
    class, so no further processing is needed.
    r
   r   c                   s(   t ||d}t | |}t||_|S rQ   r]   rS   rI   r   r   rD   .  s    
zvInline.__new__c                 C  s
   |  tS rA   r^   r#   r   r   r   r"   4  s    zvInline.to_icalc                 C  s   | |S rA   r   rM   r   r   r   r0   7  s    zvInline.from_icalr<  r   r   rI   r   rF  &  s   
rF  c                E      s   e Zd ZdZ fddZeddddddddddddddddd	d	d	d	d
ddddddddddd	dddddddddd
d	d	d	d	ddddddddddddddddddddddCZdd Zdd Zdd Z	  Z
S )TypesFactoryzAll Value types defined in RFC 5545 are registered in this factory
    class.

    The value and parameter names don't overlap. So one factory is enough for
    both kinds.
    c                   s   t  j|| tttttttt	t
ttttttttttttf| _t| d< t| d< t| d< t| d< t| d< t| d< t
| d< t| d< t| d	< t| d
< t| d< t| d< t| d< t| d< t| d< t| d< t| d< t| d< dS )z"Set keys to upper for initial dictbinarybooleancal-addressr   	date-timer   r?  integerperiodr8  textr   uri
utc-offsetr>  inlinedate-time-list
categoriesN)rC   r   r   r=   r\   rt   rz   r   r   r   rn   r   r=  rF  rs   r   r  rP   r   rB  r;  r   r   Z	all_types)r   rG   rH   rI   r   r   r   D  sR    zTypesFactory.__init__rN  rO  rS  r>  rL  rK  r   rM  rP  rJ  rR  r8  rI  )CZcalscalemethodZprodidversionattachrS  classcommentdescriptionr>  locationzpercent-completepriority	resourcesstatussummaryZ	completedZdtendZdueZdtstartr   ZfreebusyZtranspr|   tznameZtzoffsetfromZ
tzoffsettoZtzurlZattendeecontactZ	organizerzrecurrence-idz
related-tourluidZexdateZexruleZrdateZrruleactionrepeatZtriggerZacknowledgedcreatedZdtstampzlast-modifiedsequencezrequest-statusZaltrepZcnZcutypezdelegated-fromzdelegated-todirr   ZfmttypeZfbtypelanguagememberZpartstatrangerelatedZreltyperoleZrsvpzsent-byr   c                 C  s   | | j |d S )z6Returns a the default type for a property or parameterrN  )	types_mapr   )r   rm   r   r   r   for_property  s    zTypesFactory.for_propertyc                 C  s   |  |}|| S )zcEncodes a named value from a primitive python type to an icalendar
        encoded string.
        )rn  r"   )r   rm   r   
type_classr   r   r   r"     s    
zTypesFactory.to_icalc                 C  s   |  |}||}|S )zyDecodes a named property or parameter value from an icalendar
        encoded string to a primitive python type.
        )rn  r0   )r   rm   r   ro  decodedr   r   r   r0     s    

zTypesFactory.from_ical)r7   r8   r9   r:   r   r   rm  rn  r"   r0   rO   r   r   rI   r   rG  <  s   1UrG  r   r   r   r   )>r:   
__future__r   r*   r'   rer   r   r   r   typingr   Zicalendar.caselessdictr   Zicalendar.enumsr	   Zicalendar.parserr
   r   r   Zicalendar.parser_toolsr   r   r   r   r   r   r   r   r   compiler   r   r   r   r=   rT   rP   r\   r?  rn   rs   rt   r   r   rz   r   r   r   r   r   r   r  r  r  r   r;  r=  rB  rF  rG  __all__r   r   r   r   <module>   s   ,;X@C0"?LP  I$P ? ?br $