o
    >                     @   sf   d Z ddlmZ ddlmZ ddlmZ ddlZg dZdd Zd	d
 ZdddZ	G dd de
ZdS )zyISO 8601 duration/period support.

https://en.wikipedia.org/wiki/ISO_8601#Durations
https://tools.ietf.org/html/rfc3339

    )absolute_import)division)unicode_literalsN)      r      r   r   r   r   r   r   r   r   c                 C   s$   | d dkp| d dko| d dkS )zReturns True if year is a leap year.

  Cheaper than `import calendar` because its the only thing needed here.

  Args:
    year: The 4 digit year.

  Returns:
    True if year is a leap year.
  i  r   d       )yearr
   r
   B/tmp/google-cloud-sdk/lib/googlecloudsdk/core/util/iso_duration.py
IsLeapYear    s   $r   c                 C   s&   t |d  |dkrt| rd S d S )zReturns the number of days in the given month and calendar year.

  Args:
    year: The 4 digit calendar year.
    month: The month number 1..12.

  Returns:
    The number of days in the given month and calendar year.
        r   )_ISO_DAYS_IN_MONTHr   )r   monthr
   r
   r   DaysInCalendarMonth.   s
   

r       c                 C   sd   dj |d}| t|}|r|d}|dr|dd }|r.|dkr0| ||  dS dS dS )a  Appends a formatted number + suffix to result.

  Trailing "0" and "." are stripped. If no digits remain then nothing is
  appended to result.

  Args:
    result: The formatted number, if any is appended to this list.
    number: The int or float to format.
    suffix: A suffix string to append to the number.
    precision: Format the last duration part with precision digits after the
      decimal point. Trailing "0" and "." are always stripped.
  z{{0:.{precision}f}}	precision0.N)formatfloatrstripendswithappend)resultnumbersuffixr   fmtsr
   r
   r   _FormatNumber=   s   

r$   c                   @   s   e Zd ZdZeZdZdZdZdZ	dZ
dZee	 Zee
 Zee Zee Z			dd
dZdd Zdd ZdddZdddZdd ZdS )Durationa8  The parts of an ISO 8601 duration plus microseconds.

  Durations using only hours, miniutes, seconds and microseconds are exact.
  calendar=True allows the constructor to use duration units larger than hours.
  These durations will be inexact across daylight savings time and leap year
  boundaries, but will be "calendar" correct. For example:

    2015-02-14 + P1Y   => 2016-02-14
    2015-02-14 + P365D => 2016-02-14
    2016-02-14 + P1Y   => 2017-02-14
    2016-02-14 + P366D => 2017-02-14

    2016-03-13T01:00:00 + P1D   => 2016-03-14T01:00:00
    2016-03-13T01:00:00 + PT23H => 2016-03-14T01:00:00
    2016-03-13T01:00:00 + PT24H => 2016-03-14T03:00:00

  delta durations (initialized from datetime.timedelta) are calendar=False.
  Parsed durations containing duration units larger than hours are
  calendar=True.
  gvqv@@B <         r   NFc
           
      C   sX   || _ || _|| _|| _|| _|| _|| _d| _|r#|  j| 7  _|	| _| 	  d S )Nr   )
yearsmonthsdayshoursminutessecondsmicrosecondstotal_secondscalendar
_Normalize)
selfr*   r+   r,   r-   r.   r/   r0   deltar2   r
   r
   r   __init__x   s   zDuration.__init__c                 C   s  dd }|| j \| _ }|r|  j| j| 7  _|| j\| _}|r1|  jt| j| | j 7  _|| j\| _}|rE|  j| j| 7  _|| j\| _}|rY|  j| j	| 7  _|| j\| _}|rm|  j
| j| 7  _
|| j
\| _
}|rt| j| | _d| _t| j| j }|  jt|| j 8  _|  j| j| j 7  _|  j
|7  _
t| j
| j }|  j
|| j 8  _
|  j| j
7  _|  j|7  _t| j| j	 }|  j|| j	 8  _|  j| j| j 7  _|  j|7  _| js| js| js| j rd| _n|  j| j| j 7  _dS t| j| j }|  j|| j 8  _|  j| j| j 7  _|  j|7  _| jt| jd krN|  jt| jd 8  _|  j d7  _ n| jt| jd  krm|  jt| jd 7  _|  j d8  _ t| j| j }|  jt|| j 8  _|  j| j| j 7  _|  j |7  _ t| j| j }|  j|| j 8  _|  j| j| j 7  _|  j |7  _ |  j| j | j 7  _t| jd| j| j  | _dS )zNormalizes duration values to integers in ISO 8601 ranges.

    Normalization makes formatted durations aesthetically pleasing. For example,
    P2H30M0.5S instead of P9000.5S. It also determines if the duration is exact
    or a calendar duration.
    c                 S   s$   t | }tt| d| d}||fS )Nr	   )intround)f	int_valuefractionr
   r
   r   
_Percolate   s   z'Duration._Normalize.<locals>._Percolateg        TNr   r   )r*   r,   _DAYS_PER_YEARr+   r7   _MONTHS_PER_YEARr-   _HOURS_PER_DAYr.   _MINUTES_PER_HOURr/   _SECONDS_PER_MINUTE_MICROSECONDS_PER_SECONDr0   r1   r2   _SECONDS_PER_HOUR_SECONDS_PER_DAY_SECONDS_PER_MONTH_SECONDS_PER_YEARr8   )r4   r<   r;   carryr
   r
   r   r3      sx   

zDuration._Normalizec                 C   sX  |  }d}d}|dr|dd }d}n|dr!|dd }d}|dr/|dd }nd}|g}t|D ]\}}| rF|| q8|d	ksN|d
krT|d	 q8|dkrc|r^tdd }}q8t|dkrttd||d td	|}	|g}|dkr|  j
|	7  _
q8|dkr|  j|	d 7  _q8|dkr|  j|	7  _q8|dv rt||d kr||d  dkr|dkrd}
n	|dkrd}
nd}
|  j|	|
 7  _ n>|dkr|sd}|  j|	7  _q8d}|dkr|  j|	7  _q8|dkr|  j|	7  _q8|dkr
|  j|	7  _q8td|t|dkr&|  ddkr&td|   | S )a%  Parses an ISO 8601 duration from string and returns a Duration object.

    If P is omitted then T is implied (M == minutes).

    Args:
      string: The ISO 8601 duration string to parse.

    Raises:
      ValueError: For invalid duration syntax.

    Returns:
      A Duration object.
    F-r   N+r   PTr   ,Tz1A duration may contain at most one 'T' separator.z0Duration unit '{}' must be preceded by a number.YW   D)MUNr   SrQ   i  rR   r&   i ʚ;Hz$Unknown character '{0}' in duration.z+-P0z+Duration must end with time part character.)upper
startswith	enumerateisdigitr   
ValueErrorlenr   r   joinr*   r,   r/   r+   r-   r.   lstripr3   )r4   stringr#   t_separator	t_impliedsignamounticr    nr
   r
   r   Parse   sv   




(
"zDuration.Parser   c                 C   s  |dkrd}t | j}d}d}g }| jdk r|d |d ||k rJ| jrJd}t | j}||| j 8 }||d krB||| j 7 }t||ddd ||7 }||k rx| jrxd}t | j}||| j 8 }||d krp||| j 7 }t||ddd ||7 }||k r| jrd}t | j}||| j	 8 }||d kr||| j	 7 }t||d	dd |d
 ||7 }||k r| j
rd}t | j
}||| j 8 }||d kr||| j 7 }t||ddd ||7 }||k r
| jr
d}t | j}||| j 8 }||d kr||| j 7 }t||ddd ||7 }||k r2| js| jr2|d7 }t|t | jt | j| j  d|d |d d
kr?|dd }|d dkrK|d d|S )a  Returns an ISO 8601 string representation of the duration.

    The Duration format is: "[-]P[nY][nM][nD][T[nH][nM][n[.m]S]]". The 0
    duration is "P0". Otherwise at least one part will always be displayed.
    Negative durations are prefixed by "-". "T" disambiguates months "P2M" to
    the left of "T" and minutes "PT5M" to the right.

    Args:
      parts: Format at most this many duration parts starting with largest
        non-zero part, 0 for all parts. Zero-valued parts in the count are not
        shown.
      precision: Format the last duration part with precision digits after the
        decimal point. Trailing "0" and "." are always stripped.

    Returns:
      An ISO 8601 string representation of the duration.
    r   rO   rH   rJ   r   rM   r   rQ   rP   rL   rU   rT   r   Nr   r   )absr1   r   r*   rF   r$   r+   rE   r,   rD   r-   rC   r.   rA   r/   r0   rB   r]   )r4   partsr   r1   countshownr   rf   r
   r
   r   Format;  s   











zDuration.Formatc                 C   s,   |dur|| _ |  j| 7  _|   | S )zAdds a datetime.timdelta to the duration.

    Args:
      delta: A datetime.timedelta object to add.
      calendar: Use duration units larger than hours if True.

    Returns:
      The modified Duration (self).
    N)r2   r/   r1   r3   )r4   r5   r2   r
   r
   r   AddTimeDelta  s
   
zDuration.AddTimeDeltac              
   C   s4  |j |j|j|j|j|j|jf\}}}}}}}|| j7 }|| jkr+|| j8 }|d7 }n|dk r8|| j7 }|d8 }|| j	7 }|| j
krL|| j
8 }|d7 }n|dk rY|| j
7 }|d8 }|| j7 }|| jkrm|| j8 }|d7 }n|dk rz|| j7 }|d8 }t|| j | j }	|| j|	| j  7 }|dk r|| j7 }|	d8 }	||	7 }|| j7 }|| jkr|| j8 }|d7 }n|dk r|| j7 }|d8 }|| j7 }|| j7 }|dk r|dk r|d8 }|dk r| j}|d8 }|t||7 }|dk sn 	 t||}
||
krn||
8 }|d7 }|| jkrd}|d7 }qt||||||||jS )zReturns a copy of the datetime object dt relative to the duration.

    Args:
      dt: The datetime object to add the duration to.

    Returns:
      The a copy of datetime object dt relative to the duration.
    r   r   )microsecondsecondminutehourdayr   r   r0   rB   r/   rA   r.   r@   r7   r-   r?   r+   r>   r*   r,   r   datetimetzinfo)r4   dtrn   ro   rp   rq   rr   r   r   rG   days_in_monthr
   r
   r   GetRelativeDateTime  sx   
























zDuration.GetRelativeDateTime)	r   r   r   r   r   r   r   NF)r   r   )N)__name__
__module____qualname____doc__r   _DAYS_IN_MONTHr=   rB   rA   r@   r?   r>   rC   rD   rF   rE   r6   r3   rg   rl   rm   rw   r
   r
   r
   r   r%   T   s*    
`
T
^r%   )r   r   )r{   
__future__r   r   r   rs   r   r   r   r$   objectr%   r
   r
   r
   r   <module>   s   
