| 465 | } |
| 466 | |
| 467 | Result<std::string> TzinfoToString(PyObject* tzinfo) { |
| 468 | OwnedRef module_pytz; // import pytz |
| 469 | OwnedRef module_datetime; // import datetime |
| 470 | OwnedRef module_zoneinfo; // import zoneinfo |
| 471 | OwnedRef module_dateutil; // import dateutil |
| 472 | OwnedRef class_timezone; // from datetime import timezone |
| 473 | OwnedRef class_fixedoffset; // from pytz import _FixedOffset |
| 474 | OwnedRef class_basetzinfo; // from pytz import BaseTzInfo |
| 475 | OwnedRef class_zoneinfo; // from zoneinfo import ZoneInfo |
| 476 | OwnedRef class_tzfile; // from zoneinfo import tzfile |
| 477 | |
| 478 | // import necessary modules |
| 479 | RETURN_NOT_OK(internal::ImportModule("datetime", &module_datetime)); |
| 480 | // import necessary classes |
| 481 | RETURN_NOT_OK( |
| 482 | internal::ImportFromModule(module_datetime.obj(), "timezone", &class_timezone)); |
| 483 | |
| 484 | // check that it's a valid tzinfo object |
| 485 | if (!PyTZInfo_Check(tzinfo)) { |
| 486 | return Status::TypeError("Not an instance of datetime.tzinfo"); |
| 487 | } |
| 488 | |
| 489 | // if tzinfo is an instance of datetime.timezone return the |
| 490 | // HH:MM offset string representation |
| 491 | if (PyObject_IsInstance(tzinfo, class_timezone.obj())) { |
| 492 | // still recognize datetime.timezone.utc as UTC (instead of +00:00) |
| 493 | OwnedRef tzname_object(PyObject_CallMethod(tzinfo, "tzname", "O", Py_None)); |
| 494 | RETURN_IF_PYERROR(); |
| 495 | if (PyUnicode_Check(tzname_object.obj())) { |
| 496 | std::string result; |
| 497 | RETURN_NOT_OK(internal::PyUnicode_AsStdString(tzname_object.obj(), &result)); |
| 498 | if (result == "UTC") { |
| 499 | return result; |
| 500 | } |
| 501 | } |
| 502 | return PyTZInfo_utcoffset_hhmm(tzinfo); |
| 503 | } |
| 504 | |
| 505 | // Try to import pytz if it is available |
| 506 | if (internal::ImportModule("pytz", &module_pytz).ok()) { |
| 507 | RETURN_NOT_OK(internal::ImportFromModule(module_pytz.obj(), "_FixedOffset", |
| 508 | &class_fixedoffset)); |
| 509 | RETURN_NOT_OK( |
| 510 | internal::ImportFromModule(module_pytz.obj(), "BaseTzInfo", &class_basetzinfo)); |
| 511 | } |
| 512 | |
| 513 | // if tzinfo is an instance of pytz._FixedOffset return the |
| 514 | // HH:MM offset string representation |
| 515 | if (module_pytz.obj() != nullptr && |
| 516 | PyObject_IsInstance(tzinfo, class_fixedoffset.obj())) { |
| 517 | OwnedRef tzname_object(PyObject_CallMethod(tzinfo, "tzname", "O", Py_None)); |
| 518 | RETURN_IF_PYERROR(); |
| 519 | return PyTZInfo_utcoffset_hhmm(tzinfo); |
| 520 | } |
| 521 | |
| 522 | // if pytz is installed and tzinfo is and instance of pytz.BaseTzInfo |
| 523 | if (module_pytz.obj() != nullptr && |
| 524 | PyObject_IsInstance(tzinfo, class_basetzinfo.obj())) { |
no test coverage detected