{"id":553,"library":"pendulum","title":"Pendulum","description":"Pendulum is a Python package designed to simplify datetime manipulation, offering a more intuitive API and robust timezone handling than Python's native `datetime` module. It provides drop-in replacements for standard datetime classes, making integration seamless. Currently at version 3.2.0, Pendulum maintains an active release cadence, often aligning with new Python versions or significant feature enhancements.","status":"active","version":"3.2.0","language":"python","source_language":"en","source_url":"https://github.com/sdispater/pendulum","tags":["datetime","timezone","time","date","utility"],"install":[{"cmd":"pip install pendulum","lang":"bash","label":"Install core library"},{"cmd":"pip install \"pendulum[test]\"","lang":"bash","label":"Install with testing helpers"}],"dependencies":[{"reason":"Required for optional testing helpers (pendulum[test] extra).","package":"time-machine","optional":true}],"imports":[{"note":"Pendulum's `datetime` (accessed via `pendulum.datetime`) is the primary class and a drop-in replacement for the native `datetime.datetime`, offering enhanced features like automatic timezone awareness.","wrong":"from datetime import datetime\ndt = datetime(2026, 3, 28, 10, 0, 0)","symbol":"datetime","correct":"import pendulum\ndt = pendulum.datetime(2026, 3, 28, 10, 0, 0, tz='UTC')"},{"note":"Use `pendulum.now()` to get the current datetime, optionally specifying a timezone.","symbol":"now","correct":"import pendulum\ncurrent_time = pendulum.now('Europe/Paris')"},{"note":"Automatically parses various date and time string formats.","symbol":"parse","correct":"import pendulum\ndt = pendulum.parse('2026-03-28T10:00:00+02:00')"}],"quickstart":{"code":"import pendulum\n\n# Get current time in a specific timezone\nnow_paris = pendulum.now('Europe/Paris')\nprint(f\"Current time in Paris: {now_paris}\")\n\n# Create a specific datetime\nbirthday = pendulum.datetime(1990, 7, 15, tz='America/New_York')\nprint(f\"My birthday: {birthday}\")\n\n# Add time\nnext_week = now_paris.add(weeks=1, days=2)\nprint(f\"Next week and two days: {next_week}\")\n\n# Calculate difference in a human-readable format\ndiff = next_week.diff_for_humans(now_paris)\nprint(f\"Difference: {diff}\")\n\n# Convert to another timezone\nnow_london = now_paris.in_timezone('Europe/London')\nprint(f\"Current time in London: {now_london}\")","lang":"python","description":"This quickstart demonstrates how to create timezone-aware `DateTime` objects, perform common operations like adding time, calculating human-readable differences, and converting between timezones."},"warnings":[{"fix":"Upgrade your Python environment to 3.9 or higher if you intend to use Pendulum 3.x.","message":"Pendulum 3.0.0 dropped support for Python 2.7, 3.5, 3.6, and 3.7. Version 3.1.0 further dropped support for Python 3.8. The library now requires Python >= 3.9.","severity":"breaking","affected_versions":"3.0.0, 3.1.0"},{"fix":"Update all instances of `Period` to `Interval` and `pendulum.period()` to `pendulum.interval()` in your code.","message":"The `Period` class and its associated `period` helper were renamed to `Interval` and `interval` respectively in Pendulum 3.0.0.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"If your code relies on the exact string format, explicitly use `dt.isoformat()` for ISO 8601, or `dt.format('...')` with custom tokens to achieve the desired output.","message":"The default string representation (`str(dt)`) of `DateTime` instances changed in 3.0.0 to align with Python's standard library `datetime` output (e.g., from `T` separator to space).","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Migrate to the new testing helpers and ensure the `[test]` extra is installed if you use time-traveling features.","message":"Existing testing helpers like `pendulum.test()` and `pendulum.set_test_now()` were removed in 3.0.0. New testing helpers, which rely on the `time-machine` library, were introduced and require installing Pendulum with the `[test]` extra (e.g., `pip install \"pendulum[test]\"`).","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Always pass the timezone using the `tz=` keyword argument: `pendulum.datetime(2026, 3, 28, tz='UTC')`.","message":"The `tz` argument for `pendulum.datetime()` is keyword-only since Pendulum 2.x, differing from Python's native `datetime` constructor.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"This change primarily affects internals and improves compatibility. Ensure your Python environment meets the `>=3.9` requirement for optimal timezone handling.","message":"The `Timezone` class in Pendulum 3.0.0 now relies on Python's native `zoneinfo.ZoneInfo` class (available from Python 3.9+). While not a direct breaking change, users on older Python versions (not applicable for Pendulum 3.x's requirements) previously relied on Pendulum's internal timezone handling which has been streamlined.","severity":"deprecated","affected_versions":">=3.0.0"},{"fix":"No direct action required unless you were explicitly relying on `pytz` through Pendulum, in which case you should switch to `zoneinfo` or Pendulum's native timezone utilities.","message":"The `pytz` dependency was removed in Pendulum 3.2.0, streamlining timezone management to rely on standard library features (`zoneinfo`).","severity":"deprecated","affected_versions":">=3.2.0"}],"env_vars":null,"last_verified":"2026-05-12T15:03:21.467Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"Ensure Pendulum is installed in your active Python environment using pip: `pip install pendulum`.","cause":"The 'pendulum' library is not installed in the Python environment where the code is being executed, or the environment is not correctly activated.","error":"ModuleNotFoundError: No module named 'pendulum'"},{"fix":"Convert the `pendulum.DateTime` object to a standard `datetime.datetime` object before passing it to the external library: `my_pendulum_dt.in_timezone('UTC').replace(tzinfo=None) # for naive datetime` or `my_pendulum_dt.in_timezone('UTC')._datetime # for timezone-aware datetime.datetime` (though direct attribute access is generally discouraged, `to_datetime_string()` or `isoformat()` can also be used depending on the need to represent it as a string).","cause":"This error often occurs when a `pendulum.DateTime` object is passed to a library (like Pandas) that expects a native Python `datetime` object or has specific attribute expectations not present in `pendulum.DateTime` directly.","error":"AttributeError: 'DateTime' object has no attribute 'nanosecond'"},{"fix":"For non-standard or complicated strings, use `pendulum.from_format()` with an explicit format string, or pass `exact=False` (formerly `strict=False`) to `pendulum.parse()` to allow it to fall back on `dateutil` parsing: `pendulum.parse('2023-01-01 10:30:00', exact=False)` or `pendulum.from_format('2023/01/01', 'YYYY/MM/DD')`.","cause":"The `pendulum.parse()` method was unable to interpret the provided string into a valid date and time, often because the string format is not natively supported or is ambiguous.","error":"pendulum.parsing.exceptions.ParserError: Unable to parse string [...]"},{"fix":"Remove the `dst_rule` argument from your `pendulum.datetime()` calls. Pendulum 3.x handles DST transitions implicitly and correctly without this explicit parameter. If specific DST behavior is needed, leverage `in_timezone()` or ensure your timezone strings are correctly specified.","cause":"The `dst_rule` keyword argument was removed in Pendulum 3.0.0, which introduced breaking changes to simplify the API and improve standard library compatibility.","error":"TypeError: datetime() got an unexpected keyword argument 'dst_rule'"},{"fix":"Use the `add()` method with keyword arguments for time units or direct addition with `datetime.timedelta` objects: `dt.add(hours=1, minutes=30)` or `dt + timedelta(hours=1, minutes=30)`.","cause":"The `add_timedelta` method was deprecated and removed in Pendulum 2.x and later, replaced by the more intuitive `add()` and `subtract()` methods, or direct arithmetic.","error":"AttributeError: 'DateTime' object has no attribute 'add_timedelta'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":3.4,"disk_size":"24.2M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.4,"disk_size":"24.0M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.4,"disk_size":"24M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":3.4,"disk_size":"24M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":3.9,"disk_size":"26.3M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":3.9,"disk_size":"26.2M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":3.9,"disk_size":"26M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":3.9,"disk_size":"26M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":3.8,"disk_size":"18.2M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":3.8,"disk_size":"18.0M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.21,"mem_mb":3.8,"disk_size":"18M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":3.8,"disk_size":"18M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":3.9,"disk_size":"17.8M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":3.9,"disk_size":"17.6M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.16,"mem_mb":3.9,"disk_size":"18M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.16,"mem_mb":3.9,"disk_size":"18M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.4,"disk_size":"23.7M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.1,"mem_mb":3.4,"disk_size":"23.6M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"test","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":3.4,"disk_size":"24M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":3.4,"disk_size":"24M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}