o
    g +                     @   sB   d Z ddlmZ ddlmZmZ dd Zdd ZG dd	 d	Zd
S )z
This module defines a Duration class.

The class Duration allows to define durations in years and months and can be
used as limited replacement for timedelta objects.
    )	timedelta)ROUND_FLOORDecimalc                 C   s@   | | || }}||  t}|||  }||7 }t||fS )z-
    A divmod function with boundaries.

    )to_integralr   int)vallowhighabdivmod r   I/home/ubuntu/webapp/venv/lib/python3.10/site-packages/isodate/duration.pyfquotmod   s
   r   c                 C   sD   |dv rdS |dv rdS | d dks| d dkr | d dkr d	S d
S )zO
    Determines the number of days of a specific month in a specific year.
    )               
         )      	         i  r   d   r         r   )yearmonthr   r   r   max_days_in_month   s   $r#   c                   @   s   e Zd ZdZ									d"ddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd ZeZdd ZeZdd Zdd Zdd Zdd Zd#d d!ZdS )$DurationaY  
    A class which represents a duration.

    The difference to datetime.timedelta is, that this class handles also
    differences given in years and months.
    A Duration treats differences given in year, months separately from all
    other components.

    A Duration can be used almost like any timedelta object, however there
    are some restrictions:
      * It is not really possible to compare Durations, because it is unclear,
        whether a duration of 1 year is bigger than 365 days or not.
      * Equality is only tested between the two (year, month vs. timedelta)
        basic components.

    A Duration can also be converted into a datetime object, but this requires
    a start date or an end date.

    The algorithm to add a duration to a date is defined at
    http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
    r   c
           
      C   sR   t |tstt|}t |	tstt|	}	|| _|	| _t|||||||| _dS )zN
        Initialise this Duration instance with the given parameters.
        N)
isinstancer   strmonthsyearsr   tdelta)
selfdayssecondsmicrosecondsmillisecondsminuteshoursweeksr'   r(   r   r   r   __init__A   s   


zDuration.__init__c                 C   s   | j S N)__dict__r*   r   r   r   __getstate__Z   s   zDuration.__getstate__c                 C   s   | j | d S r3   )r4   update)r*   stater   r   r   __setstate__]   s   zDuration.__setstate__c                 C   s   t | j|S )zU
        Provide direct access to attributes of included timedelta instance.
        )getattrr)   )r*   namer   r   r   __getattr__`   s   zDuration.__getattr__c                 C   s\   g }| j r|d| j   | jr!d}| jdkrd}||| j  |t| j d|S )zW
        Return a string representation of this duration similar to timedelta.
        z%d yearsz	%d monthsr   z%d monthz, )r(   appendr'   r&   r)   join)r*   paramsfmtr   r   r   __str__f   s   

zDuration.__str__c                 C   s.   d| j j| j j| jj| jj| jj| j| jf S )z=
        Return a string suitable for repr(x) calls.
        z&%s.%s(%d, %d, %d, years=%d, months=%d))		__class__
__module____name__r)   r+   r,   r-   r(   r'   r5   r   r   r   __repr__u   s   zDuration.__repr__c                 C   s   t | j| j| jfS )zp
        Return a hash of this instance so that it can be used in, for
        example, dicts and sets.
        )hashr)   r'   r(   r5   r   r   r   __hash__   s   zDuration.__hash__c                 C   s"   t | j | j d}| j |_|S )zg
        A simple unary minus.

        Returns a new Duration instance with all it's negated.
        r(   r'   )r$   r(   r'   r)   )r*   negdurationr   r   r   __neg__   s   
zDuration.__neg__c           	      C   s  t |trt| j|j | j|j d}| j|j |_|S zLt| j r+t| j s/td|j| j }t	|dd\}}|j
| j | }t||}|j|krR|}n|j}|jt|t|t|d}| j| W S  tyq   Y nw zt| j| jd}| j| |_|W S  ty   Y tS w )ze
        Durations can be added with Duration, timedelta, date and datetime
        objects.
        rH   >fractional years or months not supported for date calculationsr      r!   r"   day)r%   r$   r(   r'   r)   float
is_integer
ValueErrorr"   r   r!   r#   rN   replacer   AttributeErrorNotImplemented)	r*   othernewdurationnewmonthcarrynewyearmaxdaysnewdaynewdtr   r   r   __add__   sB   


zDuration.__add__c                 C   s6   t |trt| j| | j| d}| j| |_|S tS )NrH   )r%   r   r$   r(   r'   r)   rT   r*   rU   rV   r   r   r   __mul__   s
   
zDuration.__mul__c                 C   sp   t |trt| j|j | j|j d}| j|j |_|S zt| j| jd}| j| |_|W S  ty7   Y tS w )zj
        It is possible to subtract Duration and timedelta objects from Duration
        objects.
        rH   )r%   r$   r(   r'   r)   	TypeErrorrT   r^   r   r   r   __sub__   s   
zDuration.__sub__c           	      C   s   t |trt }||_||  S zLt| j rt| j s"td|j	| j }t
|dd\}}|j| j | }t||}|j|krE|}n|j}|jt|t|t|d}|| j W S  tye   Y tS w )a@  
        It is possible to subtract Duration objects from date, datetime and
        timedelta objects.

        TODO: there is some weird behaviour in date - timedelta ...
              if timedelta has seconds or microseconds set, then
              date - timedelta != date + (-timedelta)
              for now we follow this behaviour to avoid surprises when mixing
              timedeltas with Durations, but in case this ever changes in
              the stdlib we can just do:
                return -self + other
              instead of all the current code
        rK   r   rL   rM   )r%   r   r$   r)   rO   r(   rP   r'   rQ   r"   r   r!   r#   rN   rR   r   rS   rT   )	r*   rU   tmpdurrW   rX   rY   rZ   r[   r\   r   r   r   __rsub__   s0   


zDuration.__rsub__c                 C   s`   t |tr| jd | j |jd |j kr| j|jkrdS dS | jdkr.| jdkr.| j|kS dS )z
        If the years, month part and the timedelta part are both equal, then
        the two Durations are considered equal.
        r   TFr   r%   r$   r(   r'   r)   r*   rU   r   r   r   __eq__     

zDuration.__eq__c                 C   s`   t |tr| jd | j |jd |j ks| j|jkrdS dS | jdkr.| jdkr.| j|kS dS )z
        If the years, month part or the timedelta part is not equal, then
        the two Durations are considered not equal.
        r   TFr   rd   re   r   r   r   __ne__  rg   zDuration.__ne__Nc                 C   sP   |du r|du rt d|dur|durt d|dur"||  | S |||   S )z
        Convert this duration into a timedelta object.

        This method requires a start datetime or end datetimem, but raises
        an exception if both are given.
        Nzstart or end requiredzonly start or end allowed)rQ   )r*   startendr   r   r   totimedelta/  s   zDuration.totimedelta)	r   r   r   r   r   r   r   r   r   )NN)rD   rC   __qualname____doc__r2   r6   r9   r<   rA   rE   rG   rJ   r]   __radd__r_   __rmul__ra   rc   rf   rh   rk   r   r   r   r   r$   *   s8    

/*r$   N)	rm   datetimer   decimalr   r   r   r#   r$   r   r   r   r   <module>   s    