o
    oR                     @   s   d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlmZ ddlm	Z	 ddl
mZ ddlZdd	lmZ dd
lmZ ddlmZ ddlmZ ddlZzddlmZ W n eya   dZY nw G dd dej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de_e	 Ze	 Z dZ!dd Z"dd Z#dHdd Z$d!d" Z%d#d$ Z&dId&d'Z'dJd(d)Z(d*d+ Z)d,d- Z*dKd.d/Z+dKd0d1Z,G d2d3 d3e-Z.d4d5 Z/defd6d7Z0efd8d9Z1efd:d;Z2efd<d=Z3efd>d?Z4efd@dAZ5dLdBdCZ6G dDdE dEej7Z8efdFdGZ9dS )Ma  dateutil and datetime with portable timezone and ISO 8601 durations.

This module supports round-trip conversions between strings, datetime objects
and timestamps:

         => ParseDateTime =>           => GetTimeStampFromDateTime =>
  string                      datetime                                timestamp
         <= FormatDateTime <=          <= GetDateTimeFromTimeStamp <=

GetTimeZone(str) returns the tzinfo object for a timezone name. It handles
abbreviations, IANA timezone names, and on Windows translates timezone names to
the closest Windows TimeZone registry equivalent.

LocalizeDateTime(datetime, tzinfo) returns a datetime object relative to the
timezone tzinfo.

ISO 8601 duration/period conversions are also supported:

         => ParseDuration =>           => GetDateTimePlusDuration =>
  string                      Duration                               datetime
         <= FormatDuration <=

  timedelta => GetDurationFromTimeDelta => Duration

This module is biased to the local timezone by default. To operate on timezone
naiive datetimes specify tzinfo=None in all calls that have a timezone kwarg.

The datetime and/or dateutil modules should have covered all of this.
    )absolute_import)division)unicode_literalsN)parser)tz)_common)
exceptions)encoding)iso_duration)
times_data)tzwinc                   @      e Zd ZdZdS )ErrorzBase errors for this module.N__name__
__module____qualname____doc__ r   r   ;/tmp/google-cloud-sdk/lib/googlecloudsdk/core/util/times.pyr   G       r   c                   @   r   )DateTimeSyntaxErrorzDate/Time string syntax error.Nr   r   r   r   r   r   K   r   r   c                   @   r   )DateTimeValueErrorzDate/Time part overflow error.Nr   r   r   r   r   r   O   r   r   c                   @   r   )DurationSyntaxErrorzDuration string syntax error.Nr   r   r   r   r   r   S   r   r   c                   @   r   )DurationValueErrorzDuration part overflow error.Nr   r   r   r   r   r   W   r   r   T   c              
   C   s   z|  |W S  ttfy. } zd|vrtt|t| |ddW  Y d}~S d}~w tt	t
fyC } ztt|d}~ww )z/Convert strftime exceptions to Datetime Errors.z%Zz%EzN)strftime	TypeErrorUnicodeErrorr   six	text_typeFormatDateTimereplaceAttributeErrorOverflowError
ValueError)dtfmter   r   r   	_StrFtimed   s   r)   c              
   C   sb   zt j | |W S  tttfy } ztt|d}~w ty0 } zt	t|d}~ww )z/Convert strptime exceptions to Datetime Errors.N)
datetimestrptimer#   r$   r   r   r   r    r%   r   )stringr'   r(   r   r   r   	_StrPtimes   s   r-      c                 C   s   | j ||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]]". At least one
  part will always be displayed. The 0 duration is "P0". Negative durations
  are prefixed by "-". "T" disambiguates months "P2M" to the left of "T" and
  minutes "PT5MM" to the right.

  Args:
    duration: An iso_duration.Duration object.
    parts: Format at most this many duration parts starting with largest
      non-zero part.
    precision: Format the last duration part with precision digits after the
      decimal point. Trailing "0" and "." are always stripped.

  Raises:
    DurationValueError: A Duration numeric constant exceeded its range.

  Returns:
    An ISO 8601 string representation of the duration.
  )parts	precision)Format)durationr/   r0   r   r   r   FormatDuration}   s   r3   c                 C   s6   d t| jt}|dr|dtd  }|d S )a  Returns a string representation of the duration, ending in 's'.

  See the section of
  <https://github.com/google/protobuf/blob/master/src/google/protobuf/duration.proto>
  on JSON formats.

  For example:

    >>> FormatDurationForJson(iso_duration.Duration(seconds=10))
    10s
    >>> FormatDurationForJson(iso_duration.Duration(hours=1))
    3600s
    >>> FormatDurationForJson(iso_duration.Duration(seconds=1, microseconds=5))
    1.000005s

  Args:
    duration: An iso_duration.Duration object.

  Raises:
    DurationValueError: A Duration numeric constant exceeded its range.

  Returns:
    An string representation of the duration.
  z{}z.0Ns)formatroundtotal_seconds_MICROSECOND_PRECISIONendswithlen)r2   numr   r   r   FormatDurationForJson   s   
r<   c                 C   s   dd | D S )a  Returns a list of string representations of the durations, ending in 's'.

  It will use FormatDurationForJson to process each duration object in the list.

  Args:
    duration_list: A list of iso_duration.Duration objects to be formatted.

  Raises:
    DurationValueError: A Duration numeric constant exceeded its range.

  Returns:
    A list of strings representation of the duration.
  c                 S   s   g | ]}t |qS r   )r<   ).0r2   r   r   r   
<listcomp>   s    z-FormatDurationListForJson.<locals>.<listcomp>r   )duration_listr   r   r   FormatDurationListForJson   s   r@   Fc              
   C   s   |rzt | }d||} W n	 ty   Y nw z
tj|d| W S  ttfy7 } ztt	
|d}~w tyI } ztt	
|d}~ww )aF  Parses a duration string and returns a Duration object.

  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

  Args:
    string: The ISO 8601 duration/period string to parse.
    calendar: Use duration units larger than hours if True.
    default_suffix: Use this suffix if string is an unqualified int.

  Raises:
    DurationSyntaxError: Invalid duration syntax.
    DurationValueError: A Duration numeric constant exceeded its range.

  Returns:
    An iso_duration.Duration object for the given ISO 8601 duration/period
    string.
  z{}{})calendarN)intr5   r%   r
   DurationParser#   r$   r   r   r    r   )r,   rA   default_suffixsecondsr(   r   r   r   ParseDuration   s    rG   c                 C   s   t j| |dS )a  Returns a Duration object converted from a datetime.timedelta object.

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

  Returns:
    The iso_duration.Duration object converted from a datetime.timedelta object.
  deltarA   )r
   rC   rH   r   r   r   GetDurationFromTimeDelta   s   
rJ   c                 C   s
   | | S )zReturns a new datetime object representing dt + duration.

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

  Returns:
    A new datetime object representing dt + duration.
  )GetRelativeDateTime)r&   r2   r   r   r   GetDateTimePlusDuration   s   

rL   c                 C   sp   | dv rt S | dv rtS tj| | } t| }|s6tr6tj| | } zt| }W |S  t	y5   Y |S w |S )zReturns a datetime.tzinfo object for name.

  Args:
    name: A timezone name string, None for the local timezone.

  Returns:
    A datetime.tzinfo object for name, local timezone if name is unknown.
  )UTCZ)LOCALL)
rM   rO   r   ABBREVIATION_TO_IANAgetr   gettzr   IANA_TO_WINDOWSWindowsError)nametzinfor   r   r   GetTimeZone  s    	
rX   c              	   C   s.  |rt | |} |sd}td}||}|stt| |S g }d}|r||  }||k r>|tt| |||  |d7 }|| 	 rSt
|| }|d7 }nd}|| dv rd|| }	|d7 }nd}	|| }
d|
 }|
dkrt| |}|r|t|k rt
|d| }t
|| }|d	kr|d7 }d
j|d}||}t||kr||d }n3|
dkrt| }n*|
dkrt| |}|	r|	dkr|dkrd}nt|d	kr|dd d |dd  }|r|t| || 7 }|||d }|s%|t|k r|tt| ||d  d|S )aO  Returns a string of a datetime object formatted by an extended strftime().

  fmt handles these modifier extensions to the standard formatting chars:

    %Nf   Limit the fractional seconds to N digits. The default is N=6.
    %Ez   Format +/-HHMM offsets as ISO RFC 3339 Z for +0000 otherwise +/-HH:MM.
    %Oz   Format +/-HHMM offsets as ISO RFC 3339 +/-HH:MM.

  NOTE: The standard Python 2 strftime() borks non-ascii time parts. It does
  so by encoding non-ascii names to bytes, presumably under the assumption that
  the return value will be immediately output. This code works around that by
  decoding strftime() values to unicode if necessary and then returning either
  an ASCII or UNICODE string.

  Args:
    dt: The datetime object to be formatted.
    fmt: The strftime(3) format string, None for the RFC 3339 format in the dt
      timezone ('%Y-%m-%dT%H:%M:%S.%3f%Ez').
    tzinfo: Format dt relative to this timezone.

  Raises:
    DateTimeValueError: A DateTime numeric constant exceeded its range.

  Returns:
    A string of a datetime object formatted by an extended strftime().
  z%Y-%m-%dT%H:%M:%S.%3f%Ezz%[1-9]?[EO]?[fsz]r      N)EO%f   z{{0:0{n}d}})nr4   zrZ   z+0000rN   r.   : )LocalizeDateTimerecompilesearchr	   Decoder)   startappendisdigitrB   r:   r5   GetTimeStampFromDateTimeendjoin)r&   r'   rW   	extensionmr/   rh   matchr_   	alternatespecstd_fmtvalvr]   zero_fill_formatr   r   r   r!   %  sl   








7
r!   c                    s    fdd| D S )a7  Returns a list of strings of datetime objects formatted by FormatDateTime.

  It will use FormatDateTime to process each datetime object in the list.

  Args:
    dt_list: A list of datetime objects to be formatted.
    fmt: The strftime(3) format string, None for the RFC 3339 format in the dt
      timezone ('%Y-%m-%dT%H:%M:%S.%3f%Ez').
    tzinfo: Format dt relative to this timezone.

  Raises:
    DateTimeValueError: A DateTime numeric constant exceeded its range.

  Returns:
    A list of strings of a datetime objects formatted by an extended strftime().
  c                    s   g | ]}t | qS r   )r!   )r=   r&   r'   rW   r   r   r>     s    z&FormatDateTimeList.<locals>.<listcomp>r   )dt_listr'   rW   r   rw   r   FormatDateTimeList  s   ry   c                   @   s,   e Zd ZdZdd Zdd Zedd ZdS )	_TzInfoOrOffsetGetterzA helper class for dateutil.parser.parse().

  Attributes:
    _timezone_was_specified: True if the parsed date/time string contained
      an explicit timezone name or offset.
  c                 C   s
   d| _ d S )NF_timezone_was_specifiedselfr   r   r   __init__  s   
z_TzInfoOrOffsetGetter.__init__c                 C   s&   |s|rd| _ |s|dur|S t|S )a  Returns the tzinfo for name or offset.

    Used by dateutil.parser.parse() to convert timezone names and offsets.

    Args:
      name: A timezone name or None to use offset. If offset is also None then
        the local tzinfo is returned.
      offset: A signed UTC timezone offset in seconds.

    Returns:
      The tzinfo for name or offset or the local tzinfo if both are None.
    TN)r|   rX   )r~   rV   offsetr   r   r   Get  s
   z_TzInfoOrOffsetGetter.Getc                 C   s   | j S )zCTrue if the parsed date/time string contained an explicit timezone.r{   r}   r   r   r   timezone_was_specified  s   z,_TzInfoOrOffsetGetter.timezone_was_specifiedN)r   r   r   r   r   r   propertyr   r   r   r   r   rz     s    rz   c                 C   sN   zt d| }W n
 ty   Y dS w |r%t|d}|r%|d|fS dS )zFReturns (prefix,tzinfo) if string has a trailing tz, else (None,None).z(.*[\d\s])([^\d\s]+)$NN   rY   )rd   rp   r   rX   group)r,   rp   rW   r   r   r   _SplitTzFromDate  s   r   c           
      C   s  |rt | |}|r|js|j|d}|S t|d}t }d}ztj| |j|d}|r;|js;tj| d|d}|j|d}|W S  t	yY } zt
tt|}W Y d}~n~d}~w tttfy } zkt
tt|}|jst| \}}	|	rz	tj||d}W n: t	y } zt
tt|}W Y d}~n/d}~w tttfy } zt
tt|}W Y d}~nd}~ww |j|	dW  Y d}~S W Y d}~nd}~ww zt| t|dW S  ty   |  Y dS w )a\  Parses a date/time string and returns a datetime.datetime object.

  Args:
    string: The date/time string to parse. This can be a parser.parse()
      date/time or an ISO 8601 duration after Now(tzinfo) or before if prefixed
      by '-'.
    fmt: The input must satisfy this strptime(3) format string.
    tzinfo: A default timezone tzinfo object to use if string has no timezone.

  Raises:
    DateTimeSyntaxError: Invalid date/time/duration syntax.
    DateTimeValueError: A date/time numeric constant exceeds its range.

  Returns:
    A datetime.datetime object for the given date/time string.
  rW   N)tzinfosdefault)r   )r-   rW   r"   GetDateTimeDefaultsrz   r   parser   r   r$   r   ExceptionContextr   r   r    r#   r%   r   r   r   rG   rK   Nowr   Reraise)
r,   r'   rW   r&   defaultstzgetterexcr(   prefixexplicit_tzinfor   r   r   ParseDateTime  sV   



 r   c              
   C   s>   zt j | |W S  tttfy } ztt|d}~ww )a  Returns the datetime object for a UNIX timestamp.

  Args:
    timestamp: A UNIX timestamp in int or float seconds since the epoch
      (1970-01-01T00:00:00.000000Z).
    tzinfo: A tzinfo object for the timestamp timezone, None for naive.

  Raises:
    DateTimeValueError: A date/time numeric constant exceeds its range.

  Returns:
    The datetime object for a UNIX timestamp.
  N)r*   fromtimestampr%   OSErrorr$   r   r   r    )	timestamprW   r(   r   r   r   GetDateTimeFromTimeStamp  s   r   c                 C   s0   | j s|r| j|d} | tjdt }| S )zReturns the float UNIX timestamp (with microseconds) for dt.

  Args:
    dt: The datetime object to convert from.
    tzinfo: Use this tzinfo if dt is naiive.

  Returns:
    The float UNIX timestamp (with microseconds) for dt.
  r   r   )rW   r"   r*   r   rM   r7   )r&   rW   rI   r   r   r   rk   '  s   

rk   c                 C   s   t | |d}t||dS )aD  Returns a datetime object localized to the timezone tzinfo.

  Args:
    dt: The datetime object to localize. It can be timezone naive or aware.
    tzinfo: The timezone of the localized dt. If None then the result is naive,
      otherwise it is aware.

  Returns:
    A datetime object localized to the timezone tzinfo.
  r   )rk   r   )r&   rW   tsr   r   r   rc   7  s   rc   c                 C   s   t j | S )zReturns a timezone aware datetime object for the current time.

  Args:
    tzinfo: The timezone of the localized dt. If None then the result is naive,
      otherwise it is aware.

  Returns:
    A datetime object localized to the timezone tzinfo.
  )r*   nowr   r   r   r   r   F  s   
r   c                 C   s   t j t| d t jjS )a  Returns a datetime object of default values for parsing partial datetimes.

  The year, month and day default to today (right now), and the hour, minute,
  second and fractional second values default to 0.

  Args:
    tzinfo: The timezone of the localized dt. If None then the result is naive,
      otherwise it is aware.

  Returns:
    A datetime object of default values for parsing partial datetimes.
  r   )r*   combiner   datetimeminr   r   r   r   r   S  s   r   c                 C   s   t || d S )a  Returns a tzinfo for offset minutes east of UTC with optional name.

  Args:
    offset: The minutes east of UTC. Minutes west are negative.
    name: The optional timezone name. NOTE: no dst name.

  Returns:
    A tzinfo for offset seconds east of UTC.
  <   )r   tzoffset)r   rV   r   r   r   TzOffsetd  s   
r   c                   @   s8   e Zd ZdZdZdZdZdZdZdZ	dZ
ed	d
 ZdS )WeekdayzRepresents a day of the week.r   rY   r   r.      r^   r   c                 C   s*   |  }t| |d }|std||S )Nz[{}] is not a valid Weekday)uppergetattrKeyErrorr5   )clsdayvaluer   r   r   r   |  s
   zWeekday.GetN)r   r   r   r   MONDAYTUESDAY	WEDNESDAYTHURSDAYFRIDAYSATURDAYSUNDAYclassmethodr   r   r   r   r   r   q  s    r   c                 C   s0   t | |}|  |  }|j| d }t|S )a  Returns the Weekday for dt in the timezone specified by tzinfo.

  Args:
    dt: The datetime object that represents the time on weekday.
    weekday: The day of the week specified as a Weekday enum.
    tzinfo: The timezone in which to get the new day of the week in.

  Returns:
    A Weekday that corresponds to dt and weekday pair localized to the timezone
    specified by dt.
     )rc   weekdayr   r   )r&   r   rW   localized_dtlocalized_weekday_offsetlocalized_weekday_indexr   r   r   GetWeekdayInTimezone  s   
r   )r.   r.   )FN)Fr   )N):r   
__future__r   r   r   r*   rd   dateutilr   r   dateutil.tzr   	tz_commonenumgooglecloudsdk.corer   googlecloudsdk.core.utilr	   r
   r   r   r   ImportErrorr   r   r   r   r   PY3tzlocalrO   tzutcrM   r8   r)   r-   r3   r<   r@   rG   rJ   rL   rX   r!   ry   objectrz   r   r   r   rk   rc   r   r   r   Enumr   r   r   r   r   r   <module>   sf   

!

,

e$A
