* Converts a datetime from a datetimestruct to a datetime based * on some metadata. The date is assumed to be valid. * * TODO: If meta->num is really big, there could be overflow * * Returns 0 on success, -1 on failure. */
| 278 | * Returns 0 on success, -1 on failure. |
| 279 | */ |
| 280 | NPY_NO_EXPORT int |
| 281 | convert_datetimestruct_to_datetime(PyArray_DatetimeMetaData *meta, |
| 282 | const npy_datetimestruct *dts, |
| 283 | npy_datetime *out) |
| 284 | { |
| 285 | npy_datetime ret; |
| 286 | NPY_DATETIMEUNIT base = meta->base; |
| 287 | |
| 288 | /* If the datetimestruct is NaT, return NaT */ |
| 289 | if (dts->year == NPY_DATETIME_NAT) { |
| 290 | *out = NPY_DATETIME_NAT; |
| 291 | return 0; |
| 292 | } |
| 293 | |
| 294 | /* Cannot instantiate a datetime with generic units */ |
| 295 | if (meta->base == NPY_FR_GENERIC) { |
| 296 | PyErr_SetString(PyExc_ValueError, |
| 297 | "Cannot create a NumPy datetime other than NaT " |
| 298 | "with generic units"); |
| 299 | return -1; |
| 300 | } |
| 301 | |
| 302 | if (base == NPY_FR_Y) { |
| 303 | /* Truncate to the year */ |
| 304 | ret = dts->year - 1970; |
| 305 | } |
| 306 | else if (base == NPY_FR_M) { |
| 307 | /* Truncate to the month */ |
| 308 | ret = 12 * (dts->year - 1970) + (dts->month - 1); |
| 309 | } |
| 310 | else { |
| 311 | /* Otherwise calculate the number of days to start */ |
| 312 | npy_int64 days = get_datetimestruct_days(dts); |
| 313 | |
| 314 | switch (base) { |
| 315 | case NPY_FR_W: |
| 316 | /* Truncate to weeks */ |
| 317 | if (days >= 0) { |
| 318 | ret = days / 7; |
| 319 | } |
| 320 | else { |
| 321 | ret = (days - 6) / 7; |
| 322 | } |
| 323 | break; |
| 324 | case NPY_FR_D: |
| 325 | ret = days; |
| 326 | break; |
| 327 | case NPY_FR_h: |
| 328 | ret = days * 24 + |
| 329 | dts->hour; |
| 330 | break; |
| 331 | case NPY_FR_m: |
| 332 | ret = (days * 24 + |
| 333 | dts->hour) * 60 + |
| 334 | dts->min; |
| 335 | break; |
| 336 | case NPY_FR_s: |
| 337 | ret = ((days * 24 + |
no test coverage detected