Skip to content

Follow up to #17422 #17472

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 27 additions & 28 deletions pandas/_libs/period.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@ from cpython cimport (
from numpy cimport (int8_t, int32_t, int64_t, import_array, ndarray,
NPY_INT64, NPY_DATETIME, NPY_TIMEDELTA)
import numpy as np
import_array()

from libc.stdlib cimport free

from pandas import compat
from pandas.compat import PY2

cimport cython

from datetime cimport (
is_leapyear,
PyDateTime_IMPORT,
pandas_datetimestruct,
pandas_datetimestruct_to_datetime,
pandas_datetime_to_datetimestruct,
Expand All @@ -29,6 +28,7 @@ from datetime cimport (


cimport util, lib
from util cimport is_period_object, is_string_object

from lib cimport is_null_datetimelike, is_period
from pandas._libs import tslib, lib
Expand All @@ -41,6 +41,8 @@ from tslib cimport (
_get_dst_info,
_nat_scalar_rules)

from tslibs.frequencies cimport get_freq_code

from pandas.tseries import offsets
from pandas.core.tools.datetimes import parse_time_string
from pandas.tseries import frequencies
Expand Down Expand Up @@ -329,8 +331,6 @@ cdef list str_extra_fmts = ["^`AB`^", "^`CD`^", "^`EF`^",
"^`GH`^", "^`IJ`^", "^`KL`^"]

cdef object _period_strftime(int64_t value, int freq, object fmt):
import sys

cdef:
Py_ssize_t i
date_info dinfo
Expand Down Expand Up @@ -683,7 +683,7 @@ cdef class _Period(object):
def _maybe_convert_freq(cls, object freq):

if isinstance(freq, (int, tuple)):
code, stride = frequencies.get_freq_code(freq)
code, stride = get_freq_code(freq)
freq = frequencies._get_freq_str(code, stride)

freq = frequencies.to_offset(freq)
Expand All @@ -707,7 +707,7 @@ cdef class _Period(object):
return self

def __richcmp__(self, other, op):
if isinstance(other, Period):
if is_period_object(other):
if other.freq != self.freq:
msg = _DIFFERENT_FREQ.format(self.freqstr, other.freqstr)
raise IncompatibleFrequency(msg)
Expand Down Expand Up @@ -753,7 +753,7 @@ cdef class _Period(object):
return NotImplemented

def __add__(self, other):
if isinstance(self, Period):
if is_period_object(self):
if isinstance(other, (timedelta, np.timedelta64,
offsets.DateOffset,
Timedelta)):
Expand All @@ -765,13 +765,13 @@ cdef class _Period(object):
return Period(ordinal=ordinal, freq=self.freq)
else: # pragma: no cover
return NotImplemented
elif isinstance(other, Period):
elif is_period_object(other):
return other + self
else:
return NotImplemented

def __sub__(self, other):
if isinstance(self, Period):
if is_period_object(self):
if isinstance(other, (timedelta, np.timedelta64,
offsets.DateOffset,
Timedelta)):
Expand All @@ -780,7 +780,7 @@ cdef class _Period(object):
elif lib.is_integer(other):
ordinal = self.ordinal - other * self.freq.n
return Period(ordinal=ordinal, freq=self.freq)
elif isinstance(other, Period):
elif is_period_object(other):
if other.freq != self.freq:
msg = _DIFFERENT_FREQ.format(self.freqstr, other.freqstr)
raise IncompatibleFrequency(msg)
Expand All @@ -789,7 +789,7 @@ cdef class _Period(object):
return -other.__sub__(self)
else: # pragma: no cover
return NotImplemented
elif isinstance(other, Period):
elif is_period_object(other):
if self is NaT:
return NaT
return NotImplemented
Expand All @@ -813,8 +813,8 @@ cdef class _Period(object):
"""
freq = self._maybe_convert_freq(freq)
how = _validate_end_alias(how)
base1, mult1 = frequencies.get_freq_code(self.freq)
base2, mult2 = frequencies.get_freq_code(freq)
base1, mult1 = get_freq_code(self.freq)
base2, mult2 = get_freq_code(freq)

# mult1 can't be negative or 0
end = how == 'E'
Expand Down Expand Up @@ -860,17 +860,17 @@ cdef class _Period(object):
how = _validate_end_alias(how)

if freq is None:
base, mult = frequencies.get_freq_code(self.freq)
base, mult = get_freq_code(self.freq)
freq = frequencies.get_to_timestamp_base(base)

base, mult = frequencies.get_freq_code(freq)
base, mult = get_freq_code(freq)
val = self.asfreq(freq, how)

dt64 = period_ordinal_to_dt64(val.ordinal, base)
return Timestamp(dt64, tz=tz)

cdef _field(self, alias):
base, mult = frequencies.get_freq_code(self.freq)
base, mult = get_freq_code(self.freq)
return get_period_field(alias, self.ordinal, base)

property year:
Expand Down Expand Up @@ -935,7 +935,7 @@ cdef class _Period(object):
return self.freq.freqstr

def __repr__(self):
base, mult = frequencies.get_freq_code(self.freq)
base, mult = get_freq_code(self.freq)
formatted = period_format(self.ordinal, base)
return "Period('%s', '%s')" % (formatted, self.freqstr)

Expand All @@ -946,7 +946,7 @@ cdef class _Period(object):
Invoked by unicode(df) in py2 only. Yields a Unicode String in both
py2/py3.
"""
base, mult = frequencies.get_freq_code(self.freq)
base, mult = get_freq_code(self.freq)
formatted = period_format(self.ordinal, base)
value = ("%s" % formatted)
return value
Expand Down Expand Up @@ -1096,7 +1096,7 @@ cdef class _Period(object):
>>> a.strftime('%b. %d, %Y was a %A')
'Jan. 01, 2001 was a Monday'
"""
base, mult = frequencies.get_freq_code(self.freq)
base, mult = get_freq_code(self.freq)
return period_format(self.ordinal, base, fmt)


Expand Down Expand Up @@ -1161,10 +1161,10 @@ class Period(_Period):
ordinal = _ordinal_from_fields(year, month, quarter, day,
hour, minute, second, freq)

elif isinstance(value, Period):
elif is_period_object(value):
other = value
if freq is None or frequencies.get_freq_code(
freq) == frequencies.get_freq_code(other.freq):
if freq is None or get_freq_code(
freq) == get_freq_code(other.freq):
ordinal = other.ordinal
freq = other.freq
else:
Expand All @@ -1174,7 +1174,7 @@ class Period(_Period):
elif is_null_datetimelike(value) or value in tslib._nat_strings:
ordinal = iNaT

elif isinstance(value, compat.string_types) or lib.is_integer(value):
elif is_string_object(value) or lib.is_integer(value):
if lib.is_integer(value):
value = str(value)
value = value.upper()
Expand All @@ -1191,7 +1191,7 @@ class Period(_Period):
dt = value
if freq is None:
raise ValueError('Must supply freq for datetime value')
elif isinstance(value, np.datetime64):
elif util.is_datetime64_object(value):
dt = Timestamp(value)
if freq is None:
raise ValueError('Must supply freq for datetime value')
Expand All @@ -1204,7 +1204,7 @@ class Period(_Period):
raise ValueError(msg)

if ordinal is None:
base, mult = frequencies.get_freq_code(freq)
base, mult = get_freq_code(freq)
ordinal = get_period_ordinal(dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.microsecond, 0, base)
Expand All @@ -1214,7 +1214,7 @@ class Period(_Period):

def _ordinal_from_fields(year, month, quarter, day,
hour, minute, second, freq):
base, mult = frequencies.get_freq_code(freq)
base, mult = get_freq_code(freq)
if quarter is not None:
year, month = _quarter_to_myear(year, quarter, freq)

Expand All @@ -1227,8 +1227,7 @@ def _quarter_to_myear(year, quarter, freq):
if quarter <= 0 or quarter > 4:
raise ValueError('Quarter must be 1 <= q <= 4')

mnum = frequencies._month_numbers[
frequencies._get_rule_month(freq)] + 1
mnum = tslib._MONTH_NUMBERS[tslib._get_rule_month(freq)] + 1
month = (mnum + (quarter - 1) * 3) % 12 + 1
if month > mnum:
year -= 1
Expand Down
4 changes: 4 additions & 0 deletions pandas/_libs/tslibs/frequencies.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# cython: profile=False

cpdef get_freq_code(freqstr)
3 changes: 3 additions & 0 deletions pandas/_libs/tslibs/frequencies.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ _period_code_map = {
"N": 12000, # Nanosecondly
}

_reverse_period_code_map = {
_period_code_map[key]: key for key in _period_code_map}

# Yearly aliases; careful not to put these in _reverse_period_code_map
_period_code_map.update({'Y' + key[1:]: _period_code_map[key]
for key in _period_code_map
Expand Down
Loading