From de377124c9ecdc18b60192c96c924ee6ba17b69e Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Feb 2018 09:25:02 -0800 Subject: [PATCH 1/7] scalar checkpoint --- pandas/_libs/src/period_helper.c | 11 +-- pandas/_libs/src/period_helper.h | 1 + pandas/_libs/tslibs/period.pyx | 142 +++++++++++++++++++++++++++++-- 3 files changed, 139 insertions(+), 15 deletions(-) diff --git a/pandas/_libs/src/period_helper.c b/pandas/_libs/src/period_helper.c index f0e24fec685d0..15aa8e36b730a 100644 --- a/pandas/_libs/src/period_helper.c +++ b/pandas/_libs/src/period_helper.c @@ -100,8 +100,7 @@ PANDAS_INLINE int get_freq_group(int freq) { return (freq / 1000) * 1000; } PANDAS_INLINE int get_freq_group_index(int freq) { return freq / 1000; } -PANDAS_INLINE npy_int64 get_daytime_conversion_factor(int from_index, - int to_index) { +npy_int64 get_daytime_conversion_factor(int from_index, int to_index) { int row = min_value(from_index, to_index); int col = max_value(from_index, to_index); // row or col < 6 means frequency strictly lower than Daily, which @@ -877,12 +876,8 @@ int get_yq(npy_int64 ordinal, int freq, int *quarter, int *year) { asfreq_info af_info; int qtr_freq; npy_int64 daily_ord; - freq_conv_func toDaily = NULL; - toDaily = get_asfreq_func(freq, FR_DAY); - get_asfreq_info(freq, FR_DAY, 'E', &af_info); - - daily_ord = toDaily(ordinal, &af_info); + daily_ord = get_python_ordinal(ordinal, freq) - ORD_OFFSET; if (get_freq_group(freq) == FR_QTR) { qtr_freq = freq; @@ -892,7 +887,7 @@ int get_yq(npy_int64 ordinal, int freq, int *quarter, int *year) { get_asfreq_info(FR_DAY, qtr_freq, 'E', &af_info); DtoQ_yq(daily_ord, &af_info, year, quarter); - return 0; + return qtr_freq; } int _quarter_year(npy_int64 ordinal, int freq, int *year, int *quarter) { diff --git a/pandas/_libs/src/period_helper.h b/pandas/_libs/src/period_helper.h index f14aec268a1fb..000cf277391ae 100644 --- a/pandas/_libs/src/period_helper.h +++ b/pandas/_libs/src/period_helper.h @@ -149,5 +149,6 @@ void get_asfreq_info(int fromFreq, int toFreq, char relation, int get_yq(npy_int64 ordinal, int freq, int *quarter, int *year); int _quarter_year(npy_int64 ordinal, int freq, int *year, int *quarter); +npy_int64 get_daytime_conversion_factor(int from_index, int to_index); #endif // PANDAS__LIBS_SRC_PERIOD_HELPER_H_ diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 3c396a9ff4f3c..78eb920e24908 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -24,7 +24,9 @@ from cpython.datetime cimport PyDateTime_Check, PyDateTime_IMPORT PyDateTime_IMPORT from np_datetime cimport (pandas_datetimestruct, dtstruct_to_dt64, - dt64_to_dtstruct) + dt64_to_dtstruct, + PANDAS_FR_D, + pandas_datetime_to_datetimestruct) cimport util from util cimport is_period_object, is_string_object, INT32_MIN @@ -52,6 +54,9 @@ from pandas.tseries import frequencies cdef extern from "period_helper.h": + int ORD_OFFSET + int FR_DAY + ctypedef struct date_info: double second int minute @@ -59,6 +64,7 @@ cdef extern from "period_helper.h": int day int month int year + int64_t absdate ctypedef struct asfreq_info: int is_end @@ -72,24 +78,22 @@ cdef extern from "period_helper.h": int from_q_year_end int to_q_year_end - ctypedef int64_t (*freq_conv_func)(int64_t, asfreq_info*) + ctypedef int64_t (*freq_conv_func)(int64_t, asfreq_info*) nogil int64_t asfreq(int64_t dtordinal, int freq1, int freq2, char relation) except INT32_MIN - freq_conv_func get_asfreq_func(int fromFreq, int toFreq) + freq_conv_func get_asfreq_func(int fromFreq, int toFreq) nogil void get_asfreq_info(int fromFreq, int toFreq, char relation, - asfreq_info *af_info) + asfreq_info *af_info) nogil int64_t get_period_ordinal(int year, int month, int day, int hour, int minute, int second, int microseconds, int picoseconds, int freq) nogil except INT32_MIN - int get_date_info(int64_t ordinal, int freq, - date_info *dinfo) nogil - int get_yq(int64_t ordinal, int freq, int *quarter, int *year) int _quarter_year(int64_t ordinal, int freq, int *year, int *quarter) + int64_t get_daytime_conversion_factor(int from_index, int to_index) nogil @cython.cdivision @@ -129,6 +133,130 @@ cdef char* c_strftime(date_info *dinfo, char *fmt): return result +# ---------------------------------------------------------------------- +# Conversion between date_info and pandas_datetimestruct + + +cdef int get_date_info(int64_t ordinal, int freq, date_info *dinfo) nogil: + cdef: + int64_t absdate + double abstime + + absdate = get_python_ordinal(ordinal, freq); + abstime = get_abs_time(freq, absdate - ORD_OFFSET, ordinal) + + while abstime < 0: + abstime += 86400 + absdate -= 1 + + while abstime >= 86400: + abstime -= 86400 + absdate += 1 + + dInfoCalc_SetFromAbsDateTime(dinfo, absdate, abstime) + return 0 + + +cdef int64_t get_python_ordinal(int64_t period_ordinal, int freq) nogil: + """ + Returns the proleptic Gregorian ordinal of the date, as an integer. + This corresponds to the number of days since Jan., 1st, 1AD. + When the instance has a frequency less than daily, the proleptic date + is calculated for the last day of the period. + """ + cdef: + asfreq_info af_info + freq_conv_func toDaily = NULL + + if freq == FR_DAY: + return period_ordinal + ORD_OFFSET + + toDaily = get_asfreq_func(freq, FR_DAY) + get_asfreq_info(freq, FR_DAY, 'E', &af_info) + return toDaily(period_ordinal, &af_info) + ORD_OFFSET + + +cdef int dInfoCalc_SetFromAbsDateTime(date_info *dinfo, + int64_t absdate, double abstime) nogil: + """ + Set the instance's value using the given date and time. + Assumes GREGORIAN_CALENDAR. + """ + # Bounds check + # The calling function is responsible for ensuring that + # abstime >= 0.0 && abstime <= 86400 + + # Calculate the date + dInfoCalc_SetFromAbsDate(dinfo, absdate) + + # Calculate the time + dInfoCalc_SetFromAbsTime(dinfo, abstime) + return 0 + + +cdef int dInfoCalc_SetFromAbsDate(date_info *dinfo, int64_t absdate) nogil: + """ + Sets the date part of the date_info struct + Assumes GREGORIAN_CALENDAR + """ + cdef: + pandas_datetimestruct dts + + pandas_datetime_to_datetimestruct(absdate - ORD_OFFSET, PANDAS_FR_D, &dts) + dinfo.year = dts.year + dinfo.month = dts.month + dinfo.day = dts.day + + dinfo.absdate = absdate + return 0 + + +@cython.cdivision +cdef int dInfoCalc_SetFromAbsTime(date_info *dinfo, double abstime) nogil: + """ + Sets the time part of the DateTime object. + """ + cdef: + int inttime + int hour, minute + double second + + inttime = abstime + hour = inttime / 3600 + minute = (inttime % 3600) / 60 + second = abstime - (hour * 3600 + minute * 60) + + dinfo.hour = hour + dinfo.minute = minute + dinfo.second = second + return 0 + + +@cython.cdivision +cdef double get_abs_time(int freq, int64_t date_ordinal, + int64_t ordinal) nogil: + cdef: + int freq_index, day_index, base_index + int64_t per_day, start_ord + double unit, result + + if freq <= FR_DAY: + return 0 + + freq_index = freq // 1000 + day_index = 6000 // 1000 + base_index = 9000 // 1000 + + per_day = get_daytime_conversion_factor(day_index, freq_index) + unit = get_daytime_conversion_factor(freq_index, base_index) + + if base_index < freq_index: + unit = 1 / unit + + start_ord = date_ordinal * per_day + result = (unit * (ordinal - start_ord)) + return result + # ---------------------------------------------------------------------- # Period logic From e2917c806c9a0661157a626044218cdbf67e46b0 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Feb 2018 09:30:29 -0800 Subject: [PATCH 2/7] de-dup quarter_year --- pandas/_libs/src/period_helper.c | 94 +------------------------------- pandas/_libs/src/period_helper.h | 1 - 2 files changed, 2 insertions(+), 93 deletions(-) diff --git a/pandas/_libs/src/period_helper.c b/pandas/_libs/src/period_helper.c index 15aa8e36b730a..63e79ea557a4b 100644 --- a/pandas/_libs/src/period_helper.c +++ b/pandas/_libs/src/period_helper.c @@ -45,7 +45,7 @@ static int monthToQuarter(int month) { return ((month - 1) / 3) + 1; } /* Find the absdate (days elapsed since datetime(1, 1, 1) * for the given year/month/day. * Assumes GREGORIAN_CALENDAR */ -static npy_int64 dInfoCalc_SetFromDateAndTime(int year, int month, int day) { +static npy_int64 absdate_from_ymd(int year, int month, int day) { /* Calculate the absolute date */ pandas_datetimestruct dts; npy_int64 unix_date; @@ -161,9 +161,6 @@ static npy_int64 DtoB(struct date_info *dinfo, int roll_back) { return DtoB_weekday(absdate); } -static npy_int64 absdate_from_ymd(int y, int m, int d) { - return dInfoCalc_SetFromDateAndTime(y, m, d); -} //************ FROM DAILY *************** @@ -674,65 +671,6 @@ freq_conv_func get_asfreq_func(int fromFreq, int toFreq) { } } -double get_abs_time(int freq, npy_int64 date_ordinal, npy_int64 ordinal) { - int freq_index, day_index, base_index; - npy_int64 per_day, start_ord; - double unit, result; - - if (freq <= FR_DAY) { - return 0; - } - - freq_index = get_freq_group_index(freq); - day_index = get_freq_group_index(FR_DAY); - base_index = get_freq_group_index(FR_SEC); - - per_day = get_daytime_conversion_factor(day_index, freq_index); - unit = get_daytime_conversion_factor(freq_index, base_index); - - if (base_index < freq_index) { - unit = 1 / unit; - } - - start_ord = date_ordinal * per_day; - result = (double)(unit * (ordinal - start_ord)); - return result; -} - -/* Sets the time part of the DateTime object. */ -static int dInfoCalc_SetFromAbsTime(struct date_info *dinfo, double abstime) { - int inttime; - int hour, minute; - double second; - - inttime = (int)abstime; - hour = inttime / 3600; - minute = (inttime % 3600) / 60; - second = abstime - (double)(hour * 3600 + minute * 60); - - dinfo->hour = hour; - dinfo->minute = minute; - dinfo->second = second; - return 0; -} - -/* Set the instance's value using the given date and time. - Assumes GREGORIAN_CALENDAR. */ -static int dInfoCalc_SetFromAbsDateTime(struct date_info *dinfo, - npy_int64 absdate, double abstime) { - /* Bounds check */ - // The calling function is responsible for ensuring that - // abstime >= 0.0 && abstime <= 86400 - - /* Calculate the date */ - dInfoCalc_SetFromAbsDate(dinfo, absdate); - - /* Calculate the time */ - dInfoCalc_SetFromAbsTime(dinfo, abstime); - - return 0; -} - /* ------------------------------------------------------------------ * New pandas API-helper code, to expose to cython * ------------------------------------------------------------------*/ @@ -894,36 +832,8 @@ int _quarter_year(npy_int64 ordinal, int freq, int *year, int *quarter) { asfreq_info af_info; int qtr_freq; - ordinal = get_python_ordinal(ordinal, freq) - ORD_OFFSET; - - if (get_freq_group(freq) == FR_QTR) - qtr_freq = freq; - else - qtr_freq = FR_QTR; - - get_asfreq_info(FR_DAY, qtr_freq, 'E', &af_info); - - DtoQ_yq(ordinal, &af_info, year, quarter); - + qtr_freq = get_yq(ordinal, freq, quarter, year); if ((qtr_freq % 1000) > 12) *year -= 1; return 0; } - - -int get_date_info(npy_int64 ordinal, int freq, struct date_info *dinfo) { - npy_int64 absdate = get_python_ordinal(ordinal, freq); - double abstime = get_abs_time(freq, absdate - ORD_OFFSET, ordinal); - - while (abstime < 0) { - abstime += 86400; - absdate -= 1; - } - while (abstime >= 86400) { - abstime -= 86400; - absdate += 1; - } - - dInfoCalc_SetFromAbsDateTime(dinfo, absdate, abstime); - return 0; -} diff --git a/pandas/_libs/src/period_helper.h b/pandas/_libs/src/period_helper.h index 000cf277391ae..652d995233d32 100644 --- a/pandas/_libs/src/period_helper.h +++ b/pandas/_libs/src/period_helper.h @@ -142,7 +142,6 @@ npy_int64 get_period_ordinal(int year, int month, int day, int hour, int minute, npy_int64 get_python_ordinal(npy_int64 period_ordinal, int freq); -int get_date_info(npy_int64 ordinal, int freq, struct date_info *dinfo); freq_conv_func get_asfreq_func(int fromFreq, int toFreq); void get_asfreq_info(int fromFreq, int toFreq, char relation, asfreq_info *af_info); From 7008262cf6b623c60884ce1c2766222b4b8f092d Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Feb 2018 09:45:47 -0800 Subject: [PATCH 3/7] scalar checkpoint --- pandas/_libs/src/period_helper.c | 104 +-------------------- pandas/_libs/src/period_helper.h | 4 - pandas/_libs/tslibs/period.pyx | 150 +++++++++++++++++++++++++++++-- 3 files changed, 143 insertions(+), 115 deletions(-) diff --git a/pandas/_libs/src/period_helper.c b/pandas/_libs/src/period_helper.c index 63e79ea557a4b..8e7d07a03d2ff 100644 --- a/pandas/_libs/src/period_helper.c +++ b/pandas/_libs/src/period_helper.c @@ -45,7 +45,7 @@ static int monthToQuarter(int month) { return ((month - 1) / 3) + 1; } /* Find the absdate (days elapsed since datetime(1, 1, 1) * for the given year/month/day. * Assumes GREGORIAN_CALENDAR */ -static npy_int64 absdate_from_ymd(int year, int month, int day) { +npy_int64 absdate_from_ymd(int year, int month, int day) { /* Calculate the absolute date */ pandas_datetimestruct dts; npy_int64 unix_date; @@ -688,108 +688,6 @@ npy_int64 asfreq(npy_int64 period_ordinal, int freq1, int freq2, return val; } -/* generate an ordinal in period space */ -npy_int64 get_period_ordinal(int year, int month, int day, int hour, int minute, - int second, int microseconds, int picoseconds, - int freq) { - npy_int64 absdays, delta, seconds; - npy_int64 weeks, days; - npy_int64 ordinal, day_adj; - int freq_group, fmonth, mdiff; - freq_group = get_freq_group(freq); - - if (freq == FR_SEC || freq == FR_MS || freq == FR_US || freq == FR_NS) { - absdays = absdate_from_ymd(year, month, day); - delta = (absdays - ORD_OFFSET); - seconds = - (npy_int64)(delta * 86400 + hour * 3600 + minute * 60 + second); - - switch (freq) { - case FR_MS: - return seconds * 1000 + microseconds / 1000; - - case FR_US: - return seconds * 1000000 + microseconds; - - case FR_NS: - return seconds * 1000000000 + microseconds * 1000 + - picoseconds / 1000; - } - - return seconds; - } - - if (freq == FR_MIN) { - absdays = absdate_from_ymd(year, month, day); - delta = (absdays - ORD_OFFSET); - return (npy_int64)(delta * 1440 + hour * 60 + minute); - } - - if (freq == FR_HR) { - absdays = absdate_from_ymd(year, month, day); - delta = (absdays - ORD_OFFSET); - return (npy_int64)(delta * 24 + hour); - } - - if (freq == FR_DAY) { - return (npy_int64)(absdate_from_ymd(year, month, day) - ORD_OFFSET); - } - - if (freq == FR_UND) { - return (npy_int64)(absdate_from_ymd(year, month, day) - ORD_OFFSET); - } - - if (freq == FR_BUS) { - days = absdate_from_ymd(year, month, day); - // calculate the current week assuming sunday as last day of a week - weeks = (days - BASE_WEEK_TO_DAY_OFFSET) / DAYS_PER_WEEK; - // calculate the current weekday (in range 1 .. 7) - delta = (days - BASE_WEEK_TO_DAY_OFFSET) % DAYS_PER_WEEK + 1; - // return the number of business days in full weeks plus the business - // days in the last - possible partial - week - return (npy_int64)(weeks * BUSINESS_DAYS_PER_WEEK) + - (delta <= BUSINESS_DAYS_PER_WEEK ? delta - : BUSINESS_DAYS_PER_WEEK + 1) - - BDAY_OFFSET; - } - - if (freq_group == FR_WK) { - ordinal = (npy_int64)absdate_from_ymd(year, month, day); - day_adj = freq - FR_WK; - return (ordinal - (1 + day_adj)) / 7 + 1 - WEEK_OFFSET; - } - - if (freq == FR_MTH) { - return (year - BASE_YEAR) * 12 + month - 1; - } - - if (freq_group == FR_QTR) { - fmonth = freq - FR_QTR; - if (fmonth == 0) fmonth = 12; - - mdiff = month - fmonth; - if (mdiff < 0) mdiff += 12; - if (month >= fmonth) mdiff += 12; - - return (year - BASE_YEAR) * 4 + (mdiff - 1) / 3; - } - - if (freq_group == FR_ANN) { - fmonth = freq - FR_ANN; - if (fmonth == 0) fmonth = 12; - if (month <= fmonth) { - return year - BASE_YEAR; - } else { - return year - BASE_YEAR + 1; - } - } - - Py_Error(PyExc_RuntimeError, "Unable to generate frequency ordinal"); - -onError: - return INT_ERR_CODE; -} - /* Returns the proleptic Gregorian ordinal of the date, as an integer. This corresponds to the number of days since Jan., 1st, 1AD. diff --git a/pandas/_libs/src/period_helper.h b/pandas/_libs/src/period_helper.h index 652d995233d32..b6a274134b29f 100644 --- a/pandas/_libs/src/period_helper.h +++ b/pandas/_libs/src/period_helper.h @@ -136,10 +136,6 @@ typedef npy_int64 (*freq_conv_func)(npy_int64, asfreq_info *af_info); npy_int64 asfreq(npy_int64 period_ordinal, int freq1, int freq2, char relation); -npy_int64 get_period_ordinal(int year, int month, int day, int hour, int minute, - int second, int microseconds, int picoseconds, - int freq); - npy_int64 get_python_ordinal(npy_int64 period_ordinal, int freq); freq_conv_func get_asfreq_func(int fromFreq, int toFreq); diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 78eb920e24908..3c0723d0f5423 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -13,7 +13,7 @@ import_array() from libc.stdlib cimport free, malloc from libc.time cimport strftime, tm -from libc.string cimport strlen +from libc.string cimport strlen, memset from pandas.compat import PY2 @@ -26,7 +26,13 @@ PyDateTime_IMPORT from np_datetime cimport (pandas_datetimestruct, dtstruct_to_dt64, dt64_to_dtstruct, PANDAS_FR_D, - pandas_datetime_to_datetimestruct) + pandas_datetime_to_datetimestruct, + PANDAS_DATETIMEUNIT) + +cdef extern from "../src/datetime/np_datetime.h": + int64_t pandas_datetimestruct_to_datetime(PANDAS_DATETIMEUNIT fr, + pandas_datetimestruct *d + ) nogil cimport util from util cimport is_period_object, is_string_object, INT32_MIN @@ -54,8 +60,24 @@ from pandas.tseries import frequencies cdef extern from "period_helper.h": - int ORD_OFFSET + int FR_ANN + int FR_QTR + int FR_MTH + int FR_WK int FR_DAY + int FR_HR + int FR_MIN + int FR_SEC + int FR_MS + int FR_US + int FR_NS + int FR_BUS + int FR_UND + + int ORD_OFFSET + int WEEK_OFFSET + int BDAY_OFFSET + int BASE_WEEK_TO_DAY_OFFSET ctypedef struct date_info: double second @@ -86,11 +108,6 @@ cdef extern from "period_helper.h": void get_asfreq_info(int fromFreq, int toFreq, char relation, asfreq_info *af_info) nogil - int64_t get_period_ordinal(int year, int month, int day, - int hour, int minute, int second, - int microseconds, int picoseconds, - int freq) nogil except INT32_MIN - int get_yq(int64_t ordinal, int freq, int *quarter, int *year) int _quarter_year(int64_t ordinal, int freq, int *year, int *quarter) int64_t get_daytime_conversion_factor(int from_index, int to_index) nogil @@ -136,6 +153,103 @@ cdef char* c_strftime(date_info *dinfo, char *fmt): # ---------------------------------------------------------------------- # Conversion between date_info and pandas_datetimestruct +cdef inline int get_freq_group(int freq) nogil: + return (freq // 1000) * 1000 + + +@cython.cdivision +cdef int64_t get_period_ordinal(int year, int month, int day, + int hour, int minute, int second, + int microseconds, int picoseconds, + int freq) nogil: + """generate an ordinal in period space""" + cdef: + int64_t absdays, delta, seconds + int64_t weeks, days + int64_t ordinal, day_adj + int freq_group, fmonth, mdiff + + freq_group = get_freq_group(freq) + + if freq >= FR_SEC: + absdays = absdate_from_ymd(year, month, day) + delta = absdays - ORD_OFFSET + seconds = (delta * 86400 + hour * 3600 + minute * 60 + second) + + if freq == FR_MS: + return seconds * 1000 + microseconds / 1000 + + elif freq == FR_US: + return seconds * 1000000 + microseconds + + elif freq == FR_NS: + return seconds * 1000000000 + microseconds * 1000 + picoseconds / 1000 + + else: + return seconds + + if freq == FR_MIN: + absdays = absdate_from_ymd(year, month, day) + delta = absdays - ORD_OFFSET + return (delta * 1440 + hour * 60 + minute) + + if freq == FR_HR: + absdays = absdate_from_ymd(year, month, day) + delta = absdays - ORD_OFFSET + return (delta * 24 + hour) + + if freq == FR_DAY: + return (absdate_from_ymd(year, month, day) - ORD_OFFSET) + + if freq == FR_UND: + return (absdate_from_ymd(year, month, day) - ORD_OFFSET) + + if freq == FR_BUS: + days = absdate_from_ymd(year, month, day); + # calculate the current week assuming sunday as last day of a week + weeks = (days - BASE_WEEK_TO_DAY_OFFSET) / 7 + # calculate the current weekday (in range 1 .. 7) + delta = (days - BASE_WEEK_TO_DAY_OFFSET) % 7 + 1 + # return the number of business days in full weeks plus the business + # days in the last - possible partial - week + if delta <= 5: + return (weeks * 5) + delta - BDAY_OFFSET + else: + return (weeks * 5) + (5 + 1) - BDAY_OFFSET + + if freq_group == FR_WK: + ordinal = absdate_from_ymd(year, month, day) + day_adj = freq - FR_WK + return (ordinal - (1 + day_adj)) / 7 + 1 - WEEK_OFFSET + + if freq == FR_MTH: + return (year - 1970) * 12 + month - 1; + + if freq_group == FR_QTR: + fmonth = freq - FR_QTR + if fmonth == 0: + fmonth = 12 + + mdiff = month - fmonth + # TODO: Aren't the next two conditions equivalent to unconditional incrementing? + if mdiff < 0: + mdiff += 12 + if month >= fmonth: + mdiff += 12 + + return (year - 1970) * 4 + (mdiff - 1) / 3 + + if freq_group == FR_ANN: + fmonth = freq - FR_ANN + if fmonth == 0: + fmonth = 12 + if month <= fmonth: + return year - 1970 + else: + return year - 1970 + 1 + + # raise ValueError + cdef int get_date_info(int64_t ordinal, int freq, date_info *dinfo) nogil: cdef: @@ -257,6 +371,26 @@ cdef double get_abs_time(int freq, int64_t date_ordinal, result = (unit * (ordinal - start_ord)) return result + +cdef int64_t absdate_from_ymd(int year, int month, int day) nogil: + """ + Find the absdate (days elapsed since datetime(1, 1, 1) + for the given year/month/day. + Assumes GREGORIAN_CALENDAR + """ + # /* Calculate the absolute date + cdef: + pandas_datetimestruct dts + int64_t unix_date + + memset(&dts, 0, sizeof(pandas_datetimestruct)) + dts.year = year + dts.month = month + dts.day = day + unix_date = pandas_datetimestruct_to_datetime(PANDAS_FR_D, &dts) + return ORD_OFFSET + unix_date + + # ---------------------------------------------------------------------- # Period logic From 251a166acc53c04ba4dd12dbab1ae1c836eda899 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Feb 2018 10:19:09 -0800 Subject: [PATCH 4/7] tentative commit so i can run asv --- pandas/_libs/src/period_helper.c | 47 ++++------ pandas/_libs/src/period_helper.h | 3 - pandas/_libs/tslibs/period.pyx | 145 +++++++++++++++---------------- 3 files changed, 89 insertions(+), 106 deletions(-) diff --git a/pandas/_libs/src/period_helper.c b/pandas/_libs/src/period_helper.c index 8e7d07a03d2ff..d4553df1b7edc 100644 --- a/pandas/_libs/src/period_helper.c +++ b/pandas/_libs/src/period_helper.c @@ -68,8 +68,6 @@ static int dInfoCalc_SetFromAbsDate(register struct date_info *dinfo, dinfo->year = dts.year; dinfo->month = dts.month; dinfo->day = dts.day; - - dinfo->absdate = absdate; return 0; } @@ -143,9 +141,9 @@ static npy_int64 DtoB_weekday(npy_int64 absdate) { return (((absdate) / 7) * 5) + (absdate) % 7 - BDAY_OFFSET; } -static npy_int64 DtoB(struct date_info *dinfo, int roll_back) { +static npy_int64 DtoB(struct date_info *dinfo, + int roll_back, npy_int64 absdate) { int day_of_week = dayofweek(dinfo->year, dinfo->month, dinfo->day); - npy_int64 absdate = dinfo->absdate; if (roll_back == 1) { if (day_of_week > 4) { @@ -220,15 +218,16 @@ static npy_int64 asfreq_DTtoW(npy_int64 ordinal, asfreq_info *af_info) { static npy_int64 asfreq_DTtoB(npy_int64 ordinal, asfreq_info *af_info) { struct date_info dinfo; + npy_int64 absdate; int roll_back; ordinal = downsample_daytime(ordinal, af_info); - - dInfoCalc_SetFromAbsDate(&dinfo, ordinal + ORD_OFFSET); + absdate = ordinal + ORD_OFFSET; + dInfoCalc_SetFromAbsDate(&dinfo, absdate); // This usage defines roll_back the opposite way from the others roll_back = 1 - af_info->is_end; - return DtoB(&dinfo, roll_back); + return DtoB(&dinfo, roll_back, absdate); } // all intra day calculations are now done within one function @@ -294,11 +293,11 @@ static npy_int64 asfreq_WtoW(npy_int64 ordinal, asfreq_info *af_info) { static npy_int64 asfreq_WtoB(npy_int64 ordinal, asfreq_info *af_info) { struct date_info dinfo; + npy_int64 absdate = asfreq_WtoDT(ordinal, af_info) + ORD_OFFSET; int roll_back = af_info->is_end; - dInfoCalc_SetFromAbsDate( - &dinfo, asfreq_WtoDT(ordinal, af_info) + ORD_OFFSET); + dInfoCalc_SetFromAbsDate(&dinfo, absdate); - return DtoB(&dinfo, roll_back); + return DtoB(&dinfo, roll_back, absdate); } //************ FROM MONTHLY *************** @@ -334,12 +333,12 @@ static npy_int64 asfreq_MtoW(npy_int64 ordinal, asfreq_info *af_info) { static npy_int64 asfreq_MtoB(npy_int64 ordinal, asfreq_info *af_info) { struct date_info dinfo; + npy_int64 absdate = asfreq_MtoDT(ordinal, af_info) + ORD_OFFSET; int roll_back = af_info->is_end; - dInfoCalc_SetFromAbsDate( - &dinfo, asfreq_MtoDT(ordinal, af_info) + ORD_OFFSET); + dInfoCalc_SetFromAbsDate(&dinfo, absdate); - return DtoB(&dinfo, roll_back); + return DtoB(&dinfo, roll_back, absdate); } //************ FROM QUARTERLY *************** @@ -389,12 +388,12 @@ static npy_int64 asfreq_QtoW(npy_int64 ordinal, asfreq_info *af_info) { static npy_int64 asfreq_QtoB(npy_int64 ordinal, asfreq_info *af_info) { struct date_info dinfo; + npy_int64 absdate = asfreq_QtoDT(ordinal, af_info) + ORD_OFFSET; int roll_back = af_info->is_end; - dInfoCalc_SetFromAbsDate( - &dinfo, asfreq_QtoDT(ordinal, af_info) + ORD_OFFSET); + dInfoCalc_SetFromAbsDate(&dinfo, absdate); - return DtoB(&dinfo, roll_back); + return DtoB(&dinfo, roll_back, absdate); } //************ FROM ANNUAL *************** @@ -435,11 +434,11 @@ static npy_int64 asfreq_AtoW(npy_int64 ordinal, asfreq_info *af_info) { static npy_int64 asfreq_AtoB(npy_int64 ordinal, asfreq_info *af_info) { struct date_info dinfo; + npy_int64 absdate = asfreq_AtoDT(ordinal, af_info) + ORD_OFFSET; int roll_back = af_info->is_end; - dInfoCalc_SetFromAbsDate( - &dinfo, asfreq_AtoDT(ordinal, af_info) + ORD_OFFSET); + dInfoCalc_SetFromAbsDate(&dinfo, absdate); - return DtoB(&dinfo, roll_back); + return DtoB(&dinfo, roll_back, absdate); } static npy_int64 nofunc(npy_int64 ordinal, asfreq_info *af_info) { @@ -725,13 +724,3 @@ int get_yq(npy_int64 ordinal, int freq, int *quarter, int *year) { DtoQ_yq(daily_ord, &af_info, year, quarter); return qtr_freq; } - -int _quarter_year(npy_int64 ordinal, int freq, int *year, int *quarter) { - asfreq_info af_info; - int qtr_freq; - - qtr_freq = get_yq(ordinal, freq, quarter, year); - if ((qtr_freq % 1000) > 12) *year -= 1; - - return 0; -} diff --git a/pandas/_libs/src/period_helper.h b/pandas/_libs/src/period_helper.h index b6a274134b29f..9278c18415032 100644 --- a/pandas/_libs/src/period_helper.h +++ b/pandas/_libs/src/period_helper.h @@ -118,8 +118,6 @@ typedef struct asfreq_info { } asfreq_info; typedef struct date_info { - npy_int64 absdate; - double second; int minute; int hour; @@ -143,7 +141,6 @@ void get_asfreq_info(int fromFreq, int toFreq, char relation, asfreq_info *af_info); int get_yq(npy_int64 ordinal, int freq, int *quarter, int *year); -int _quarter_year(npy_int64 ordinal, int freq, int *year, int *quarter); npy_int64 get_daytime_conversion_factor(int from_index, int to_index); #endif // PANDAS__LIBS_SRC_PERIOD_HELPER_H_ diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 3c0723d0f5423..7a0356814a243 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -86,7 +86,6 @@ cdef extern from "period_helper.h": int day int month int year - int64_t absdate ctypedef struct asfreq_info: int is_end @@ -109,7 +108,6 @@ cdef extern from "period_helper.h": asfreq_info *af_info) nogil int get_yq(int64_t ordinal, int freq, int *quarter, int *year) - int _quarter_year(int64_t ordinal, int freq, int *year, int *quarter) int64_t get_daytime_conversion_factor(int from_index, int to_index) nogil @@ -164,17 +162,45 @@ cdef int64_t get_period_ordinal(int year, int month, int day, int freq) nogil: """generate an ordinal in period space""" cdef: - int64_t absdays, delta, seconds - int64_t weeks, days - int64_t ordinal, day_adj + int64_t absdays, unix_date, seconds, delta + int64_t weeks + int64_t day_adj int freq_group, fmonth, mdiff freq_group = get_freq_group(freq) + if freq_group == FR_ANN: + fmonth = freq - FR_ANN + if fmonth == 0: + fmonth = 12 + if month <= fmonth: + return year - 1970 + else: + return year - 1970 + 1 + + elif freq_group == FR_QTR: + fmonth = freq - FR_QTR + if fmonth == 0: + fmonth = 12 + + mdiff = month - fmonth + # TODO: Aren't the next two conditions equivalent to + # unconditional incrementing? + if mdiff < 0: + mdiff += 12 + if month >= fmonth: + mdiff += 12 + + return (year - 1970) * 4 + (mdiff - 1) / 3 + + elif freq == FR_MTH: + return (year - 1970) * 12 + month - 1; + + absdays = absdate_from_ymd(year, month, day) + unix_date = absdays - ORD_OFFSET + if freq >= FR_SEC: - absdays = absdate_from_ymd(year, month, day) - delta = absdays - ORD_OFFSET - seconds = (delta * 86400 + hour * 3600 + minute * 60 + second) + seconds = unix_date * 86400 + hour * 3600 + minute * 60 + second if freq == FR_MS: return seconds * 1000 + microseconds / 1000 @@ -183,70 +209,39 @@ cdef int64_t get_period_ordinal(int year, int month, int day, return seconds * 1000000 + microseconds elif freq == FR_NS: - return seconds * 1000000000 + microseconds * 1000 + picoseconds / 1000 + return (seconds * 1000000000 + + microseconds * 1000 + picoseconds / 1000) else: return seconds - if freq == FR_MIN: - absdays = absdate_from_ymd(year, month, day) - delta = absdays - ORD_OFFSET - return (delta * 1440 + hour * 60 + minute) + elif freq == FR_MIN: + return unix_date * 1440 + hour * 60 + minute - if freq == FR_HR: - absdays = absdate_from_ymd(year, month, day) - delta = absdays - ORD_OFFSET - return (delta * 24 + hour) + elif freq == FR_HR: + return unix_date * 24 + hour - if freq == FR_DAY: - return (absdate_from_ymd(year, month, day) - ORD_OFFSET) + elif freq == FR_DAY: + return unix_date - if freq == FR_UND: - return (absdate_from_ymd(year, month, day) - ORD_OFFSET) + elif freq == FR_UND: + return unix_date - if freq == FR_BUS: - days = absdate_from_ymd(year, month, day); + elif freq == FR_BUS: # calculate the current week assuming sunday as last day of a week - weeks = (days - BASE_WEEK_TO_DAY_OFFSET) / 7 + weeks = (unix_date + ORD_OFFSET - BASE_WEEK_TO_DAY_OFFSET) / 7 # calculate the current weekday (in range 1 .. 7) - delta = (days - BASE_WEEK_TO_DAY_OFFSET) % 7 + 1 + delta = (unix_date + ORD_OFFSET - BASE_WEEK_TO_DAY_OFFSET) % 7 + 1 # return the number of business days in full weeks plus the business # days in the last - possible partial - week if delta <= 5: - return (weeks * 5) + delta - BDAY_OFFSET + return (weeks * 5) + delta - BDAY_OFFSET else: - return (weeks * 5) + (5 + 1) - BDAY_OFFSET + return (weeks * 5) + (5 + 1) - BDAY_OFFSET - if freq_group == FR_WK: - ordinal = absdate_from_ymd(year, month, day) + elif freq_group == FR_WK: day_adj = freq - FR_WK - return (ordinal - (1 + day_adj)) / 7 + 1 - WEEK_OFFSET - - if freq == FR_MTH: - return (year - 1970) * 12 + month - 1; - - if freq_group == FR_QTR: - fmonth = freq - FR_QTR - if fmonth == 0: - fmonth = 12 - - mdiff = month - fmonth - # TODO: Aren't the next two conditions equivalent to unconditional incrementing? - if mdiff < 0: - mdiff += 12 - if month >= fmonth: - mdiff += 12 - - return (year - 1970) * 4 + (mdiff - 1) / 3 - - if freq_group == FR_ANN: - fmonth = freq - FR_ANN - if fmonth == 0: - fmonth = 12 - if month <= fmonth: - return year - 1970 - else: - return year - 1970 + 1 + return (unix_date + ORD_OFFSET - (1 + day_adj)) / 7 + 1 - WEEK_OFFSET # raise ValueError @@ -298,7 +293,7 @@ cdef int dInfoCalc_SetFromAbsDateTime(date_info *dinfo, """ # Bounds check # The calling function is responsible for ensuring that - # abstime >= 0.0 && abstime <= 86400 + # abstime >= 0.0 and abstime <= 86400 # Calculate the date dInfoCalc_SetFromAbsDate(dinfo, absdate) @@ -320,8 +315,6 @@ cdef int dInfoCalc_SetFromAbsDate(date_info *dinfo, int64_t absdate) nogil: dinfo.year = dts.year dinfo.month = dts.month dinfo.day = dts.day - - dinfo.absdate = absdate return 0 @@ -358,8 +351,8 @@ cdef double get_abs_time(int freq, int64_t date_ordinal, return 0 freq_index = freq // 1000 - day_index = 6000 // 1000 - base_index = 9000 // 1000 + day_index = FR_DAY // 1000 + base_index = FR_SEC // 1000 per_day = get_daytime_conversion_factor(day_index, freq_index) unit = get_daytime_conversion_factor(freq_index, base_index) @@ -455,8 +448,7 @@ cdef char START = 'S' cdef char END = 'E' -cpdef int64_t period_asfreq(int64_t period_ordinal, int freq1, int freq2, - bint end): +cpdef int64_t period_asfreq(int64_t ordinal, int freq1, int freq2, bint end): """ Convert period ordinal from one frequency to another, and if upsampling, choose to use start ('S') or end ('E') of period. @@ -464,13 +456,13 @@ cpdef int64_t period_asfreq(int64_t period_ordinal, int freq1, int freq2, cdef: int64_t retval - if period_ordinal == iNaT: + if ordinal == iNaT: return iNaT if end: - retval = asfreq(period_ordinal, freq1, freq2, END) + retval = asfreq(ordinal, freq1, freq2, END) else: - retval = asfreq(period_ordinal, freq1, freq2, START) + retval = asfreq(ordinal, freq1, freq2, START) if retval == INT32_MIN: raise ValueError('Frequency conversion failed') @@ -487,7 +479,7 @@ def period_asfreq_arr(ndarray[int64_t] arr, int freq1, int freq2, bint end): ndarray[int64_t] result Py_ssize_t i, n freq_conv_func func - asfreq_info finfo + asfreq_info af_info int64_t val char relation @@ -500,20 +492,20 @@ def period_asfreq_arr(ndarray[int64_t] arr, int freq1, int freq2, bint end): relation = START func = get_asfreq_func(freq1, freq2) - get_asfreq_info(freq1, freq2, relation, &finfo) + get_asfreq_info(freq1, freq2, relation, &af_info) mask = arr == iNaT if mask.any(): # NaT process for i in range(n): val = arr[i] if val != iNaT: - val = func(val, &finfo) + val = func(val, &af_info) if val == INT32_MIN: raise ValueError("Unable to convert to desired frequency.") result[i] = val else: for i in range(n): - val = func(arr[i], &finfo) + val = func(arr[i], &af_info) if val == INT32_MIN: raise ValueError("Unable to convert to desired frequency.") result[i] = val @@ -665,17 +657,22 @@ cdef int pyear(int64_t ordinal, int freq): return dinfo.year +@cython.cdivision cdef int pqyear(int64_t ordinal, int freq): cdef: - int year, quarter - _quarter_year(ordinal, freq, &year, &quarter) + int year, quarter, qtr_freq + qtr_freq = get_yq(ordinal, freq, &quarter, &year) + if (qtr_freq % 1000) > 12: + year -= 1 return year cdef int pquarter(int64_t ordinal, int freq): cdef: - int year, quarter - _quarter_year(ordinal, freq, &year, &quarter) + int year, quarter, qtr_freq + qtr_freq = get_yq(ordinal, freq, &quarter, &year) + if (qtr_freq % 1000) > 12: + year -= 1 return quarter From c50d1f6064804e08999c5e72e9ee1fa7ee3f0adf Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Feb 2018 11:01:02 -0800 Subject: [PATCH 5/7] checkpoint --- pandas/_libs/tslibs/period.pyx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 7a0356814a243..279f10e5b3502 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -77,7 +77,6 @@ cdef extern from "period_helper.h": int ORD_OFFSET int WEEK_OFFSET int BDAY_OFFSET - int BASE_WEEK_TO_DAY_OFFSET ctypedef struct date_info: double second @@ -229,9 +228,11 @@ cdef int64_t get_period_ordinal(int year, int month, int day, elif freq == FR_BUS: # calculate the current week assuming sunday as last day of a week - weeks = (unix_date + ORD_OFFSET - BASE_WEEK_TO_DAY_OFFSET) / 7 + # Jan 1 0001 is a Monday, so subtract 1 to get to end-of-week + # Jan 1 1970 was a Thursday, so subtract 3 to get to end-of-week (Sun) + weeks = (unix_date + ORD_OFFSET - 1) / 7 # calculate the current weekday (in range 1 .. 7) - delta = (unix_date + ORD_OFFSET - BASE_WEEK_TO_DAY_OFFSET) % 7 + 1 + delta = (unix_date + ORD_OFFSET - 1) % 7 + 1 # return the number of business days in full weeks plus the business # days in the last - possible partial - week if delta <= 5: From 03a520689217f7f2ade77d3129dac6d1b031b94b Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Feb 2018 13:11:04 -0800 Subject: [PATCH 6/7] scalar checkpoint --- pandas/_libs/src/period_helper.c | 38 -------------------------- pandas/_libs/src/period_helper.h | 3 -- pandas/_libs/tslibs/period.pyx | 47 +++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 45 deletions(-) diff --git a/pandas/_libs/src/period_helper.c b/pandas/_libs/src/period_helper.c index d4553df1b7edc..7c4de8e42e73b 100644 --- a/pandas/_libs/src/period_helper.c +++ b/pandas/_libs/src/period_helper.c @@ -686,41 +686,3 @@ npy_int64 asfreq(npy_int64 period_ordinal, int freq1, int freq2, val = (*func)(period_ordinal, &finfo); return val; } - -/* - Returns the proleptic Gregorian ordinal of the date, as an integer. - This corresponds to the number of days since Jan., 1st, 1AD. - When the instance has a frequency less than daily, the proleptic date - is calculated for the last day of the period. - */ - -npy_int64 get_python_ordinal(npy_int64 period_ordinal, int freq) { - asfreq_info af_info; - freq_conv_func toDaily = NULL; - - if (freq == FR_DAY) return period_ordinal + ORD_OFFSET; - - toDaily = get_asfreq_func(freq, FR_DAY); - get_asfreq_info(freq, FR_DAY, 'E', &af_info); - - return toDaily(period_ordinal, &af_info) + ORD_OFFSET; -} - - -int get_yq(npy_int64 ordinal, int freq, int *quarter, int *year) { - asfreq_info af_info; - int qtr_freq; - npy_int64 daily_ord; - - daily_ord = get_python_ordinal(ordinal, freq) - ORD_OFFSET; - - if (get_freq_group(freq) == FR_QTR) { - qtr_freq = freq; - } else { - qtr_freq = FR_QTR; - } - get_asfreq_info(FR_DAY, qtr_freq, 'E', &af_info); - - DtoQ_yq(daily_ord, &af_info, year, quarter); - return qtr_freq; -} diff --git a/pandas/_libs/src/period_helper.h b/pandas/_libs/src/period_helper.h index 9278c18415032..1573b1eeec74b 100644 --- a/pandas/_libs/src/period_helper.h +++ b/pandas/_libs/src/period_helper.h @@ -134,13 +134,10 @@ typedef npy_int64 (*freq_conv_func)(npy_int64, asfreq_info *af_info); npy_int64 asfreq(npy_int64 period_ordinal, int freq1, int freq2, char relation); -npy_int64 get_python_ordinal(npy_int64 period_ordinal, int freq); - freq_conv_func get_asfreq_func(int fromFreq, int toFreq); void get_asfreq_info(int fromFreq, int toFreq, char relation, asfreq_info *af_info); -int get_yq(npy_int64 ordinal, int freq, int *quarter, int *year); npy_int64 get_daytime_conversion_factor(int from_index, int to_index); #endif // PANDAS__LIBS_SRC_PERIOD_HELPER_H_ diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 279f10e5b3502..cf5f1b4c67148 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -106,7 +106,6 @@ cdef extern from "period_helper.h": void get_asfreq_info(int fromFreq, int toFreq, char relation, asfreq_info *af_info) nogil - int get_yq(int64_t ordinal, int freq, int *quarter, int *year) int64_t get_daytime_conversion_factor(int from_index, int to_index) nogil @@ -176,7 +175,7 @@ cdef int64_t get_period_ordinal(int year, int month, int day, return year - 1970 else: return year - 1970 + 1 - + elif freq_group == FR_QTR: fmonth = freq - FR_QTR if fmonth == 0: @@ -193,7 +192,7 @@ cdef int64_t get_period_ordinal(int year, int month, int day, return (year - 1970) * 4 + (mdiff - 1) / 3 elif freq == FR_MTH: - return (year - 1970) * 12 + month - 1; + return (year - 1970) * 12 + month - 1 absdays = absdate_from_ymd(year, month, day) unix_date = absdays - ORD_OFFSET @@ -229,7 +228,6 @@ cdef int64_t get_period_ordinal(int year, int month, int day, elif freq == FR_BUS: # calculate the current week assuming sunday as last day of a week # Jan 1 0001 is a Monday, so subtract 1 to get to end-of-week - # Jan 1 1970 was a Thursday, so subtract 3 to get to end-of-week (Sun) weeks = (unix_date + ORD_OFFSET - 1) / 7 # calculate the current weekday (in range 1 .. 7) delta = (unix_date + ORD_OFFSET - 1) % 7 + 1 @@ -385,6 +383,47 @@ cdef int64_t absdate_from_ymd(int year, int month, int day) nogil: return ORD_OFFSET + unix_date +cdef int get_yq(int64_t ordinal, int freq, int *quarter, int *year): + cdef: + asfreq_info af_info + int qtr_freq + int64_t daily_ord + + daily_ord = get_python_ordinal(ordinal, freq) - ORD_OFFSET + + if get_freq_group(freq) == FR_QTR: + qtr_freq = freq + else: + qtr_freq = FR_QTR + + get_asfreq_info(FR_DAY, qtr_freq, 'E', &af_info) + + DtoQ_yq(daily_ord, &af_info, year, quarter) + return qtr_freq + + +cdef int64_t DtoQ_yq(int64_t ordinal, asfreq_info *af_info, + int *year, int *quarter): + cdef: + date_info dinfo + + dInfoCalc_SetFromAbsDate(&dinfo, ordinal + ORD_OFFSET) + + if af_info.to_q_year_end != 12: + dinfo.month -= af_info.to_q_year_end + if dinfo.month <= 0: + dinfo.month += 12 + else: + dinfo.year += 1 + + year[0] = dinfo.year + quarter[0] = monthToQuarter(dinfo.month) + return 0 + + +cdef inline int monthToQuarter(int month): + return (month - 1) // 3 + 1 + # ---------------------------------------------------------------------- # Period logic From 769feee147b0e2543a86d320f4ec8f317975398e Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 8 Feb 2018 13:23:27 -0800 Subject: [PATCH 7/7] fixup whitespace --- pandas/_libs/tslibs/period.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index cf5f1b4c67148..03d28af5e7f27 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -424,6 +424,7 @@ cdef int64_t DtoQ_yq(int64_t ordinal, asfreq_info *af_info, cdef inline int monthToQuarter(int month): return (month - 1) // 3 + 1 + # ---------------------------------------------------------------------- # Period logic