Skip to content

Commit e8b3c6a

Browse files
committed
progress
1 parent 6c8d649 commit e8b3c6a

File tree

4 files changed

+53
-20
lines changed

4 files changed

+53
-20
lines changed

src/methods.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,15 @@ PyObject *
205205
is_objectable_dt64(PyObject *Py_UNUSED(m), PyObject *a) {
206206
AK_CHECK_NUMPY_ARRAY(a);
207207
PyArrayObject* array = (PyArrayObject*)a;
208-
AK_is_objectable_dt64(array);
209-
Py_RETURN_FALSE;
208+
switch (AK_is_objectable_dt64(array)) {
209+
case -1:
210+
return NULL;
211+
case 0:
212+
Py_RETURN_FALSE;
213+
case 1:
214+
Py_RETURN_TRUE;
215+
}
216+
return NULL;
210217
}
211218

212219

src/utilities.h

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,8 @@ AK_dt_unit_from_array(PyArrayObject* a) {
232232
return dma->base;
233233
}
234234

235-
// Givne a dt64 array, determine if it can be cast to a object without data loss.
236-
static inline bool
235+
// Given a dt64 array, determine if it can be cast to a object without data loss. Returns -1 on error
236+
static inline int
237237
AK_is_objectable_dt64(PyArrayObject* a)
238238
{
239239
NPY_DATETIMEUNIT unit = AK_dt_unit_from_array(a);
@@ -258,24 +258,42 @@ AK_is_objectable_dt64(PyArrayObject* a)
258258
return false;
259259
}
260260

261-
PyArray_Descr* dt_year = PyArray_DescrFromType(NPY_DATETIME);
262-
if (dt_year == NULL) {
263-
return NULL;
261+
PyObject* dt_year_str = PyUnicode_FromString("datetime64[Y]");
262+
if (!dt_year_str) return -1;
263+
264+
PyArray_Descr* dt_year = NULL;
265+
if (!PyArray_DescrConverter2(dt_year_str, &dt_year)) {
266+
Py_DECREF(dt_year_str);
267+
return -1;
264268
}
265-
// TODO: not sure how to do this
266-
// dt_year->metadata = Py_BuildValue("{s:i}", "unit", NPY_FR_Y);
269+
Py_DECREF(dt_year_str);
270+
AK_DEBUG_MSG_OBJ("got descr", (PyObject*)dt_year);
271+
267272
PyObject* a_year = PyArray_CastToType(a, dt_year, 0);
268-
Py_DECREF(dt_year);
273+
if (!a_year) {
274+
Py_DECREF(dt_year);
275+
return -1;
276+
}
277+
AK_DEBUG_MSG_OBJ("a_year", a_year);
278+
279+
npy_int64* data = (npy_int64*)PyArray_DATA((PyArrayObject*)a_year);
280+
npy_intp size = PyArray_SIZE((PyArrayObject*)a_year);
281+
282+
for (npy_intp i = 0; i < size; ++i) {
283+
npy_int64 v = data[i];
284+
// if (v == NPY_DATETIME_NAT) {
285+
// continue;
286+
// }
287+
// offset: 1-1970, 9999-1970
288+
AK_DEBUG_MSG_OBJ("int values", PyLong_FromSsize_t(v));
289+
if (v < -1969 || v > 8029) {
290+
Py_DECREF(a_year);
291+
return 0;
292+
}
293+
}
269294

270295
Py_DECREF(a_year);
271-
return false;
272-
273-
// years = array[~np.isnat(array)].astype(DT64_YEAR).astype(DTYPE_INT_DEFAULT) + 1970
274-
// if np.any(years < datetime.MINYEAR):
275-
// return False
276-
// if np.any(years > datetime.MAXYEAR):
277-
// return False
278-
// return True
296+
return 1;
279297

280298
}
281299

test/test_objectable.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,16 @@ class TestUnit(unittest.TestCase):
88

99
def test_is_objectable_dt64_a(self) -> None:
1010
a1 = np.array(['2022-01-04', '1954-04-12'], dtype=np.datetime64)
11+
self.assertTrue(is_objectable_dt64(a1))
12+
13+
14+
def test_is_objectable_dt64_b(self) -> None:
15+
# years are nevery objectable
16+
a1 = np.array(['2022', '2023'], dtype=np.datetime64)
1117
self.assertFalse(is_objectable_dt64(a1))
1218

1319

20+
def test_is_objectable_dt64_c(self) -> None:
21+
a1 = np.array(['-120', '2023'], dtype=np.datetime64)
22+
self.assertFalse(is_objectable_dt64(a1))
1423

test/test_util.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from arraykit import immutable_filter
1818
from arraykit import array_deepcopy
1919
from arraykit import isna_element
20+
from arraykit import is_objectable_dt64
2021
from arraykit import dtype_from_element
2122
from arraykit import count_iteration
2223
from arraykit import first_true_1d
@@ -953,7 +954,5 @@ def test_slice_to_ascending_slice_i(self) -> None:
953954
)
954955

955956

956-
957-
958957
if __name__ == '__main__':
959958
unittest.main()

0 commit comments

Comments
 (0)