Skip to content

Commit 1a586e2

Browse files
jbrockmendeljreback
authored andcommitted
Trim unncessary code in datetime/np_datetime.c (#21962)
1 parent 652a3de commit 1a586e2

File tree

4 files changed

+34
-174
lines changed

4 files changed

+34
-174
lines changed

pandas/_libs/src/datetime/np_datetime.c

+22-161
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,7 @@ NPY_NO_EXPORT void add_seconds_to_datetimestruct(npy_datetimestruct *dts,
235235
* Fills in the year, month, day in 'dts' based on the days
236236
* offset from 1970.
237237
*/
238-
static void set_datetimestruct_days(npy_int64 days,
239-
npy_datetimestruct *dts) {
238+
static void set_datetimestruct_days(npy_int64 days, npy_datetimestruct *dts) {
240239
const int *month_lengths;
241240
int i;
242241

@@ -318,7 +317,7 @@ int cmp_npy_datetimestruct(const npy_datetimestruct *a,
318317

319318
/*
320319
*
321-
* Tests for and converts a Python datetime.datetime or datetime.date
320+
* Converts a Python datetime.datetime or datetime.date
322321
* object into a NumPy npy_datetimestruct. Uses tzinfo (if present)
323322
* to convert to UTC time.
324323
*
@@ -330,68 +329,22 @@ int cmp_npy_datetimestruct(const npy_datetimestruct *a,
330329
* Returns -1 on error, 0 on success, and 1 (with no error set)
331330
* if obj doesn't have the needed date or datetime attributes.
332331
*/
333-
int convert_pydatetime_to_datetimestruct(PyObject *obj,
332+
int convert_pydatetime_to_datetimestruct(PyDateTime_Date *obj,
334333
npy_datetimestruct *out) {
334+
// Assumes that obj is a valid datetime object
335335
PyObject *tmp;
336-
int isleap;
337336

338337
/* Initialize the output to all zeros */
339338
memset(out, 0, sizeof(npy_datetimestruct));
340339
out->month = 1;
341340
out->day = 1;
342341

343-
/* Need at least year/month/day attributes */
344-
if (!PyObject_HasAttrString(obj, "year") ||
345-
!PyObject_HasAttrString(obj, "month") ||
346-
!PyObject_HasAttrString(obj, "day")) {
347-
return 1;
348-
}
349-
350-
/* Get the year */
351-
tmp = PyObject_GetAttrString(obj, "year");
352-
if (tmp == NULL) {
353-
return -1;
354-
}
355-
out->year = PyInt_AsLong(tmp);
356-
if (out->year == -1 && PyErr_Occurred()) {
357-
Py_DECREF(tmp);
358-
return -1;
359-
}
360-
Py_DECREF(tmp);
361-
362-
/* Get the month */
363-
tmp = PyObject_GetAttrString(obj, "month");
364-
if (tmp == NULL) {
365-
return -1;
366-
}
367-
out->month = PyInt_AsLong(tmp);
368-
if (out->month == -1 && PyErr_Occurred()) {
369-
Py_DECREF(tmp);
370-
return -1;
371-
}
372-
Py_DECREF(tmp);
373-
374-
/* Get the day */
375-
tmp = PyObject_GetAttrString(obj, "day");
376-
if (tmp == NULL) {
377-
return -1;
378-
}
379-
out->day = PyInt_AsLong(tmp);
380-
if (out->day == -1 && PyErr_Occurred()) {
381-
Py_DECREF(tmp);
382-
return -1;
383-
}
384-
Py_DECREF(tmp);
342+
out->year = PyInt_AsLong(PyObject_GetAttrString(obj, "year"));
343+
out->month = PyInt_AsLong(PyObject_GetAttrString(obj, "month"));
344+
out->day = PyInt_AsLong(PyObject_GetAttrString(obj, "day"));
385345

386-
/* Validate that the month and day are valid for the year */
387-
if (out->month < 1 || out->month > 12) {
388-
goto invalid_date;
389-
}
390-
isleap = is_leapyear(out->year);
391-
if (out->day < 1 ||
392-
out->day > days_per_month_table[isleap][out->month - 1]) {
393-
goto invalid_date;
394-
}
346+
// TODO(anyone): If we can get PyDateTime_IMPORT to work, we could use
347+
// PyDateTime_Check here, and less verbose attribute lookups.
395348

396349
/* Check for time attributes (if not there, return success as a date) */
397350
if (!PyObject_HasAttrString(obj, "hour") ||
@@ -401,61 +354,13 @@ int convert_pydatetime_to_datetimestruct(PyObject *obj,
401354
return 0;
402355
}
403356

404-
/* Get the hour */
405-
tmp = PyObject_GetAttrString(obj, "hour");
406-
if (tmp == NULL) {
407-
return -1;
408-
}
409-
out->hour = PyInt_AsLong(tmp);
410-
if (out->hour == -1 && PyErr_Occurred()) {
411-
Py_DECREF(tmp);
412-
return -1;
413-
}
414-
Py_DECREF(tmp);
415-
416-
/* Get the minute */
417-
tmp = PyObject_GetAttrString(obj, "minute");
418-
if (tmp == NULL) {
419-
return -1;
420-
}
421-
out->min = PyInt_AsLong(tmp);
422-
if (out->min == -1 && PyErr_Occurred()) {
423-
Py_DECREF(tmp);
424-
return -1;
425-
}
426-
Py_DECREF(tmp);
427-
428-
/* Get the second */
429-
tmp = PyObject_GetAttrString(obj, "second");
430-
if (tmp == NULL) {
431-
return -1;
432-
}
433-
out->sec = PyInt_AsLong(tmp);
434-
if (out->sec == -1 && PyErr_Occurred()) {
435-
Py_DECREF(tmp);
436-
return -1;
437-
}
438-
Py_DECREF(tmp);
357+
out->hour = PyInt_AsLong(PyObject_GetAttrString(obj, "hour"));
358+
out->min = PyInt_AsLong(PyObject_GetAttrString(obj, "minute"));
359+
out->sec = PyInt_AsLong(PyObject_GetAttrString(obj, "second"));
360+
out->us = PyInt_AsLong(PyObject_GetAttrString(obj, "microsecond"));
439361

440-
/* Get the microsecond */
441-
tmp = PyObject_GetAttrString(obj, "microsecond");
442-
if (tmp == NULL) {
443-
return -1;
444-
}
445-
out->us = PyInt_AsLong(tmp);
446-
if (out->us == -1 && PyErr_Occurred()) {
447-
Py_DECREF(tmp);
448-
return -1;
449-
}
450-
Py_DECREF(tmp);
451-
452-
if (out->hour < 0 || out->hour >= 24 || out->min < 0 || out->min >= 60 ||
453-
out->sec < 0 || out->sec >= 60 || out->us < 0 || out->us >= 1000000) {
454-
goto invalid_time;
455-
}
456-
457-
/* Apply the time zone offset if it exists */
458-
if (PyObject_HasAttrString(obj, "tzinfo")) {
362+
/* Apply the time zone offset if datetime obj is tz-aware */
363+
if (PyObject_HasAttrString((PyObject*)obj, "tzinfo")) {
459364
tmp = PyObject_GetAttrString(obj, "tzinfo");
460365
if (tmp == NULL) {
461366
return -1;
@@ -497,50 +402,15 @@ int convert_pydatetime_to_datetimestruct(PyObject *obj,
497402
}
498403

499404
return 0;
500-
501-
invalid_date:
502-
PyErr_Format(PyExc_ValueError,
503-
"Invalid date (%d,%d,%d) when converting to NumPy datetime",
504-
(int)out->year, (int)out->month, (int)out->day);
505-
return -1;
506-
507-
invalid_time:
508-
PyErr_Format(PyExc_ValueError,
509-
"Invalid time (%d,%d,%d,%d) when converting "
510-
"to NumPy datetime",
511-
(int)out->hour, (int)out->min, (int)out->sec, (int)out->us);
512-
return -1;
513-
}
514-
515-
npy_datetime npy_datetimestruct_to_datetime(NPY_DATETIMEUNIT fr,
516-
npy_datetimestruct *d) {
517-
npy_datetime result = NPY_DATETIME_NAT;
518-
519-
convert_datetimestruct_to_datetime(fr, d, &result);
520-
return result;
521-
}
522-
523-
void pandas_datetime_to_datetimestruct(npy_datetime val, NPY_DATETIMEUNIT fr,
524-
npy_datetimestruct *result) {
525-
convert_datetime_to_datetimestruct(fr, val, result);
526-
}
527-
528-
void pandas_timedelta_to_timedeltastruct(npy_timedelta val,
529-
NPY_DATETIMEUNIT fr,
530-
pandas_timedeltastruct *result) {
531-
convert_timedelta_to_timedeltastruct(fr, val, result);
532405
}
533406

534407

535408
/*
536409
* Converts a datetime from a datetimestruct to a datetime based
537410
* on a metadata unit. The date is assumed to be valid.
538-
*
539-
* Returns 0 on success, -1 on failure.
540411
*/
541-
int convert_datetimestruct_to_datetime(NPY_DATETIMEUNIT base,
542-
const npy_datetimestruct *dts,
543-
npy_datetime *out) {
412+
npy_datetime npy_datetimestruct_to_datetime(NPY_DATETIMEUNIT base,
413+
const npy_datetimestruct *dts) {
544414
npy_datetime ret;
545415

546416
if (base == NPY_FR_Y) {
@@ -632,17 +502,14 @@ int convert_datetimestruct_to_datetime(NPY_DATETIMEUNIT base,
632502
return -1;
633503
}
634504
}
635-
636-
*out = ret;
637-
638-
return 0;
505+
return ret;
639506
}
640507

641508
/*
642509
* Converts a datetime based on the given metadata into a datetimestruct
643510
*/
644-
int convert_datetime_to_datetimestruct(NPY_DATETIMEUNIT base,
645-
npy_datetime dt,
511+
void pandas_datetime_to_datetimestruct(npy_datetime dt,
512+
NPY_DATETIMEUNIT base,
646513
npy_datetimestruct *out) {
647514
npy_int64 perday;
648515

@@ -850,10 +717,7 @@ int convert_datetime_to_datetimestruct(NPY_DATETIMEUNIT base,
850717
PyErr_SetString(PyExc_RuntimeError,
851718
"NumPy datetime metadata is corrupted with invalid "
852719
"base unit");
853-
return -1;
854720
}
855-
856-
return 0;
857721
}
858722

859723
/*
@@ -862,8 +726,8 @@ int convert_datetime_to_datetimestruct(NPY_DATETIMEUNIT base,
862726
*
863727
* Returns 0 on success, -1 on failure.
864728
*/
865-
int convert_timedelta_to_timedeltastruct(NPY_DATETIMEUNIT base,
866-
npy_timedelta td,
729+
void pandas_timedelta_to_timedeltastruct(npy_timedelta td,
730+
NPY_DATETIMEUNIT base,
867731
pandas_timedeltastruct *out) {
868732
npy_int64 frac;
869733
npy_int64 sfrac;
@@ -953,8 +817,5 @@ int convert_timedelta_to_timedeltastruct(NPY_DATETIMEUNIT base,
953817
PyErr_SetString(PyExc_RuntimeError,
954818
"NumPy timedelta metadata is corrupted with "
955819
"invalid base unit");
956-
return -1;
957820
}
958-
959-
return 0;
960821
}

pandas/_libs/src/datetime/np_datetime.h

+4-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ This file is derived from NumPy 1.7. See NUMPY_LICENSE.txt
1818
#define PANDAS__LIBS_SRC_DATETIME_NP_DATETIME_H_
1919

2020
#include <numpy/ndarraytypes.h>
21+
#include <datetime.h>
2122

2223
typedef struct {
2324
npy_int64 days;
@@ -30,11 +31,11 @@ extern const npy_datetimestruct _NS_MAX_DTS;
3031
// stuff pandas needs
3132
// ----------------------------------------------------------------------------
3233

33-
int convert_pydatetime_to_datetimestruct(PyObject *obj,
34+
int convert_pydatetime_to_datetimestruct(PyDateTime_Date *obj,
3435
npy_datetimestruct *out);
3536

36-
npy_datetime npy_datetimestruct_to_datetime(NPY_DATETIMEUNIT fr,
37-
npy_datetimestruct *d);
37+
npy_datetime npy_datetimestruct_to_datetime(NPY_DATETIMEUNIT base,
38+
const npy_datetimestruct *dts);
3839

3940
void pandas_datetime_to_datetimestruct(npy_datetime val, NPY_DATETIMEUNIT fr,
4041
npy_datetimestruct *result);
@@ -74,9 +75,4 @@ void
7475
add_minutes_to_datetimestruct(npy_datetimestruct *dts, int minutes);
7576

7677

77-
int
78-
convert_datetime_to_datetimestruct(NPY_DATETIMEUNIT base,
79-
npy_datetime dt,
80-
npy_datetimestruct *out);
81-
8278
#endif // PANDAS__LIBS_SRC_DATETIME_NP_DATETIME_H_

pandas/_libs/src/ujson/python/objToJSON.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -481,16 +481,17 @@ static void *NpyDateTimeScalarToJSON(JSOBJ _obj, JSONTypeContext *tc,
481481
npy_datetimestruct dts;
482482
PyDatetimeScalarObject *obj = (PyDatetimeScalarObject *)_obj;
483483
PRINTMARK();
484+
// TODO(anyone): Does not appear to be reached in tests.
484485

485-
pandas_datetime_to_datetimestruct(
486-
obj->obval, (NPY_DATETIMEUNIT)obj->obmeta.base, &dts);
486+
pandas_datetime_to_datetimestruct(obj->obval,
487+
(NPY_DATETIMEUNIT)obj->obmeta.base, &dts);
487488
return PandasDateTimeStructToJSON(&dts, tc, outValue, _outLen);
488489
}
489490

490491
static void *PyDateTimeToJSON(JSOBJ _obj, JSONTypeContext *tc, void *outValue,
491492
size_t *_outLen) {
492493
npy_datetimestruct dts;
493-
PyObject *obj = (PyObject *)_obj;
494+
PyDateTime_Date *obj = (PyDateTime_Date *)_obj;
494495

495496
PRINTMARK();
496497

pandas/_libs/tslibs/np_datetime.pyx

+4-2
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ cdef inline void td64_to_tdstruct(int64_t td64,
147147

148148
cdef inline int64_t pydatetime_to_dt64(datetime val,
149149
npy_datetimestruct *dts):
150+
"""
151+
Note we are assuming that the datetime object is timezone-naive.
152+
"""
150153
dts.year = PyDateTime_GET_YEAR(val)
151154
dts.month = PyDateTime_GET_MONTH(val)
152155
dts.day = PyDateTime_GET_DAY(val)
@@ -158,8 +161,7 @@ cdef inline int64_t pydatetime_to_dt64(datetime val,
158161
return dtstruct_to_dt64(dts)
159162

160163

161-
cdef inline int64_t pydate_to_dt64(date val,
162-
npy_datetimestruct *dts):
164+
cdef inline int64_t pydate_to_dt64(date val, npy_datetimestruct *dts):
163165
dts.year = PyDateTime_GET_YEAR(val)
164166
dts.month = PyDateTime_GET_MONTH(val)
165167
dts.day = PyDateTime_GET_DAY(val)

0 commit comments

Comments
 (0)