{ "info": { "author": "Aymeric Augustin", "author_email": "aymeric.augustin@m4x.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "datedelta\n#########\n\n``datedelta.datedelta`` is ``datetime.timedelta`` for date arithmetic.\n\nIt can add years, months, weeks, or days to dates while accounting for\noddities of the Gregorian calendar. It can also subtract years, months, weeks,\nor days from dates.\n\nTypically, it's useful to compute yearly, monthly, or weekly subscriptions\nperiods.\n\nBehavior\n========\n\nThere are two date arithmetic traps in the Gregorian calendar:\n\n1. Leap years. Problems arise when adding years to a February 29th gives a\n result in a non-leap year.\n\n2. Variable number of days in months. Problems arise when adding months to a\n 29th, 30th or 31st gives a result in a month where that day doesn't exist.\n\nIn both cases, the result must be changed to the first day of the next month.\n\nThis method gives consistent results provided periods are represented by\n(start date inclusive, end date exclusive) \u2014 that's [start date, end date) if\nyou prefer the mathematical notation. This representation of periods is akin\nto 0-based indexing, which is the convention Python uses.\n\nFor example, if someone subscribes for a year starting on 2016-02-29 inclusive,\nthe end date must be 2017-03-01 exclusive. If it was 2016-02-28 exclusive, the\nsubscription would be one day too short.\n\nOperations are always performed on years, then months, then days. This order\nusually provides the expected behavior. It also minimizes loss of precision.\n\nInstallation\n============\n\n.. code-block:: bash\n\n pip install datedelta\n\nUsage\n=====\n\nThe most common operations are adding a ``datedelta`` to a ``date`` and\nsubtracting a ``datedelta`` from a ``date``.\n\nBasic intervals\n---------------\n\nThe ``YEAR``, ``MONTH``, and ``DAY`` constants allow expressing common\ncalculations with little code.\n\n.. code-block:: python\n\n >>> import datetime\n >>> import datedelta\n\n >>> datetime.date(2016, 1, 1) + datedelta.YEAR\n datetime.date(2017, 1, 1)\n\n >>> datetime.date(2017, 1, 1) - datedelta.YEAR\n datetime.date(2016, 1, 1)\n\n >>> datetime.date(2016, 2, 29) + datedelta.YEAR\n datetime.date(2017, 3, 1)\n\n >>> datetime.date(2017, 3, 1) - datedelta.YEAR\n datetime.date(2016, 3, 1)\n\n >>> datetime.date(2016, 1, 1) + datedelta.MONTH\n datetime.date(2016, 2, 1)\n\n >>> datetime.date(2016, 2, 1) - datedelta.MONTH\n datetime.date(2016, 1, 1)\n\n >>> datetime.date(2016, 1, 31) + datedelta.MONTH\n datetime.date(2016, 3, 1)\n\n >>> datetime.date(2016, 3, 1) - datedelta.MONTH\n datetime.date(2016, 2, 1)\n\n >>> datetime.date(2016, 1, 1) + datedelta.WEEK\n datetime.date(2016, 1, 8)\n\n >>> datetime.date(2016, 1, 1) - datedelta.WEEK\n datetime.date(2015, 12, 25)\n\n >>> datetime.date(2016, 1, 1) + datedelta.DAY\n datetime.date(2016, 1, 2)\n\n >>> datetime.date(2016, 1, 1) - datedelta.DAY\n datetime.date(2015, 12, 31)\n\nNote that ``datedelta.DAY`` behaves exactly like ``datetime.timedelta(1)``.\nIt's only provided for consistency.\n\nArbitrary intervals\n-------------------\n\n``datedelta`` objects provide support for arbitrary calculations.\n\n.. code-block:: python\n\n >>> import datetime\n >>> import datedelta\n\n >>> datetime.date(2016, 3, 23) + datedelta.datedelta(years=1, months=1, days=-1)\n datetime.date(2017, 4, 22)\n\n >>> datetime.date(2016, 3, 23) - datedelta.datedelta(years=-1, months=-1, days=1)\n datetime.date(2017, 4, 22)\n\n >>> datetime.date(2016, 2, 29) + datedelta.datedelta(years=2)\n datetime.date(2018, 3, 1)\n\n >>> datetime.date(2020, 2, 29) - datedelta.datedelta(years=2)\n datetime.date(2018, 3, 1)\n\n >>> datetime.date(2016, 2, 29) + datedelta.datedelta(years=2, days=-1)\n datetime.date(2018, 2, 28)\n\n >>> datetime.date(2020, 2, 29) - datedelta.datedelta(years=2, days=1)\n datetime.date(2018, 2, 28)\n\n >>> datetime.date(2016, 2, 29) + datedelta.datedelta(years=2, months=6)\n datetime.date(2018, 9, 1)\n\n >>> datetime.date(2020, 2, 29) - datedelta.datedelta(years=2, months=-6)\n datetime.date(2018, 9, 1)\n\n >>> datetime.date(2016, 2, 29) + datedelta.datedelta(years=4)\n datetime.date(2020, 2, 29)\n\n >>> datetime.date(2020, 2, 29) - datedelta.datedelta(years=4)\n datetime.date(2016, 2, 29)\n\n >>> datetime.date(2016, 2, 29) + datedelta.datedelta(years=4, days=1)\n datetime.date(2020, 3, 1)\n\n >>> datetime.date(2020, 2, 29) - datedelta.datedelta(years=4, days=-1)\n datetime.date(2016, 3, 1)\n\n >>> datetime.date(2016, 2, 29) + datedelta.datedelta(years=4, months=6)\n datetime.date(2020, 8, 29)\n\n >>> datetime.date(2020, 2, 29) - datedelta.datedelta(years=4, months=-6)\n datetime.date(2016, 8, 29)\n\nThese results may appear slightly surprising. However, they're consistent, for\nreasons explained in the \"Behavior\" section above.\n\nOther operations\n----------------\n\n``datedelta`` instances can be added, subtracted, and multiplied with an\ninteger. However there are some restrictions on addition and subtraction.\n\nAs demonstrated in the \"Limitations\" section below, adding then subtracting a\ngiven datedelta to a date doesn't always return the original date. In order to\nprevent bugs caused by this behavior, when the result of adding or subtracting\ntwo ``datedelta`` isn't well defined, that operation raises ``ValueError``.\n\n.. code-block:: python\n\n >>> import datedelta\n\n >>> datedelta.YEAR + datedelta.YEAR\n datedelta.datedelta(years=2)\n\n >>> 3 * datedelta.YEAR\n datedelta.datedelta(years=3)\n\n >>> datedelta.YEAR - datedelta.DAY\n datedelta.datedelta(years=1, days=-1)\n\n >>> datedelta.YEAR - datedelta.YEAR\n Traceback (most recent call last):\n ...\n ValueError: cannot subtract datedeltas with same signs\n\n >>> datedelta.datedelta(months=6) + datedelta.datedelta(months=-3)\n Traceback (most recent call last):\n ...\n ValueError: cannot add datedeltas with opposite signs\n\nLimitations\n===========\n\nAdditions involving ``datedelta`` are neither associative nor commutative in\ngeneral.\n\nHere are two examples where adding a ``datedelta`` then subtracting it doesn't\nreturn the original value:\n\n.. code-block:: python\n\n >>> import datetime\n >>> import datedelta\n\n >>> datetime.date(2020, 2, 29) + datedelta.datedelta(years=1)\n datetime.date(2021, 3, 1)\n\n >>> datetime.date(2021, 3, 1) - datedelta.datedelta(years=1)\n datetime.date(2020, 3, 1)\n\n >>> datetime.date(2020, 1, 31) + datedelta.datedelta(months=1)\n datetime.date(2020, 3, 1)\n\n >>> datetime.date(2020, 3, 1) - datedelta.datedelta(months=1)\n datetime.date(2020, 2, 1)\n\nHere are two examples where adding two ``datedelta`` gives a different result\ndepending on the order of operations:\n\n.. code-block:: python\n\n >>> import datetime\n >>> import datedelta\n\n >>> datetime.date(2016, 2, 29) + datedelta.datedelta(months=6) + datedelta.datedelta(years=1)\n datetime.date(2017, 8, 29)\n\n >>> datetime.date(2016, 2, 29) + datedelta.datedelta(years=1) + datedelta.datedelta(months=6)\n datetime.date(2017, 9, 1)\n\n >>> datetime.date(2016, 1, 31) + datedelta.datedelta(months=2) + datedelta.datedelta(months=5)\n datetime.date(2016, 8, 31)\n\n >>> datetime.date(2016, 1, 31) + datedelta.datedelta(months=5) + datedelta.datedelta(months=2)\n datetime.date(2016, 9, 1)\n\nTo avoid problems, you should always start from the same reference date and add\na single ``datedelta``. Don't chain additions or subtractions.\n\nTo minimize the risk of incorrect results, ``datedelta`` only implements\noperations that have unambiguous semantics:\n\n* Adding a datedelta to a date\n* Subtracting a datedelta from a date\n* Adding a datedelta to a datedelta when components have the same sign\n* Subtracting a datedelta from a datedelta when components have opposite signs\n\n(PEP 20 says: \"In the face of ambiguity, refuse the temptation to guess.\")\n\nAlternatives\n============\n\n``datedelta.datedelta`` is smarter than ``datetime.timedelta`` because it knows\nabout years and months in addition to days.\n\n``datedelta.datedelta`` provides a subset of the features found in\n``dateutil.relativedelta``. Not only does it only support dates, but:\n\n* It omits the \"replace\" behavior which is very error-prone.\n* It doesn't allow explicit control of leapdays.\n* It uses keyword-only arguments.\n* It requires Python 3.\n\nHandling leap days automatically reduces the number of choices the programmer\nmust make and thus the number of errors they can make.\n\nNote that ``datedelta.datedelta`` adjusts non-existing days to the first day of\nthe next month while ``dateutil.relativedelta`` adjusts them to the last day of\nthe current month.\n\nIf you're stuck with Python 2, just copy the code, make ``datedelta`` inherit\nfrom ``object``, and remove the ``*`` in the signature of ``__init__``.\n\nIf you're comfortable with ``dateutil`` and don't mind its larger footprint,\nthere's little to gain by switching to ``datedelta``.\n\nChangelog\n=========\n\n1.3\n---\n\n* Add ``WEEK`` constant.\n\n1.2\n---\n\n* Optimize hashing and pickling.\n\n1.1\n---\n\n* Add ``YEAR``, ``MONTH``, and ``DAY`` constants.\n\n1.0\n---\n\n* Initial stable release.\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/aaugustin/datedelta", "keywords": "", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "datedelta", "package_url": "https://pypi.org/project/datedelta/", "platform": "", "project_url": "https://pypi.org/project/datedelta/", "project_urls": { "Homepage": "https://github.com/aaugustin/datedelta" }, "release_url": "https://pypi.org/project/datedelta/1.3/", "requires_dist": null, "requires_python": "", "summary": "Like datetime.timedelta, for date arithmetic.", "version": "1.3" }, "last_serial": 5472181, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "925fe905eba72611a57c9fc61c3c31f3", "sha256": "d167cdf9a72a9a6fcf1e2162f43666876b851b1422d493f1bafee91b0ca16274" }, "downloads": -1, "filename": "datedelta-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "925fe905eba72611a57c9fc61c3c31f3", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 7579, "upload_time": "2016-03-23T22:48:36", "url": "https://files.pythonhosted.org/packages/f1/72/bed1696397bb253c91033d0cbdc830bff8541a34b631d729caf63dd1b3a3/datedelta-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0f741e333ab3f0e426e8c23b4ae71942", "sha256": "3832cc1a292c83f082f43c4502e54f94da58a4f5c31701f58660bc52b6244faa" }, "downloads": -1, "filename": "datedelta-1.0.0.tar.gz", "has_sig": false, "md5_digest": "0f741e333ab3f0e426e8c23b4ae71942", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4410, "upload_time": "2016-03-23T22:47:31", "url": "https://files.pythonhosted.org/packages/c3/26/eb523c6109d6cddfc06d04b75ee4daa27bff4545fcbb2eb1c6dbc4531358/datedelta-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "db7a8cac50b505f1effeae99febf052a", "sha256": "59fb9ef6d3b1f22f240895ed662dcccfd33fa91061a579b59527a33c2e8728a5" }, "downloads": -1, "filename": "datedelta-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "db7a8cac50b505f1effeae99febf052a", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 8779, "upload_time": "2016-03-23T23:34:09", "url": "https://files.pythonhosted.org/packages/dc/1c/0fd592d570638dc088a43fa21f45fa57a8252fc6c027e80ac1b030fbee19/datedelta-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0d4b77c71268c59ac9198dc28c1f6f1b", "sha256": "b8b1eab2ab08b15c4912c888ea7283f9b9fd45fe51d5b5d87307a8fb7ef9a4d0" }, "downloads": -1, "filename": "datedelta-1.0.1.tar.gz", "has_sig": false, "md5_digest": "0d4b77c71268c59ac9198dc28c1f6f1b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5276, "upload_time": "2016-03-23T23:33:56", "url": "https://files.pythonhosted.org/packages/88/a3/539f295ddbfd980d792be353ad642ddf98b21730e120bb92c19bfdfc13b6/datedelta-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "6aa1bd90215b8a53da264896e3a5e017", "sha256": "84b122503d0cec98dd93ddbe9f6131c2344b16ef41a884dc693e14aaafde1909" }, "downloads": -1, "filename": "datedelta-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "6aa1bd90215b8a53da264896e3a5e017", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 8808, "upload_time": "2016-03-24T09:14:06", "url": "https://files.pythonhosted.org/packages/8f/99/7c0c07e2f4c3d85066b82650329ff331c028d4de3c7fdeca3b00cac11659/datedelta-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "88b72ed51b60facdf2c8f8e4d67c1ce0", "sha256": "3d7be252095f8522947db612a208bba1021a7fe8829c987b22c9a701198b7c91" }, "downloads": -1, "filename": "datedelta-1.0.2.tar.gz", "has_sig": false, "md5_digest": "88b72ed51b60facdf2c8f8e4d67c1ce0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5306, "upload_time": "2016-03-24T09:13:44", "url": "https://files.pythonhosted.org/packages/3c/55/7cde1a00529508f1b899616b08c6b6f822e88b27e7c0136720d4e215bbfa/datedelta-1.0.2.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "25708515ab53244329603ff31ddf6111", "sha256": "8109a892e2ae361a57b9c476a2ee172ac2e2b181941dd4e9f020bf1dd278e721" }, "downloads": -1, "filename": "datedelta-1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "25708515ab53244329603ff31ddf6111", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 9131, "upload_time": "2016-04-04T09:28:52", "url": "https://files.pythonhosted.org/packages/39/4a/d6befc43c2cc1fb61628bcf2f537f9292fbfd7e911c046f0fc8f17064997/datedelta-1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d36d451aa3c84b1f8c52516c9f3b0e67", "sha256": "b263f42ffd4d2150e01ae75d008713fbe93e6626279dedc233d8255f61600c53" }, "downloads": -1, "filename": "datedelta-1.1.tar.gz", "has_sig": false, "md5_digest": "d36d451aa3c84b1f8c52516c9f3b0e67", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5559, "upload_time": "2016-04-04T09:28:43", "url": "https://files.pythonhosted.org/packages/b2/e9/26618b376b0b0a3686bd4dd91382cccbbc2724fd43259259eb6b362efcfb/datedelta-1.1.tar.gz" } ], "1.2": [ { "comment_text": "", "digests": { "md5": "159957e137f2052cb80d563277a7c6e5", "sha256": "e90c3459c227fab571c683d957a9b5276790c242670d791bcd05e551cdcfc0b1" }, "downloads": -1, "filename": "datedelta-1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "159957e137f2052cb80d563277a7c6e5", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 10069, "upload_time": "2017-02-11T12:52:48", "url": "https://files.pythonhosted.org/packages/9a/01/16f37fcbd505cd2e6d096cd0052782d5ed96425561932414f858533e24ac/datedelta-1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7f3cc97c51f197362ee671b388fb86e0", "sha256": "dd2cea8569300dcc9fb7f387d19c946126fcbe5aaa36a759e33f89a587797ac8" }, "downloads": -1, "filename": "datedelta-1.2.tar.gz", "has_sig": false, "md5_digest": "7f3cc97c51f197362ee671b388fb86e0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6094, "upload_time": "2017-02-11T12:52:46", "url": "https://files.pythonhosted.org/packages/1b/58/ad2b7f73ed8709acc59b21a6081817a0e828b6285dfaa25957842991106b/datedelta-1.2.tar.gz" } ], "1.3": [ { "comment_text": "", "digests": { "md5": "713ee5b86b9c59d9b4df4046b153c7d2", "sha256": "eaf2b332582a083e0db7baab36ab37d5fe98b9de3cfd46a75c45247c59b2f117" }, "downloads": -1, "filename": "datedelta-1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "713ee5b86b9c59d9b4df4046b153c7d2", "packagetype": "bdist_wheel", "python_version": "3.7", "requires_python": null, "size": 6699, "upload_time": "2019-07-01T17:39:24", "url": "https://files.pythonhosted.org/packages/53/8c/00b6a91ad6b2f72efdc384afe76990ea751db4c2b092ae598f287c8f116c/datedelta-1.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ad005f957a280e277ac248e6ef73f5fd", "sha256": "b69229755ed61ae0a78dc63820a8ed1492a60126edceb430aece212b5ba19575" }, "downloads": -1, "filename": "datedelta-1.3.tar.gz", "has_sig": false, "md5_digest": "ad005f957a280e277ac248e6ef73f5fd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6984, "upload_time": "2019-07-01T17:39:22", "url": "https://files.pythonhosted.org/packages/7e/f8/9240da56a6859a8366e476c9fde26621396bff494bfeecd52323bf3717ce/datedelta-1.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "713ee5b86b9c59d9b4df4046b153c7d2", "sha256": "eaf2b332582a083e0db7baab36ab37d5fe98b9de3cfd46a75c45247c59b2f117" }, "downloads": -1, "filename": "datedelta-1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "713ee5b86b9c59d9b4df4046b153c7d2", "packagetype": "bdist_wheel", "python_version": "3.7", "requires_python": null, "size": 6699, "upload_time": "2019-07-01T17:39:24", "url": "https://files.pythonhosted.org/packages/53/8c/00b6a91ad6b2f72efdc384afe76990ea751db4c2b092ae598f287c8f116c/datedelta-1.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ad005f957a280e277ac248e6ef73f5fd", "sha256": "b69229755ed61ae0a78dc63820a8ed1492a60126edceb430aece212b5ba19575" }, "downloads": -1, "filename": "datedelta-1.3.tar.gz", "has_sig": false, "md5_digest": "ad005f957a280e277ac248e6ef73f5fd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6984, "upload_time": "2019-07-01T17:39:22", "url": "https://files.pythonhosted.org/packages/7e/f8/9240da56a6859a8366e476c9fde26621396bff494bfeecd52323bf3717ce/datedelta-1.3.tar.gz" } ] }