|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once |
|
|
|
#include <algorithm> |
|
#include <chrono> |
|
|
|
#include "arrow/python/platform.h" |
|
#include "arrow/python/visibility.h" |
|
#include "arrow/result.h" |
|
#include "arrow/status.h" |
|
#include "arrow/type.h" |
|
#include "arrow/type_fwd.h" |
|
#include "arrow/util/int_util_overflow.h" |
|
#include "arrow/util/logging.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef PYPY_VERSION |
|
# include "datetime.h" |
|
#else |
|
# define PyDateTimeAPI ::arrow::py::internal::datetime_api |
|
#endif |
|
|
|
namespace arrow { |
|
using internal::AddWithOverflow; |
|
using internal::MultiplyWithOverflow; |
|
namespace py { |
|
namespace internal { |
|
|
|
#ifndef PYPY_VERSION |
|
extern PyDateTime_CAPI* datetime_api; |
|
|
|
ARROW_PYTHON_EXPORT |
|
void InitDatetime(); |
|
#endif |
|
|
|
|
|
ARROW_PYTHON_EXPORT |
|
PyObject* NewMonthDayNanoTupleType(); |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyTime_to_us(PyObject* pytime) { |
|
return (PyDateTime_TIME_GET_HOUR(pytime) * 3600000000LL + |
|
PyDateTime_TIME_GET_MINUTE(pytime) * 60000000LL + |
|
PyDateTime_TIME_GET_SECOND(pytime) * 1000000LL + |
|
PyDateTime_TIME_GET_MICROSECOND(pytime)); |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyTime_to_s(PyObject* pytime) { return PyTime_to_us(pytime) / 1000000; } |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyTime_to_ms(PyObject* pytime) { return PyTime_to_us(pytime) / 1000; } |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyTime_to_ns(PyObject* pytime) { return PyTime_to_us(pytime) * 1000; } |
|
|
|
ARROW_PYTHON_EXPORT |
|
Status PyTime_from_int(int64_t val, const TimeUnit::type unit, PyObject** out); |
|
|
|
ARROW_PYTHON_EXPORT |
|
Status PyDate_from_int(int64_t val, const DateUnit unit, PyObject** out); |
|
|
|
|
|
ARROW_PYTHON_EXPORT |
|
Status PyDateTime_from_int(int64_t val, const TimeUnit::type unit, PyObject** out); |
|
|
|
|
|
using TimePoint = |
|
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>; |
|
|
|
ARROW_PYTHON_EXPORT |
|
int64_t PyDate_to_days(PyDateTime_Date* pydate); |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyDate_to_s(PyDateTime_Date* pydate) { |
|
return PyDate_to_days(pydate) * 86400LL; |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyDate_to_ms(PyDateTime_Date* pydate) { |
|
return PyDate_to_days(pydate) * 86400000LL; |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyDateTime_to_s(PyDateTime_DateTime* pydatetime) { |
|
return (PyDate_to_s(reinterpret_cast<PyDateTime_Date*>(pydatetime)) + |
|
PyDateTime_DATE_GET_HOUR(pydatetime) * 3600LL + |
|
PyDateTime_DATE_GET_MINUTE(pydatetime) * 60LL + |
|
PyDateTime_DATE_GET_SECOND(pydatetime)); |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyDateTime_to_ms(PyDateTime_DateTime* pydatetime) { |
|
return (PyDateTime_to_s(pydatetime) * 1000LL + |
|
PyDateTime_DATE_GET_MICROSECOND(pydatetime) / 1000); |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyDateTime_to_us(PyDateTime_DateTime* pydatetime) { |
|
return (PyDateTime_to_s(pydatetime) * 1000000LL + |
|
PyDateTime_DATE_GET_MICROSECOND(pydatetime)); |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyDateTime_to_ns(PyDateTime_DateTime* pydatetime) { |
|
return PyDateTime_to_us(pydatetime) * 1000LL; |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline TimePoint PyDateTime_to_TimePoint(PyDateTime_DateTime* pydatetime) { |
|
return TimePoint(TimePoint::duration(PyDateTime_to_ns(pydatetime))); |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t TimePoint_to_ns(TimePoint val) { return val.time_since_epoch().count(); } |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline TimePoint TimePoint_from_s(double val) { |
|
return TimePoint(TimePoint::duration(static_cast<int64_t>(1e9 * val))); |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline TimePoint TimePoint_from_ns(int64_t val) { |
|
return TimePoint(TimePoint::duration(val)); |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyDelta_to_s(PyDateTime_Delta* pytimedelta) { |
|
return (PyDateTime_DELTA_GET_DAYS(pytimedelta) * 86400LL + |
|
PyDateTime_DELTA_GET_SECONDS(pytimedelta)); |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline int64_t PyDelta_to_ms(PyDateTime_Delta* pytimedelta) { |
|
return (PyDelta_to_s(pytimedelta) * 1000LL + |
|
PyDateTime_DELTA_GET_MICROSECONDS(pytimedelta) / 1000); |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline Result<int64_t> PyDelta_to_us(PyDateTime_Delta* pytimedelta) { |
|
int64_t result = PyDelta_to_s(pytimedelta); |
|
if (MultiplyWithOverflow(result, 1000000LL, &result)) { |
|
return Status::Invalid("Timedelta too large to fit in 64-bit integer"); |
|
} |
|
if (AddWithOverflow(result, PyDateTime_DELTA_GET_MICROSECONDS(pytimedelta), &result)) { |
|
return Status::Invalid("Timedelta too large to fit in 64-bit integer"); |
|
} |
|
return result; |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
inline Result<int64_t> PyDelta_to_ns(PyDateTime_Delta* pytimedelta) { |
|
ARROW_ASSIGN_OR_RAISE(int64_t result, PyDelta_to_us(pytimedelta)); |
|
if (MultiplyWithOverflow(result, 1000LL, &result)) { |
|
return Status::Invalid("Timedelta too large to fit in 64-bit integer"); |
|
} |
|
return result; |
|
} |
|
|
|
ARROW_PYTHON_EXPORT |
|
Result<int64_t> PyDateTime_utcoffset_s(PyObject* pydatetime); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ARROW_PYTHON_EXPORT |
|
Result<PyObject*> StringToTzinfo(const std::string& tz); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ARROW_PYTHON_EXPORT |
|
Result<std::string> TzinfoToString(PyObject* pytzinfo); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ARROW_PYTHON_EXPORT |
|
PyObject* MonthDayNanoIntervalToNamedTuple( |
|
const MonthDayNanoIntervalType::MonthDayNanos& interval); |
|
|
|
|
|
|
|
ARROW_PYTHON_EXPORT |
|
Result<PyObject*> MonthDayNanoIntervalArrayToPyList( |
|
const MonthDayNanoIntervalArray& array); |
|
|
|
|
|
|
|
ARROW_PYTHON_EXPORT |
|
Result<PyObject*> MonthDayNanoIntervalScalarToPyObject( |
|
const MonthDayNanoIntervalScalar& scalar); |
|
|
|
} |
|
} |
|
} |
|
|