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