METADATA 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. Metadata-Version: 2.1
  2. Name: pendulum
  3. Version: 3.0.0
  4. Classifier: License :: OSI Approved :: MIT License
  5. Classifier: Programming Language :: Python :: 3
  6. Classifier: Programming Language :: Python :: 3.8
  7. Classifier: Programming Language :: Python :: 3.9
  8. Classifier: Programming Language :: Python :: 3.10
  9. Classifier: Programming Language :: Python :: 3.11
  10. Classifier: Programming Language :: Python :: 3.12
  11. Requires-Dist: python-dateutil >=2.6
  12. Requires-Dist: tzdata >=2020.1
  13. Requires-Dist: backports.zoneinfo >=0.2.1 ; python_version < '3.9'
  14. Requires-Dist: time-machine >=2.6.0 ; implementation_name != 'pypy'
  15. Requires-Dist: importlib-resources >=5.9.0 ; python_version < '3.9'
  16. License-File: LICENSE
  17. Summary: Python datetimes made easy
  18. Keywords: datetime,date,time
  19. Author-email: Sébastien Eustace <sebastien@eustace.io>>
  20. License: MIT License
  21. Requires-Python: >=3.8
  22. Description-Content-Type: text/x-rst; charset=UTF-8
  23. Project-URL: Homepage, https://pendulum.eustace.io
  24. Project-URL: Documentation, https://pendulum.eustace.io/docs
  25. Project-URL: Repository, https://github.com/sdispater/pendulum
  26. Pendulum
  27. ########
  28. .. image:: https://img.shields.io/pypi/v/pendulum.svg
  29. :target: https://pypi.python.org/pypi/pendulum
  30. .. image:: https://img.shields.io/pypi/l/pendulum.svg
  31. :target: https://pypi.python.org/pypi/pendulum
  32. .. image:: https://github.com/sdispater/pendulum/actions/workflows/tests.yml/badge.svg
  33. :alt: Pendulum Build status
  34. :target: https://github.com/sdispater/pendulum/actions
  35. Python datetimes made easy.
  36. Supports Python **3.8 and newer**.
  37. .. code-block:: python
  38. >>> import pendulum
  39. >>> now_in_paris = pendulum.now('Europe/Paris')
  40. >>> now_in_paris
  41. '2016-07-04T00:49:58.502116+02:00'
  42. # Seamless timezone switching
  43. >>> now_in_paris.in_timezone('UTC')
  44. '2016-07-03T22:49:58.502116+00:00'
  45. >>> tomorrow = pendulum.now().add(days=1)
  46. >>> last_week = pendulum.now().subtract(weeks=1)
  47. >>> past = pendulum.now().subtract(minutes=2)
  48. >>> past.diff_for_humans()
  49. '2 minutes ago'
  50. >>> delta = past - last_week
  51. >>> delta.hours
  52. 23
  53. >>> delta.in_words(locale='en')
  54. '6 days 23 hours 58 minutes'
  55. # Proper handling of datetime normalization
  56. >>> pendulum.datetime(2013, 3, 31, 2, 30, tz='Europe/Paris')
  57. '2013-03-31T03:30:00+02:00' # 2:30 does not exist (Skipped time)
  58. # Proper handling of dst transitions
  59. >>> just_before = pendulum.datetime(2013, 3, 31, 1, 59, 59, 999999, tz='Europe/Paris')
  60. '2013-03-31T01:59:59.999999+01:00'
  61. >>> just_before.add(microseconds=1)
  62. '2013-03-31T03:00:00+02:00'
  63. Resources
  64. =========
  65. * `Official Website <https://pendulum.eustace.io>`_
  66. * `Documentation <https://pendulum.eustace.io/docs/>`_
  67. * `Issue Tracker <https://github.com/sdispater/pendulum/issues>`_
  68. Why Pendulum?
  69. =============
  70. Native ``datetime`` instances are enough for basic cases but when you face more complex use-cases
  71. they often show limitations and are not so intuitive to work with.
  72. ``Pendulum`` provides a cleaner and more easy to use API while still relying on the standard library.
  73. So it's still ``datetime`` but better.
  74. Unlike other datetime libraries for Python, Pendulum is a drop-in replacement
  75. for the standard ``datetime`` class (it inherits from it), so, basically, you can replace all your ``datetime``
  76. instances by ``DateTime`` instances in your code (exceptions exist for libraries that check
  77. the type of the objects by using the ``type`` function like ``sqlite3`` or ``PyMySQL`` for instance).
  78. It also removes the notion of naive datetimes: each ``Pendulum`` instance is timezone-aware
  79. and by default in ``UTC`` for ease of use.
  80. Pendulum also improves the standard ``timedelta`` class by providing more intuitive methods and properties.
  81. Limitations
  82. ===========
  83. Even though the ``DateTime`` class is a subclass of ``datetime`` there are some rare cases where
  84. it can't replace the native class directly. Here is a list (non-exhaustive) of the reported cases with
  85. a possible solution, if any:
  86. * ``sqlite3`` will use the ``type()`` function to determine the type of the object by default. To work around it you can register a new adapter:
  87. .. code-block:: python
  88. from pendulum import DateTime
  89. from sqlite3 import register_adapter
  90. register_adapter(DateTime, lambda val: val.isoformat(' '))
  91. * ``mysqlclient`` (former ``MySQLdb``) and ``PyMySQL`` will use the ``type()`` function to determine the type of the object by default. To work around it you can register a new adapter:
  92. .. code-block:: python
  93. import MySQLdb.converters
  94. import pymysql.converters
  95. from pendulum import DateTime
  96. MySQLdb.converters.conversions[DateTime] = MySQLdb.converters.DateTime2literal
  97. pymysql.converters.conversions[DateTime] = pymysql.converters.escape_datetime
  98. * ``django`` will use the ``isoformat()`` method to store datetimes in the database. However since ``pendulum`` is always timezone aware the offset information will always be returned by ``isoformat()`` raising an error, at least for MySQL databases. To work around it you can either create your own ``DateTimeField`` or use the previous workaround for ``MySQLdb``:
  99. .. code-block:: python
  100. from django.db.models import DateTimeField as BaseDateTimeField
  101. from pendulum import DateTime
  102. class DateTimeField(BaseDateTimeField):
  103. def value_to_string(self, obj):
  104. val = self.value_from_object(obj)
  105. if isinstance(value, DateTime):
  106. return value.to_datetime_string()
  107. return '' if val is None else val.isoformat()
  108. Contributing
  109. ============
  110. Contributions are welcome, especially with localization.
  111. Getting started
  112. ---------------
  113. To work on the Pendulum codebase, you'll want to clone the project locally
  114. and install the required dependencies via `poetry <https://poetry.eustace.io>`_.
  115. .. code-block:: bash
  116. $ git clone git@github.com:sdispater/pendulum.git
  117. $ poetry install
  118. Localization
  119. ------------
  120. If you want to help with localization, there are two different cases: the locale already exists
  121. or not.
  122. If the locale does not exist you will need to create it by using the ``clock`` utility:
  123. .. code-block:: bash
  124. ./clock locale create <your-locale>
  125. It will generate a directory in ``pendulum/locales`` named after your locale, with the following
  126. structure:
  127. .. code-block:: text
  128. <your-locale>/
  129. - custom.py
  130. - locale.py
  131. The ``locale.py`` file must not be modified. It contains the translations provided by
  132. the CLDR database.
  133. The ``custom.py`` file is the one you want to modify. It contains the data needed
  134. by Pendulum that are not provided by the CLDR database. You can take the `en <https://github.com/sdispater/pendulum/tree/master/pendulum/locales/en/custom.py>`_
  135. data as a reference to see which data is needed.
  136. You should also add tests for the created or modified locale.