Converted from python. See https://github.com/apache/arrow/pull/7604 for details.
| 369 | // Converted from python. See https://github.com/apache/arrow/pull/7604 |
| 370 | // for details. |
| 371 | Result<PyObject*> StringToTzinfo(const std::string& tz) { |
| 372 | std::string_view sign_str, hour_str, minute_str; |
| 373 | OwnedRef pytz; |
| 374 | OwnedRef zoneinfo; |
| 375 | OwnedRef datetime; |
| 376 | |
| 377 | if (internal::ImportModule("pytz", &pytz).ok()) { |
| 378 | if (MatchFixedOffset(tz, &sign_str, &hour_str, &minute_str)) { |
| 379 | int sign = -1; |
| 380 | if (sign_str == "+") { |
| 381 | sign = 1; |
| 382 | } |
| 383 | OwnedRef fixed_offset; |
| 384 | RETURN_NOT_OK(internal::ImportFromModule(pytz.obj(), "FixedOffset", &fixed_offset)); |
| 385 | uint32_t minutes, hours; |
| 386 | if (!::arrow::internal::ParseUnsigned(hour_str.data(), hour_str.size(), &hours) || |
| 387 | !::arrow::internal::ParseUnsigned(minute_str.data(), minute_str.size(), |
| 388 | &minutes)) { |
| 389 | return Status::Invalid("Invalid timezone: ", tz); |
| 390 | } |
| 391 | OwnedRef total_minutes(PyLong_FromLong( |
| 392 | sign * ((static_cast<int>(hours) * 60) + static_cast<int>(minutes)))); |
| 393 | RETURN_IF_PYERROR(); |
| 394 | auto tzinfo = |
| 395 | PyObject_CallFunctionObjArgs(fixed_offset.obj(), total_minutes.obj(), NULL); |
| 396 | RETURN_IF_PYERROR(); |
| 397 | return tzinfo; |
| 398 | } |
| 399 | |
| 400 | OwnedRef timezone; |
| 401 | RETURN_NOT_OK(internal::ImportFromModule(pytz.obj(), "timezone", &timezone)); |
| 402 | OwnedRef py_tz_string( |
| 403 | PyUnicode_FromStringAndSize(tz.c_str(), static_cast<Py_ssize_t>(tz.size()))); |
| 404 | auto tzinfo = PyObject_CallFunctionObjArgs(timezone.obj(), py_tz_string.obj(), NULL); |
| 405 | RETURN_IF_PYERROR(); |
| 406 | return tzinfo; |
| 407 | } |
| 408 | |
| 409 | // catch fixed offset if pytz is not present |
| 410 | if (MatchFixedOffset(tz, &sign_str, &hour_str, &minute_str)) { |
| 411 | RETURN_NOT_OK(internal::ImportModule("datetime", &datetime)); |
| 412 | int sign = -1; |
| 413 | if (sign_str == "+") { |
| 414 | sign = 1; |
| 415 | } |
| 416 | |
| 417 | // import timezone and timedelta module to create a tzinfo object |
| 418 | OwnedRef class_timezone; |
| 419 | OwnedRef class_timedelta; |
| 420 | RETURN_NOT_OK( |
| 421 | internal::ImportFromModule(datetime.obj(), "timezone", &class_timezone)); |
| 422 | RETURN_NOT_OK( |
| 423 | internal::ImportFromModule(datetime.obj(), "timedelta", &class_timedelta)); |
| 424 | |
| 425 | // check input |
| 426 | uint32_t minutes, hours; |
| 427 | if (!::arrow::internal::ParseUnsigned(hour_str.data(), hour_str.size(), &hours) || |
| 428 | !::arrow::internal::ParseUnsigned(minute_str.data(), minute_str.size(), |
no test coverage detected