U
    caK                     @  s  d dl mZ d dlmZmZ d dlmZ d dlZd dlZd dl	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 d dlmZmZ d d	lmZ d d
lmZmZmZ d dl m!Z! d dl"m#Z# d dl$m%Z%m&Z&m'Z'm(Z( d dl)m*  m+Z, d dl-m*  m.  m/Z0 d dl-m1Z1 d dl2m3Z3 d dl4m5Z5m6Z6 d dl7m8Z8 d dl9m:Z: e;e0j<Z<e<=ddi ddiZ>dd Z?e8dddge%j@ e%dde8ddge%G d d! d!e3ZAd&d"d!d#d$d%ZBdS )'    )annotations)datetime	timedelta)HashableN)indexlib)
BaseOffsetNaTPeriod
ResolutionTick)DtypeDtypeObjnpt)cache_readonlydoc)find_stack_level)is_datetime64_any_dtype
is_integerpandas_dtype)PeriodDtype)is_valid_na_for_dtype)PeriodArrayperiod_arrayraise_on_incompatiblevalidate_dtype_freq)maybe_extract_name)DatetimeIndexOpsMixin)DatetimeIndexIndex)inherit_names)
Int64IndexZtarget_klasszPeriodIndex or list of Periodsklassr   c                 K  sJ   | d}|jdkr:| dd }t||d}| j|f|S | |f|S d S )Ndataint64freqr%   )popdtyper   _simple_new)clsdvaluesr%    r-   >/tmp/pip-unpacked-wheel-g7fro6k3/pandas/core/indexes/period.py_new_PeriodIndexD   s    

r/   strftime
start_timeZend_timeT)wrapZis_leap_yearZ_format_native_typesc                      s  e Zd ZU dZdZded< ded< ded< eZd	Ze	d
dddZ
eddddZeejfdddedRdd dddZeejdSdddddZe	eejjddddZe	eejjddd d!Ze	eejjddd"d#ZdTd%d&d'd d(d)d*Ze	d+dd,d-Zd.dd/d0Zd1d&d2d3d4Zd5d6d+d7 fd8d9Zeejd	ejfd&d: fd;d<Ze	d&dd=d>Ze	ddd?d@Z fdAdBZ dUdCdDZ!dEdEdFdGdHZ"dIdJ Z#ee$j%ejfddK fdLdMZ%ddNdOdPdQZ&  Z'S )VPeriodIndexa  
    Immutable ndarray holding ordinal values indicating regular periods in time.

    Index keys are boxed to Period objects which carries the metadata (eg,
    frequency information).

    Parameters
    ----------
    data : array-like (1d int np.ndarray or PeriodArray), optional
        Optional period-like data to construct index with.
    copy : bool
        Make a copy of input ndarray.
    freq : str or period object, optional
        One of pandas period strings or corresponding objects.
    year : int, array, or Series, default None
    month : int, array, or Series, default None
    quarter : int, array, or Series, default None
    day : int, array, or Series, default None
    hour : int, array, or Series, default None
    minute : int, array, or Series, default None
    second : int, array, or Series, default None
    dtype : str or PeriodDtype, default None

    Attributes
    ----------
    day
    dayofweek
    day_of_week
    dayofyear
    day_of_year
    days_in_month
    daysinmonth
    end_time
    freq
    freqstr
    hour
    is_leap_year
    minute
    month
    quarter
    qyear
    second
    start_time
    week
    weekday
    weekofyear
    year

    Methods
    -------
    asfreq
    strftime
    to_timestamp

    See Also
    --------
    Index : The base pandas Index type.
    Period : Represents a period of time.
    DatetimeIndex : Index with datetime64 data.
    TimedeltaIndex : Index of timedelta64 data.
    period_range : Create a fixed-frequency PeriodIndex.

    Examples
    --------
    >>> idx = pd.PeriodIndex(year=[2000, 2002], quarter=[1, 3])
    >>> idx
    PeriodIndex(['2000Q1', '2002Q3'], dtype='period[Q-DEC]')
    Zperiodindexr   _datar   r%   r   r(   Tztype[libindex.PeriodEngine])returnc                 C  s   t jS N)libindexZPeriodEngineselfr-   r-   r.   _engine_type   s    zPeriodIndex._engine_typer   c                 C  s   | j jS r6   )r(   _resolution_objr8   r-   r-   r.   r;      s    zPeriodIndex._resolution_objzpandas.arrays.PeriodArray)otherZ
other_nameNEstr)howr5   c                 C  s"   | j ||}t| j|| jdS Nname)r4   asfreqtyper)   rB   r9   r%   r?   Zarrr-   r-   r.   rC      s    zPeriodIndex.asfreqstartr   c                 C  s   | j ||}tj|| jdS r@   )r4   to_timestampr   r)   rB   rE   r-   r-   r.   rG      s    zPeriodIndex.to_timestampr!   c                 C  s   t | jj| jdS r@   )r!   r4   hourrB   r8   r-   r-   r.   rH      s    zPeriodIndex.hourc                 C  s   t | jj| jdS r@   )r!   r4   minuterB   r8   r-   r-   r.   rI      s    zPeriodIndex.minutec                 C  s   t | jj| jdS r@   )r!   r4   secondrB   r8   r-   r-   r.   rJ      s    zPeriodIndex.secondFzDtype | Noneboolr   )r(   copyrB   r5   c                 K  s  dddddddh}t ||sBtt || d }	td	|	 t||| }|d kr|d kr|sl| d td d d ||\}}
|
}t||d
}nft||}|rt	|| r|j
|kr||}|d kr|d k	rtj|tjd}t||d
}nt||d}|r| }| j||dS )NyearmonthdayZquarterrH   rI   rJ   r   z-__new__() got an unexpected keyword argument r&   r(   )r#   r%   rA   )setissubsetlist	TypeErrorr   Z_scalar_data_errorr   _generate_ranger   
isinstancer%   rC   npasarrayr$   r   rL   r)   )r*   r#   Zordinalr%   r(   rL   rB   fieldsZvalid_field_setargumentZfreq2r-   r-   r.   __new__   s8    



zPeriodIndex.__new__z
np.ndarrayc                 C  s   t j| tdS )NrP   )rW   rX   objectr8   r-   r-   r.   r,     s    zPeriodIndex.valueszint | npt.NDArray[np.int64]c                 C  sx   t |ttjttjfr4t | jtrj| j|}|S n6t |t	r^|j
| jj
krR|jS t| |nt|rj|S t| ddS )a  
        Convert timedelta-like input to an integer multiple of self.freq

        Parameters
        ----------
        other : timedelta, np.timedelta64, DateOffset, int, np.ndarray

        Returns
        -------
        converted : int, np.ndarray[int64]

        Raises
        ------
        IncompatibleFrequency : if the input cannot be written as a multiple
            of self.freq.  Note IncompatibleFrequency subclasses ValueError.
        N)rV   r   rW   Ztimedelta64r   Zndarrayr%   r4   Z _check_timedeltalike_freq_compatr   basenr   r   )r9   r<   deltar-   r-   r.   _maybe_convert_timedelta  s    
z$PeriodIndex._maybe_convert_timedeltar   )r(   r5   c                 C  s2   t |tsdS |j}| j}|j|jko0|j|jkS )zF
        Can we compare values of the given dtype to our own?
        F)rV   r   r%   _period_dtype_coder^   )r9   r(   r%   Zown_freqr-   r-   r.   _is_comparable_dtypeC  s    

z PeriodIndex._is_comparable_dtyper   znpt.NDArray[np.bool_])wheremaskr5   c                   s<   t |trt|j| jd}nt |ts.tdt ||S )z
        where : array of timestamps
        mask : np.ndarray[bool]
            Array of booleans where data is not NA.
        r&   z6asof_locs `where` must be DatetimeIndex or PeriodIndex)rV   r   r3   Z_valuesr%   rT   super	asof_locs)r9   rc   rd   	__class__r-   r.   rf   Y  s
    

zPeriodIndex.asof_locsrL   c                   s`   t |}|tjk	r&tjdtt d nd}t|rPt|dd }| j	|d
|S t j||dS )NzThe 'how' keyword in PeriodIndex.astype is deprecated and will be removed in a future version. Use index.to_timestamp(how=how) instead.)
stacklevelrF   tzr?   ri   )r   r   
no_defaultwarningswarnFutureWarningr   r   getattrrG   Ztz_localizere   astype)r9   r(   rL   r?   rk   rg   r-   r.   rr   f  s    
zPeriodIndex.astypec                 C  sD   t | dkrdS | jstd| j}|dd |dd  dk  S )z
        Returns True if this PeriodIndex is range-like in that all Periods
        between start and end are present, in order.
        r   TzIndex is not monotonic   N   )lenZis_monotonic_increasing
ValueErrorZasi8all)r9   r,   r-   r-   r.   is_full  s    zPeriodIndex.is_fullc                 C  s   dS )NZperiodr-   r8   r-   r-   r.   inferred_type  s    zPeriodIndex.inferred_typec                   s(   t  ||}| j|jkr$| |}|S r6   )re   _convert_tolerancer(   r`   )r9   	tolerancetargetrg   r-   r.   r{     s    
zPeriodIndex._convert_tolerancec           	   
   C  s  |}|  | t|| jr"t}nt|trz| |\}}W n4 tk
rt } ztd| d|W 5 d}~X Y nX | 	|rz| 
||W S  tk
r } zt||W 5 d}~X Y nX || jkr| |}| j|||d}|S |dkrt|n
| |}n8t|tr| |}n t|tr2| |}nt|zt| |||W S  tk
rz } zt||W 5 d}~X Y nX dS )a  
        Get integer location for requested label.

        Parameters
        ----------
        key : Period, NaT, str, or datetime
            String or datetime key must be parsable as Period.

        Returns
        -------
        loc : int or ndarray[int64]

        Raises
        ------
        KeyError
            Key is not present in the index.
        TypeError
            If key is listlike or otherwise not hashable.
        zCannot interpret 'z' as periodN)methodr|   )Z_check_indexing_errorr   r(   r	   rV   r>   Z_parse_with_resorw   KeyErrorZ_can_partial_date_sliceZ_partial_date_slicer;   _cast_partial_indexing_scalarget_locr
   _maybe_cast_for_get_locr   r   )	r9   keyr~   r|   Zorig_keyparsedresoerrlocr-   r-   r.   r     s<    
$



zPeriodIndex.get_locr
   )r   r5   c                 C  s0   | j }|j }|j|jkr$|j|jks,t||S r6   )r%   r^   ra   r   )r9   r   ZsfreqZkfreqr-   r-   r.   r     s    

z#PeriodIndex._maybe_cast_for_get_locc              
   C  sD   zt || jd}W n, tk
r> } zt||W 5 d }~X Y nX |S )Nr&   )r
   r%   rw   r   )r9   labelr   r   r-   r-   r.   r     s
    z)PeriodIndex._cast_partial_indexing_scalar)sidec                   s&   t |tr| |}t j|||dS )N)kind)rV   r   r   re   _maybe_cast_slice_bound)r9   r   r   r   rg   r-   r.   r     s    

z#PeriodIndex._maybe_cast_slice_boundr   )r   r   c                 C  s.   t ||jd}|j| jdd|j| jddfS )Nr&   rF   rl   end)r
   Zattr_abbrevrC   r%   )r9   r   r   Zivr-   r-   r.   _parsed_string_to_bounds	  s    z$PeriodIndex._parsed_string_to_bounds)Nr=   )NrF   )NNNNFN)NN)(__name__
__module____qualname____doc__Z_typ__annotations__r   Z	_data_clsZ!_supports_partial_string_indexingpropertyr:   r   r;   r   rC   _shared_doc_kwargsrG   rH   fgetrI   rJ   r[   r,   r`   rb   rf   r   rr   r   rm   ry   rz   r{   r   r   r   r   r   r   __classcell__r-   r-   rg   r.   r3   O   sp   
E


      B$
Fr3   z
int | None)periodsr5   c                 C  sj   t | ||dkrtd|dkr:t| ts:t|ts:d}tj| |||i d\}}t||d}t||dS )a  
    Return a fixed frequency PeriodIndex.

    The day (calendar) is the default frequency.

    Parameters
    ----------
    start : str or period-like, default None
        Left bound for generating periods.
    end : str or period-like, default None
        Right bound for generating periods.
    periods : int, default None
        Number of periods to generate.
    freq : str or DateOffset, optional
        Frequency alias. By default the freq is taken from `start` or `end`
        if those are Period objects. Otherwise, the default is ``"D"`` for
        daily frequency.
    name : str, default None
        Name of the resulting PeriodIndex.

    Returns
    -------
    PeriodIndex

    Notes
    -----
    Of the three parameters: ``start``, ``end``, and ``periods``, exactly two
    must be specified.

    To learn more about the frequency strings, please see `this link
    <https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases>`__.

    Examples
    --------
    >>> pd.period_range(start='2017-01-01', end='2018-01-01', freq='M')
    PeriodIndex(['2017-01', '2017-02', '2017-03', '2017-04', '2017-05', '2017-06',
             '2017-07', '2017-08', '2017-09', '2017-10', '2017-11', '2017-12',
             '2018-01'],
            dtype='period[M]')

    If ``start`` or ``end`` are ``Period`` objects, they will be used as anchor
    endpoints for a ``PeriodIndex`` with frequency matching that of the
    ``period_range`` constructor.

    >>> pd.period_range(start=pd.Period('2017Q1', freq='Q'),
    ...                 end=pd.Period('2017Q2', freq='Q'), freq='M')
    PeriodIndex(['2017-03', '2017-04', '2017-05', '2017-06'],
                dtype='period[M]')
    ru   zOOf the three parameters: start, end, and periods, exactly two must be specifiedND)rY   r&   rA   )comZcount_not_nonerw   rV   r
   r   rU   r3   )rF   r   r   r%   rB   r#   r-   r-   r.   period_range  s    4r   )NNNNN)C
__future__r   r   r   typingr   rn   ZnumpyrW   Zpandas._libsr   r7   r   Zpandas._libs.tslibsr   r	   r
   r   r   Zpandas._typingr   r   r   Zpandas.util._decoratorsr   r   Zpandas.util._exceptionsr   Zpandas.core.dtypes.commonr   r   r   Zpandas.core.dtypes.dtypesr   Zpandas.core.dtypes.missingr   Zpandas.core.arrays.periodr   r   r   r   Zpandas.core.commoncorecommonr   Zpandas.core.indexes.baseZindexesr]   Zibaser   Z pandas.core.indexes.datetimeliker   Zpandas.core.indexes.datetimesr   r   Zpandas.core.indexes.extensionr    Zpandas.core.indexes.numericr!   dictZ_index_doc_kwargsupdater   r/   Z
_field_opsr3   r   r-   r-   r-   r.   <module>   sT   
    =         