Skip to content

REF: de-duplicate code in libperiod #33491

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 18 commits into from
Apr 15, 2020
Merged
Changes from 12 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
60cf071
Handle time-part of datetime in int64 nanoseconds rather than float s…
jbrockmendel Feb 1, 2020
9e36d99
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Feb 1, 2020
40d8426
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Feb 2, 2020
1019e2e
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Feb 3, 2020
d1d44a7
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Feb 4, 2020
8013c05
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Feb 9, 2020
b5d563b
remove workaround
jbrockmendel Feb 10, 2020
6ca98fe
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Feb 10, 2020
6743180
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Feb 21, 2020
12c8b31
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Mar 3, 2020
eb887bc
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Mar 7, 2020
b76d3a8
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Apr 12, 2020
50480c3
if -> elif
jbrockmendel Apr 12, 2020
10720d3
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Apr 13, 2020
edbb448
Merge branch 'master' of https://github.com/pandas-dev/pandas into pe…
jbrockmendel Apr 14, 2020
b911eb2
dummy commit to force CI
jbrockmendel Apr 14, 2020
a0d475f
Dummy commit to force CI
jbrockmendel Apr 14, 2020
e82a8c6
Fix compiler warning
jbrockmendel Apr 14, 2020
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
107 changes: 38 additions & 69 deletions pandas/_libs/tslibs/period.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -806,24 +806,22 @@ cdef int64_t get_period_ordinal(npy_datetimestruct *dts, int freq) nogil:
return unix_date_to_week(unix_date, freq - FR_WK)


cdef void get_date_info(int64_t ordinal, int freq,
npy_datetimestruct *dts) nogil:
cdef void get_date_info(int64_t ordinal, int freq, npy_datetimestruct *dts) nogil:
cdef:
int64_t unix_date
double abstime
int64_t unix_date, nanos
npy_datetimestruct dts2

unix_date = get_unix_date(ordinal, freq)
abstime = get_abs_time(freq, unix_date, ordinal)

while abstime < 0:
abstime += 86400
unix_date -= 1
nanos = get_time_nanos(freq, unix_date, ordinal)

while abstime >= 86400:
abstime -= 86400
unix_date += 1
pandas_datetime_to_datetimestruct(unix_date, NPY_FR_D, dts)

date_info_from_days_and_time(dts, unix_date, abstime)
dt64_to_dtstruct(nanos, &dts2)
dts.hour = dts2.hour
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason you don't just pass the reference to dts in the call above?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the caller might still need dts

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't calling dt64_to_dtstruct do exactly what the next 5 lines of code do anyway?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i can confirm that just passing dts does Break The World. IIRC part of whats going on here is that dts may be out of bounds for dt64[ns]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah OK. Thanks for checking - seems strange to have to do this but probably a separate issue then

dts.min = dts2.min
dts.sec = dts2.sec
dts.us = dts2.us
dts.ps = dts2.ps


cdef int64_t get_unix_date(int64_t period_ordinal, int freq) nogil:
Expand Down Expand Up @@ -855,74 +853,49 @@ cdef int64_t get_unix_date(int64_t period_ordinal, int freq) nogil:


@cython.cdivision
cdef void date_info_from_days_and_time(npy_datetimestruct *dts,
int64_t unix_date,
double abstime) nogil:
cdef int64_t get_time_nanos(int freq, int64_t unix_date, int64_t ordinal) nogil:
"""
Set the instance's value using the given date and time.
Find the number of nanoseconds after midnight on the given unix_date
that the ordinal represents in the given frequency.

Parameters
----------
dts : npy_datetimestruct*
freq : int
unix_date : int64_t
days elapsed since datetime(1970, 1, 1)
abstime : double
seconds elapsed since beginning of day described by unix_date
ordinal : int64_t

Notes
-----
Updates dts inplace
Returns
-------
int64_t
"""
cdef:
int inttime
int hour, minute
double second, subsecond_fraction

# Bounds check
# The calling function is responsible for ensuring that
# abstime >= 0.0 and abstime <= 86400
int64_t sub, factor

# Calculate the date
pandas_datetime_to_datetimestruct(unix_date, NPY_FR_D, dts)
freq = get_freq_group(freq)

# Calculate the time
inttime = <int>abstime
hour = inttime / 3600
minute = (inttime % 3600) / 60
second = abstime - <double>(hour * 3600 + minute * 60)
if freq <= FR_DAY:
return 0

dts.hour = hour
dts.min = minute
dts.sec = <int>second
if freq == FR_NS:
factor = 1

subsecond_fraction = second - dts.sec
dts.us = int((subsecond_fraction) * 1e6)
dts.ps = int(((subsecond_fraction) * 1e6 - dts.us) * 1e6)
if freq == FR_US:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elif on these?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated+green

factor = 10**3

if freq == FR_MS:
factor = 10**6

@cython.cdivision
cdef double get_abs_time(int freq, int64_t unix_date, int64_t ordinal) nogil:
cdef:
int freq_index, day_index, base_index
int64_t per_day, start_ord
double unit, result
if freq == FR_SEC:
factor = 10 **9

if freq <= FR_DAY:
return 0
if freq == FR_MIN:
factor = 10**9 * 60

freq_index = freq // 1000
day_index = FR_DAY // 1000
base_index = FR_SEC // 1000
if freq == FR_HR:
factor = 10**9 * 3600

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 = unix_date * per_day
result = <double>(unit * (ordinal - start_ord))
return result
sub = ordinal - unix_date * 24 * 3600 * 10**9 / factor
return sub * factor


cdef int get_yq(int64_t ordinal, int freq, int *quarter, int *year):
Expand Down Expand Up @@ -1176,11 +1149,7 @@ cdef int64_t period_ordinal_to_dt64(int64_t ordinal, int freq) except? -1:
if ordinal == NPY_NAT:
return NPY_NAT

if freq == 11000:
# Microsecond, avoid get_date_info to prevent floating point errors
pandas_datetime_to_datetimestruct(ordinal, NPY_FR_us, &dts)
else:
get_date_info(ordinal, freq, &dts)
get_date_info(ordinal, freq, &dts)

check_dts_bounds(&dts)
return dtstruct_to_dt64(&dts)
Expand Down