pax_global_header00006660000000000000000000000064140165515100014510gustar00rootroot0000000000000052 comment=7c024404aee1b0f06a34113de129dac37aa5d995 convertdate-2.3.2/000077500000000000000000000000001401655151000140325ustar00rootroot00000000000000convertdate-2.3.2/.gitignore000066400000000000000000000004341401655151000160230ustar00rootroot00000000000000# This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr build dist *.egg-info *.egg *.pyc *.whl .tox .eggs py35 __pycache__ *.sublime-project convertdate-2.3.2/.readthedocs.yml000066400000000000000000000003031401655151000171140ustar00rootroot00000000000000# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details version: 2 python: version: 3.8 install: - method: pip path: . extra_requirements: - docs convertdate-2.3.2/.travis.yml000066400000000000000000000007541401655151000161510ustar00rootroot00000000000000# This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016-2020, fitnr os: linux arch: - amd64 - ppc64le language: python python: - "3.5" - "3.6" - "3.7" - "3.8" - "3.9" - pypy3 matrix: exclude: - arch: ppc64le python: pypy3 # Use container-based infrastructure sudo: false install: - pip install tox-travis script: - tox convertdate-2.3.2/HISTORY.rst000066400000000000000000000067351401655151000157400ustar00rootroot00000000000000History ------- 2.3.2 ----- * Switch Persian calendar to astronomical computation (was non-canonical algorithmic method) * Fix inappropriate uses of trunc, which caused several errors before the Julian Day epoch (#39, #40, #42) * Fix bug in `julian.leap` (#43) * Add official suppport and tests for Python 3.9 * Raise ValueError for attempted conversion of dates before the Mayan epoch 2.3.1 ----- * Adjust requirements to avoid a broken release (pymeeus 0.3.8) 2.3.0 ----- * Fix bug in Bahai calculations during Ayyám-i-Há (#32). Thanks @chiuczek * Regularize variable names: - coptic: rename `MONTH_NAMES` to `MONTHS`, rename `DAY_NAMES` to `WEEKDAYS` - french_republican: add `MONTHS` - mayan: rename `HAAB_MONTHS` to `HAAB`, rename `TZOLKIN_NAMES` to `TZOLKIN` * Add some Jewish and Islamic holidays to `holidays`: `shemini_azeret`, `lag_baomer`, `tu_beshvat`, `tisha_bav`, `ramadan`, `ashura`, `eid_alfitr`, `eid_aladha` * Add docs. See https://convertdate.readthedocs.io/ * Fix December 31st bug in `ordinal` (#34) * Add Indigenous Peoples' Day and Juneteenth to `holidays`, deprecate Columbus day * Additional `format` methods for expressing dates as strings (#37, thanks @philosp) 2.2.2 ----- * Add `observed` argument to the functions for several American holidays (#30) 2.2.1 ----- * Add orthodox/eastern Easter calculations and docs * Add module for Armenian and Sarkawag regularisation * Bump pytz requirement 2.2.0 ----- * Repair Bahai intercalary days bug (#13, thanks @bchurchill) * Replace pyephem, which is now in maintenance mode, with pymeeus. * Remove shebangs and regularize licenses (thanks @fabaff) * Convert readme to ascii (#16) 2.1.3 ----- * Bump requirements 2.1.2 ----- * Additional Jewish holidays (thanks, @ohadeytan) * Upload source distributions to Pypi (#10) 2.1.1 ----- * Add Coptic (Alexandrian) calendar converter. * Add explicit support for Python 3.6. 2.1.0 ----- * Change Exception thrown on illegal dates to ValueError. * Add Comte's Positivist calendar. * Bump requirement versions. 2.0.8 ----- * Fix Persian weekday order (thanks, @meyt) 2.0.7 ----- * Better Python 2/3 compatibility * Improve tests * bump pytz requirement 2.0.6 ----- * Executing holidays module returns class with current year, not '2014'. * Expand tests for French Republican, Bahai, Persian, holidays * Add Travis CI testing Bug fixes: * Fix edge case when detecting the day of fall equinox in French Republican calendar * Fix minor methods of calculating French Republican leap years. * Change holidays.holidays.fathers_day from a method to a property * Add pulaski_day to holidays.holidays * Add pytz is dependency list 2.0.5 ----- * Fix Yom Kippur error in holidays.py (issue #3) 2.0.4 ----- * Typo in name of holidays.independence_day method * Fix major bug in ordinal.from_gregorian * Expand and organized tests 2.0.3.1 ------- Features: * Add `ordinal` module, for counting the day of year * Added Mexican national holidays * Add `monthcalendar` functions Other changes: * Simplified logic in `ISO` module 2.0.3 ----- Features: - Add list of day names and `day_name` function to French Republican converter - Add multiple conversion methods to the French Republican calendar - Add Dublin day count and Julian day count converters - Add month names to Bahai and Hebrew calendars. Other changes: - Clarify that weekdays run Monday=0 to Sunday=6 (#2) - Change Julian converter to use astronomical notation (0 = 1 BCE, -1 = 1 BCE) - Expanded tests 2.0.2 ----- Features: * Add support for Python 3 (#1) convertdate-2.3.2/LICENSE000066400000000000000000000020751401655151000150430ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014-2016 Neil Freeman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. convertdate-2.3.2/Makefile000066400000000000000000000011521401655151000154710ustar00rootroot00000000000000# This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr .PHONY: all htmlcov test deploy format all: htmlcov: | test python -m coverage html test: tox cov: python -m coverage run --branch --source=convertdate -m unittest python -m coverage report format: black src/ tests/ isort src/convertdate/*.py src/convertdate/data/*.py tests/*.py deploy: rm -rf dist build python setup.py sdist python setup.py bdist_wheel twine upload dist/* git push; git push --tags convertdate-2.3.2/README.md000066400000000000000000000156171401655151000153230ustar00rootroot00000000000000convertdate =========== The convertdate package was originally developed as "[Python Date Utils](http://sourceforge.net/projects/pythondateutil/)" by Phil Schwartz. It had been significantly updated and expanded. [Consult the complete docs for detailed usage info](https://convertdate.readthedocs.io/). Available calendars: - Armenian - Bahai - Coptic (Alexandrian) - French Republican - Gregorian - Hebrew - Indian Civil - Islamic - Julian - Mayan - Persian - Positivist - Mayan - ISO - Ordinal (day of year) - Dublin day count - Julian day count The `holidays` module also provides some useful holiday-calculation, with a focus on North American and Jewish holidays. Installing ---------- `pip install convertdate` Or download the package and run `python setup.py install`. Using ----- >>> from convertdate import french_republican >>> from convertdate import hebrew >>> french_republican.from_gregorian(2014, 10, 31) (223, 2, 9) >>> hebrew.from_gregorian(2014, 10, 31) (5775, 8, 7) Note that in some calendar systems, the day begins at sundown. Convertdate gives the conversion for noon of the day in question. Each module includes a `monthcalendar` function, which will generate a calender-like nested list for a year and month (each list of dates runs from Sunday to Saturday) >>> hebrew.monthcalendar(5775, 8) [ [None, None, None, None, None, None, 1], [2, 3, 4, 5, 6, 7, 8], [9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22], [23, 24, 25, 26, 27, 28, 29] ] >>> julian.monthcalendar(2015, 1) [ [None, None, None, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17, 18], [19, 20, 21, 22, 23, 24, 25], [26, 27, 28, 29, 30, 31, None] ] Special Options --------------- ### Armenian The Armenian calendar begins on 11 July 552 (Julian) and has two modes of reckoning. The first is the invariant-length version consisting of 12 months of 30 days each and five epagomenal days; the second is the version established by Yovhannes Sarkawag in 1084, which fixed the first day of the year with respect to the Julian calendar and added a sixth epagomenal day every four years. By default the invariant calendar is used, but the Sarkawag calendar can be used beginning with the Armenian year 533 (11 August 1084) by passing the parameter `method='sarkawag'` to the relevant functions. ### French Republican Leap year calculations in the French Republican calendar are a matter of dispute. By default, `convertdate` calculates leap years using the autumnal equinox. You can also use one of three more systematic methods proposed over the years. - Romme, a co-creator of the calendar, proposed leap years in years divisible by four, except for years divisible by 100. - Some concordances were drawn up in the 19th century that gave leap years every 4 years, in years that give a remainder of three when divided by four (19, 23, 27, etc...). - Von Mädler proposed leap years in years divisible by four, except for years divisible by 128. You can specify any of these three methods with the method keyword argument in `french_republican` conversion functions. from convertdate import french_republican # Romme's method french_republican.to_gregorian(20, 1, 1), method='romme') # (1811, 9, 23) # continuous method french_republican.to_gregorian(20, 1, 1), method='continuous') # (1811, 9, 24) # von Madler's method french_republican.to_gregorian(20, 1, 1), method='madler') # (1811, 9, 23) All the conversion methods correctly assign the leap years implemented while calendar was in use (3, 7, 11). Baha'i ------ The Bahá'í (Badí) calendar has an intercalary period, Ayyam-i-Há, which occurs between the 18th and 19th months. Dates in this period are returned as month 19, and the month of ‘Alá is reported as month 20. ```python from convertdate import bahai # the first day of Ayyam-i-Ha: bahai.to_gregorian(175, 19, 1) # (2019, 2, 26) # The first day of 'Ala: bahai.to_gregorian(175, 20, 1) # (2019, 3, 2) ``` Before the Common Era --------------------- For dates before the Common Era (year 1), `convertdate` uses astronomical notation: 1 BC is recorded as 0, 2 BC is -1, etc. This makes arithmatic much easier at the expense of ignoring custom. Note that for dates before 4 CE, `convertdate` uses the [proleptic Julian calendar](https://en.wikipedia.org/wiki/Proleptic_Julian_calendar). The Julian Calendar was in use from 45 BC, but before 4 CE the leap year leap year pattern was irregular. The [proleptic Gregorian calendar](https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar) is used for dates before 1582 CE, the year of the Gregorian calendar reform. Holidays -------- North American holidays are the current focus of the `holidays` module, but pull requests are welcome. from convertdate import holidays # For simplicity, functions in the holidays module return a tuple # In the format (year, month, day) holidays.new_years(2014) # (2014, 1, 1) holidays.memorial_day(2014) # (2014, 5, 26) # USA is default holidays.thanksgiving(2014) # (2014, 11, 27) # But there is a Canadian option for some holidays holidays.thanksgiving(2014, 'canada') # (2014, 10, 13) # Mexican national holidays holidays.natalicio_benito_juarez(2016) # (2016, 3, 21) holidays.dia_revolucion(2016) # (2016, 11, 21) # Some Jewish holidays are included holidays.rosh_hashanah(2014) # Easter can be calculated according to different churches # ('western', 'orthodox', 'eastern') # The eastern Christian computation differs from the Orthodox one # 4 times in each 532-year cycle. holidays.easter(2019) # (2019, 4, 21) holidays.easter(2019, church="orthodox") # (2019, 4, 28) holidays.easter(2019, church="orthodox") # (2019, 4, 28) Utils ----- Convertdate includes some utilities for manipulating and calculating dates. from convertdate import utils # Calculate an arbitrary day of the week THUR = 3 APRIL = 4 # 3rd Thursday in April utils.nth_day_of_month(3, THUR, APRIL, 2014) # (2014, 4, 17) utils.nth_day_of_month(5, THUR, APRIL, 2014) # IndexError: No 5th day of month 4 # Use 0 for the first argument to get the last weekday of a month utils.nth_day_of_month(0, THUR, APRIL, 2014) # (2014, 4, 24) Note that when calculating weekdays, convertdate uses the convention of the calendar and time modules: Monday is 0, Sunday is 6. from convertdate import gregorian SUN = 6 day = gregorian.to_jd(2014, 4, 17) nextsunday = utils.next_weekday(SUN, day) gregorian.from_jd(nextsunday) # (2014, 4, 20) Other utility functions: - nearest\_weekday - next\_or\_current\_weekday - previous\_weekday - previous\_or\_current\_weekday convertdate-2.3.2/docs/000077500000000000000000000000001401655151000147625ustar00rootroot00000000000000convertdate-2.3.2/docs/.gitignore000066400000000000000000000000061401655151000167460ustar00rootroot00000000000000_buildconvertdate-2.3.2/docs/Makefile000066400000000000000000000011701401655151000164210ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build SOURCEDIR = . BUILDDIR = _build # Put it first so that "make" without argument is like "make help". help: $(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) convertdate-2.3.2/docs/conf.py000066400000000000000000000036531401655151000162700ustar00rootroot00000000000000# Configuration file for the Sphinx documentation builder. # # This file only contains a selection of the most common options. For a full # list see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # import os import sys sys.path.insert(0, os.path.abspath('../src')) # -- Project information ----------------------------------------------------- project = 'convertdate' copyright = '2020, Neil Freeman' author = 'Neil Freeman' # The full version, including alpha/beta/rc tags with open('../src/convertdate/__init__.py') as i: release = next(r for r in i.readlines() if '__version__' in r).split('=')[1].strip('"\' \n') # -- General configuration --------------------------------------------------- master_doc = 'index' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc' ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] html_sidebars = {'*': ['globaltoc.html', 'sourcelink.html']} # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = "sphinx_rtd_theme" html_theme_options = { 'display_version': True, } convertdate-2.3.2/docs/index.rst000066400000000000000000000007371401655151000166320ustar00rootroot00000000000000.. convertdate documentation master file, created by sphinx-quickstart on Sun Sep 27 16:55:31 2020. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Documentation for convertdate ============================= .. automodule:: convertdate .. toctree:: :caption: Modules :maxdepth: 3 :glob: modules/* Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` convertdate-2.3.2/docs/modules/000077500000000000000000000000001401655151000164325ustar00rootroot00000000000000convertdate-2.3.2/docs/modules/armenian.rst000066400000000000000000000001531401655151000207550ustar00rootroot00000000000000Armenian calendar ================= .. automodule:: convertdate.armenian :members: :undoc-members: convertdate-2.3.2/docs/modules/bahai.rst000066400000000000000000000001511401655151000202250ustar00rootroot00000000000000Bahá'í calendar ================ .. automodule:: convertdate.bahai :members: :undoc-members: convertdate-2.3.2/docs/modules/coptic.rst000066400000000000000000000001461401655151000204460ustar00rootroot00000000000000Coptic calendar =============== .. automodule:: convertdate.coptic :members: :undoc-members: convertdate-2.3.2/docs/modules/daycount.rst000066400000000000000000000001461401655151000210130ustar00rootroot00000000000000Day count class =============== .. automodule:: convertdate.daycount :members: :undoc-members: convertdate-2.3.2/docs/modules/dublin.rst000066400000000000000000000001741401655151000204430ustar00rootroot00000000000000Dublin day count ================ .. automodule:: convertdate.dublin :members: :undoc-members: :imported-members: convertdate-2.3.2/docs/modules/french_republican.rst000066400000000000000000000002071401655151000226340ustar00rootroot00000000000000French Republican calendar ========================== .. automodule:: convertdate.french_republican :members: :undoc-members: convertdate-2.3.2/docs/modules/gregorian.rst000066400000000000000000000001571401655151000211440ustar00rootroot00000000000000Gregorian calendar ================== .. automodule:: convertdate.gregorian :members: :undoc-members: convertdate-2.3.2/docs/modules/hebrew.rst000066400000000000000000000001451401655151000204400ustar00rootroot00000000000000Hebrew calendar =============== .. automodule:: convertdate.hebrew :members: :undoc-members: convertdate-2.3.2/docs/modules/holidays.rst000066400000000000000000000001311401655151000207730ustar00rootroot00000000000000Holidays ========= .. automodule:: convertdate.holidays :members: :undoc-members: convertdate-2.3.2/docs/modules/indian_civil.rst000066400000000000000000000001701401655151000216120ustar00rootroot00000000000000Indian Civil calendar ====================== .. automodule:: convertdate.indian_civil :members: :undoc-members: convertdate-2.3.2/docs/modules/islamic.rst000066400000000000000000000001521401655151000206030ustar00rootroot00000000000000Islamic calendar ================= .. automodule:: convertdate.islamic :members: :undoc-members: convertdate-2.3.2/docs/modules/iso.rst000066400000000000000000000001351401655151000177550ustar00rootroot00000000000000ISO calendar ============= .. automodule:: convertdate.iso :members: :undoc-members: convertdate-2.3.2/docs/modules/julian.rst000066400000000000000000000001451401655151000204460ustar00rootroot00000000000000Julian calendar =============== .. automodule:: convertdate.julian :members: :undoc-members: convertdate-2.3.2/docs/modules/julianday.rst000066400000000000000000000001541401655151000211440ustar00rootroot00000000000000Julian Day Count ================= .. automodule:: convertdate.julianday :members: :undoc-members: convertdate-2.3.2/docs/modules/mayan.rst000066400000000000000000000001441401655151000202700ustar00rootroot00000000000000Mayan calendar ============== .. automodule:: convertdate.mayan :members: :undoc-members: convertdate-2.3.2/docs/modules/ordinal.rst000066400000000000000000000001441401655151000206130ustar00rootroot00000000000000Ordinal dates ============== .. automodule:: convertdate.ordinal :members: :undoc-members: convertdate-2.3.2/docs/modules/persian.rst000066400000000000000000000001531401655151000206240ustar00rootroot00000000000000Persian Calendar =================== .. automodule:: convertdate.persian :members: :undoc-members: convertdate-2.3.2/docs/modules/positivist.rst000066400000000000000000000001621401655151000214000ustar00rootroot00000000000000Positivist Calendar =================== .. automodule:: convertdate.positivist :members: :undoc-members: convertdate-2.3.2/docs/modules/utils.rst000066400000000000000000000001311401655151000203170ustar00rootroot00000000000000Utilities ========= .. automodule:: convertdate.utils :members: :undoc-members: convertdate-2.3.2/pyproject.toml000066400000000000000000000007751401655151000167570ustar00rootroot00000000000000# This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2020, fitnr [tool.black] line-length = 120 target-version = ["py38"] include = 'py$' skip-string-normalization = true [tool.pylint.master] fail-under = "9.5" [tool.pylint.messages_control] disable = [ "invalid-name", "duplicate-code" ] [tool.pylint.format] max-line-length = 120 [tool.isort] line_length = 120 convertdate-2.3.2/setup.py000066400000000000000000000037061401655151000155520ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr from setuptools import setup try: readme = open('README.md').read() except IOError: readme = '' with open('src/convertdate/__init__.py') as i: version = next(r for r in i.readlines() if '__version__' in r).split('=')[1].strip('"\' \n') tests_require = [ "coverage", ] setup( name="convertdate", version=version, description=("Converts between Gregorian dates and other calendar systems." "Calendars included: Baha'i, French Republican, Hebrew, " "Indian Civil, Islamic, ISO, Julian, Mayan and Persian."), long_description=readme, long_description_content_type='text/markdown', author="Neil Freeman", license='MIT', author_email="contact@fakeisthenewreal.org", url="https://github.com/fitnr/convertdate", packages=['convertdate', 'convertdate.data'], package_dir={'convertdate': 'src/convertdate'}, zip_safe=True, classifiers=[ 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Topic :: Religion', 'Topic :: Scientific/Engineering :: Astronomy', 'Operating System :: OS Independent', 'License :: OSI Approved :: MIT License' ], python_requires=">=3.5", install_requires=[ 'pytz>=2014.10', 'pymeeus>=0.3.13, <=1' ], tests_require=tests_require, extras_require={ 'test': tests_require, 'docs': [ 'sphinx', 'sphinx_rtd_theme' ] } ) convertdate-2.3.2/src/000077500000000000000000000000001401655151000146215ustar00rootroot00000000000000convertdate-2.3.2/src/convertdate/000077500000000000000000000000001401655151000171375ustar00rootroot00000000000000convertdate-2.3.2/src/convertdate/__init__.py000066400000000000000000000031021401655151000212440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, 2020, 2021 fitnr """ The Convertdate library contains methods and functions for converting dates between different calendar systems. It was originally developed as as `Python Date Util <(http://sourceforge.net/projects/pythondateutil/>`__ by Phil Schwartz. It had been significantly updated and expanded. Most of the original code is ported from `Fourmilab's calendar converter `__, which was developed by John Walker. The algorithms are believed to be derived from: Meeus, Jean. `Astronomical Algorithms`, Richmond: Willmann-Bell, 1991 (ISBN 0-943396-35-2) """ from . import armenian from . import bahai from . import coptic from . import daycount from . import dublin from . import french_republican from . import gregorian from . import hebrew from . import holidays from . import indian_civil from . import iso from . import islamic from . import julian from . import julianday from . import mayan from . import persian from . import positivist from . import ordinal from . import utils __version__ = '2.3.2' __all__ = [ 'holidays', 'armenian', 'bahai', 'coptic', 'dublin', 'daycount', 'french_republican', 'gregorian', 'hebrew', 'indian_civil', 'islamic', 'iso', 'julian', 'julianday', 'mayan', 'persian', 'positivist', 'mayan', 'ordinal', 'utils', ] convertdate-2.3.2/src/convertdate/armenian.py000066400000000000000000000122331401655151000213040ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """ The Armenian calendar begins on 11 July 552 (Julian) and has two modes of reckoning. The first is the invariant-length version consisting of 12 months of 30 days each and five epagomenal days; the second is the version established by Yovhannes Sarkawag in 1084, which fixed the first day of the year with respect to the Julian calendar and added a sixth epagomenal day every four years. By default the invariant calendar is used, but the Sarkawag calendar can be used beginning with the Armenian year 533 (11 August 1084) by passing the parameter ``method='sarkawag'`` to the relevant functions. """ from math import trunc from . import gregorian, julian from .utils import jwday, monthcalendarhelper EPOCH = 1922501.5 # beginning of proleptic year 0, day 0 of the moveable calendar EPOCH_SARKAWAG = 2117210.5 # last day of Sarkawag's first cycle MONTHS = [ "nawasard", "hoṙi", "sahmi", "trē", "kʿałocʿ", "aracʿ", "mehekan", "areg", "ahekan", "mareri", "margacʿ", "hroticʿ", "aweleacʿ", ] MONTHS_ARM = [ "նաւասարդ", "հոռի", "սահմի", "տրէ", "քաղոց", "արաց", "մեհեկան", "արեգ", "ահեկան", "մարերի", "մարգաց", "հրոտից", "աւելեաց", ] def _valid_date(year, month, day, method=None): try: assert 1 <= month <= 13, "Month out of range" except AssertionError as error: raise ValueError from error day_max = 30 method = method or "moveable" if method.lower() == "sarkawag": year_min = 533 if month == 13: day_max = 6 if leap(year) else 5 else: year_min = 1 if month == 13: day_max = 5 try: assert year >= year_min, "Year out of range for Armenian calendar ({} method)".format(method) except AssertionError as err: raise ValueError from err try: assert 1 <= day <= day_max, "Day out of range" except AssertionError as err: raise ValueError from err return True def leap(year): """Return true if the year was a leap year under the system of Sarkawag""" if year < 533: return False return year % 4 == 0 def to_jd(year, month, day, method=None): """Convert Armenian date to Julian day count. Use the method of Sarkawag if requested.""" _valid_date(year, month, day, method) yeardays = (month - 1) * 30 + day if method == "sarkawag": yeardelta = year - 533 leapdays = trunc(yeardelta / 4) return EPOCH_SARKAWAG + (365 * yeardelta) + leapdays + yeardays return EPOCH + (365 * year) + yeardays def from_jd(jd, method=None): """Convert a Julian day count to an Armenian date. Use the method of Sarkawag if requested.""" if method == "sarkawag": dc = jd - EPOCH_SARKAWAG if dc < 0: raise ValueError("Day count out of range for method") years = trunc(dc / 365.25) yeardays = dc - (365 * years + trunc(years / 4)) if yeardays == 0: yeardays = 366 if years % 4 == 0 else 365 years -= 1 months = trunc((yeardays - 1) / 30) days = yeardays - (30 * months) return years + 533, months + 1, trunc(days) dc = jd - EPOCH if dc < 0: raise ValueError("Day count out of range") years = trunc((dc - 1) / 365) months = trunc(((dc - 1) % 365) / 30) days = dc - (365 * years) - (30 * months) return years, months + 1, trunc(days) def to_julian(year, month, day, method=None): return julian.from_jd(to_jd(year, month, day, method)) def from_julian(year, month, day, method=None): return from_jd(julian.to_jd(year, month, day), method) def to_gregorian(year, month, day, method=None): return gregorian.from_jd(to_jd(year, month, day, method)) def from_gregorian(year, month, day, method=None): return from_jd(gregorian.to_jd(year, month, day), method) def month_length(year, month, method=None): if month > 13: raise ValueError("Requested month %d doesn't exist" % month) if month == 13: return 6 if (method == "sarkawag" and leap(year)) else 5 return 30 def monthcalendar(year, month, method=None): start_weekday = jwday(to_jd(year, month, 1, method)) monthlen = month_length(year, month, method) return monthcalendarhelper(start_weekday, monthlen) def format(year, month, day, lang=None): """Convert an Armenian date into a string with the format DD MONTH YYYY.""" # pylint: disable=redefined-builtin lang = lang or "en" if lang[0:2] == 'hy' or lang[0:2] == 'am' or lang == 'arm': month_name = MONTHS_ARM[month - 1] else: month = month_name = MONTHS[month - 1] return "{0:d} {1:} {2:d}".format(day, month_name, year) def tostring(year, month, day, lang=None): """Kept for backwards compatibility, the format function name will be standard across the library""" return format(year, month, day, lang) convertdate-2.3.2/src/convertdate/bahai.py000066400000000000000000000116311401655151000205570ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """ The Bahá'í (Badí) calendar is a solar calendar with 19 months of 19 days. Every four years, an intercalary period, Ayyam-i-Há, occurs between the 18th and 19th months. Dates in this period are returned as month 19, and the month of ‘Alá is always reported as month 20. .. code-block:: python from convertdate import bahai # the first day of Ayyam-i-Ha: bahai.to_gregorian(175, 19, 1) # (2019, 2, 26) # The first day of 'Ala: bahai.to_gregorian(175, 20, 1) # (2019, 3, 2) """ from calendar import isleap from math import ceil, trunc from pymeeus.Angle import Angle from pymeeus.Epoch import Epoch from pymeeus.Sun import Sun from . import gregorian from .utils import jwday, monthcalendarhelper EPOCH = 2394646.5 EPOCH_GREGORIAN_YEAR = 1844 TEHRAN = 51.4215, 35.6944 WEEKDAYS = ("Jamál", "Kamál", "Fidál", "Idál", "Istijlál", "Istiqlál", "Jalál") MONTHS = ( "Bahá", "Jalál", "Jamál", "‘Aẓamat", "Núr", "Raḥmat", "Kalimát", "Kamál", "Asmá’", "‘Izzat", "Mashíyyat", "‘Ilm", "Qudrat", "Qawl", "Masá’il", "Sharaf", "Sulṭán", "Mulk", "Ayyám-i-Há", "‘Alá", ) ENGLISH_MONTHS = ( "Splendor", "Glory", "Beauty", "Grandeur", "Light", "Mercy", "Words", "Perfection", "Names", "Might", "Will", "Knowledge", "Power", "Speech", "Questions", "Honour", "Sovereignty", "Dominion", "Days of Há", "Loftiness", ) BAHA = 1 JALAL = 2 JAMAL = 3 AZAMAT = 4 NUR = 5 RAHMAT = 6 KALIMAT = 7 KAMAL = 8 ASMA = 9 IZZAT = 10 MASHIYYAT = 11 ILM = 12 QUDRAT = 13 QAWL = 14 MASAIL = 15 SHARAF = 16 SULTAN = 17 MULK = 18 AYYAMIHA = 19 ALA = 20 def gregorian_nawruz(year): """ Return Nawruz in the Gregorian calendar. Returns a tuple (month, day), where month is always 3 """ if year == 2059: return 3, 20 # Timestamp of spring equinox. equinox = Sun.get_equinox_solstice(year, "spring") # Get times of sunsets in Tehran near vernal equinox. x, y = Angle(TEHRAN[0]), Angle(TEHRAN[1]) days = trunc(equinox.get_date()[2]), ceil(equinox.get_date()[2]) for day in days: sunset = Epoch(year, 3, day).rise_set(y, x)[1] if sunset > equinox: return 3, day raise ValueError("Couldn't find date of Nawruz.") def to_jd(year, month, day): '''Determine Julian day from Bahai date''' if month <= 18: gy = year - 1 + EPOCH_GREGORIAN_YEAR n_month, n_day = gregorian_nawruz(gy) return gregorian.to_jd(gy, n_month, n_day - 1) + day + (month - 1) * 19 if month == 19: # Count Ayyám-i-Há from the last day of Mulk return to_jd(year, month - 1, 19) + day # For the month of ‘Alá we will count _backwards_ from the next Naw Rúz gy = year + EPOCH_GREGORIAN_YEAR n_month, n_day = gregorian_nawruz(gy) return gregorian.to_jd(gy, n_month, n_day) - 20 + day def from_jd(jd): '''Calculate Bahai date from Julian day''' jd = trunc(jd) + 0.5 g = gregorian.from_jd(jd) gy = g[0] n_month, n_day = gregorian_nawruz(gy) bstarty = EPOCH_GREGORIAN_YEAR if jd <= gregorian.to_jd(gy, n_month, 20): x = 1 else: x = 0 # verify this next line... bys = gy - (bstarty + (((gregorian.to_jd(gy, 1, 1) <= jd) and x))) year = bys + 1 days = jd - to_jd(year, 1, 1) bld = to_jd(year, n_day - 1, 1) if jd >= bld: month = 20 else: month = trunc(days / 19) + 1 day = int((jd + 1) - to_jd(year, month, 1)) return year, month, day def from_gregorian(year, month, day): return from_jd(gregorian.to_jd(year, month, day)) def to_gregorian(year, month, day): return gregorian.from_jd(to_jd(year, month, day)) def month_length(year, month): gy = year + EPOCH_GREGORIAN_YEAR - 1 if month == 19: _, nawruz_future = gregorian_nawruz(gy + 1) _, nawruz_past = gregorian_nawruz(gy) length_of_year = nawruz_future + 365 - nawruz_past if isleap(gy + 1): length_of_year = length_of_year + 1 return length_of_year - 19 * 19 return 19 def monthcalendar(year, month): start_weekday = jwday(to_jd(year, month, 1)) monthlen = month_length(year, month) return monthcalendarhelper(start_weekday, monthlen) def format(year, month, day, lang=None): """Convert a Baha'i date into a string with the format DD MONTH YYYY.""" # pylint: disable=redefined-builtin lang = lang or "en" if lang[0:2] == 'ar' or lang[0:2] == 'fa': month_name = MONTHS[month - 1] else: month_name = ENGLISH_MONTHS[month - 1] return "{0:d} {1:} {2:d}".format(day, month_name, year) convertdate-2.3.2/src/convertdate/coptic.py000066400000000000000000000044541401655151000210010ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http:#github.com/fitnr/convertdate # Licensed under the MIT license: # http:#opensource.org/licenses/MIT # Copyright (c) 2017, fitnr """ The `Coptic calendar `__, also called the Alexandrian calendar, is a liturgical calendar used by the Coptic Orthodox Church and some communities in Egypt. It is a reformed version of the ancient Egyptian calendar. It consists of twelve months of 30 days, followed by a "little month" of five days (six in leap years). """ from . import gregorian from .utils import floor, jwday, monthcalendarhelper EPOCH = 1825029.5 MONTHS = [ "Thout", "Paopi", "Hathor", "Koiak", "Tobi", "Meshir", "Paremhat", "Paremoude", "Pashons", "Paoni", "Epip", "Mesori", "Pi Kogi Enavot", ] WEEKDAYS = ["Tkyriaka", "Pesnau", "Pshoment", "Peftoou", "Ptiou", "Psoou", "Psabbaton"] def is_leap(year): "Determine whether this is a leap year." return year % 4 == 3 or year % 4 == -1 def to_jd(year, month, day): "Retrieve the Julian date equivalent for this date" return day + (month - 1) * 30 + (year - 1) * 365 + floor(year / 4) + EPOCH - 1 def from_jd(jdc): "Create a new date from a Julian date." cdc = floor(jdc) + 0.5 - EPOCH year = floor((cdc - floor((cdc + 366) / 1461)) / 365) + 1 yday = jdc - to_jd(year, 1, 1) month = floor(yday / 30) + 1 day = yday - (month - 1) * 30 + 1 return int(year), int(month), int(day) def to_gregorian(year, month, day): return gregorian.from_jd(to_jd(year, month, day)) def from_gregorian(year, month, day): return from_jd(gregorian.to_jd(year, month, day)) def month_length(year, month): if month <= 12: return 30 if month == 13: if is_leap(year): return 6 return 5 raise ValueError("Invalid month") def monthcalendar(year, month): start_weekday = jwday(to_jd(year, month, 1)) monthlen = month_length(year, month) return monthcalendarhelper(start_weekday, monthlen) def format(year, month, day): """Convert a Coptic date into a string with the format DD MONTH YYYY.""" # pylint: disable=redefined-builtin return "{0:d} {1:} {2:d}".format(day, MONTHS[month - 1], year) convertdate-2.3.2/src/convertdate/data/000077500000000000000000000000001401655151000200505ustar00rootroot00000000000000convertdate-2.3.2/src/convertdate/data/__init__.py000066400000000000000000000000001401655151000221470ustar00rootroot00000000000000convertdate-2.3.2/src/convertdate/data/french_republican_days.py000066400000000000000000000167401401655151000251230ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr # source: Wikipedia # month 13 is the Sansculottides french_republican_days = { 1: [ "Raisin", "Safran", "Châtaigne", "Colchique", "Cheval", "Balsamine", "Carotte", "Amaranthe", "Panais", "Cuve", "Pomme de terre", "Immortelle", "Potiron", "Réséda", "Âne", "Belle de nuit", "Citrouille", "Sarrasin", "Tournesol", "Pressoir", "Chanvre", "Pêche", "Navet", "Amaryllis", "Bœuf", "Aubergine", "Piment", "Tomate", "Orge", "Tonneau", ], 2: [ "Pomme", "Céleri", "Poire", "Betterave", "Oie", "Héliotrope", "Figue", "Scorsonère", "Alisier", "Charrue", "Salsifis", "Mâcre", "Topinambour", "Endive", "Dindon", "Chervis", "Cresson", "Dentelaire", "Grenade", "Herse", "Bacchante", "Azerole", "Garance", "Orange", "Faisan", "Pistache", "Macjonc", "Coing", "Cormier", "Rouleau", ], 3: [ "Raiponce", "Turneps", "Chicorée", "Nèfle", "Cochon", "Mâche", "Chou-fleur", "Miel", "Genièvre", "Pioche", "Cire", "Raifort", "Cèdre", "Sapin", "Chevreuil", "Ajonc", "Cyprès", "Lierre", "Sabine", "Hoyau", "Érable à sucre", "Bruyère", "Roseau", "Oseille", "Grillon", "Pignon", "Liège", "Truffe", "Olive", "Pelle", ], 4: [ "Tourbe", "Houille", "Bitume", "Soufre", "Chien", "Lave", "Terre végétale", "Fumier", "Salpêtre", "Fléau", "Granit", "Argile", "Ardoise", "Grès", "Lapin", "Silex", "Marne", "Pierre à chaux", "Marbre", "Van", "Pierre à plâtre", "Sel", "Fer", "Cuivre", "Chat", "Étain", "Plomb", "Zinc", "Mercure", "Crible", ], 5: [ "Lauréole", "Mousse", "Fragon", "Perce-neige", "Taureau", "Laurier-thym", "Amadouvier", "Mézéréon", "Peuplier", "Coignée", "Ellébore", "Brocoli", "Laurier", "Avelinier", "Vache", "Buis", "Lichen", "If", "Pulmonaire", "Serpette", "Thlaspi", "Thimelé", "Chiendent", "Trainasse", "Lièvre", "Guède", "Noisetier", "Cyclamen", "Chélidoine", "Traîneau", ], 6: [ "Tussilage", "Cornouiller", "Violier", "Troène", "Bouc", "Asaret", "Alaterne", "Violette", "Marceau", "Bêche", "Narcisse", "Orme", "Fumeterre", "Vélar", "Chèvre", "Épinard", "Doronic", "Mouron", "Cerfeuil", "Cordeau", "Mandragore", "Persil", "Cochléaria", "Pâquerette", "Thon", "Pissenlit", "Sylvie", "Capillaire", "Frêne", "Plantoir", ], 7: [ "Primevère", "Platane", "Asperge", "Tulipe", "Poule", "Bette", "Bouleau", "Jonquille", "Aulne", "Couvoir", "Pervenche", "Charme", "Morille", "Hêtre", "Abeille", "Laitue", "Mélèze", "Ciguë", "Radis", "Ruche", "Gainier", "Romaine", "Marronnier", "Roquette", "Pigeon", "Lilas", "Anémone", "Pensée", "Myrtille", "Greffoir", ], 8: [ "Rose", "Chêne", "Fougère", "Aubépine", "Rossignol", "Ancolie", "Muguet", "Champignon", "Hyacinthe", "Râteau", "Rhubarbe", "Sainfoin", "Bâton d'or", "Chamerisier", "Ver à soie", "Consoude", "Pimprenelle", "Corbeille d'or", "Arroche", "Sarcloir", "Statice", "Fritillaire", "Bourrache", "Valériane", "Carpe", "Fusain", "Civette", "Buglosse", "Sénevé", "Houlette", ], 9: [ "Luzerne", "Hémérocalle", "Trèfle", "Angélique", "Canard", "Mélisse", "Fromental", "Martagon", "Serpolet", "Faux", "Fraise", "Bétoine", "Pois", "Acacia", "Caille", "Œillet", "Sureau", "Pavot", "Tilleul", "Fourche", "Barbeau", "Camomille", "Chèvrefeuille", "Caille-lait", "Tanche", "Jasmin", "Verveine", "Thym", "Pivoine", "Chariot", ], 10: [ "Seigle", "Avoine", "Oignon", "Véronique", "Mulet", "Romarin", "Concombre", "Échalote", "Absinthe", "Faucille", "Coriandre", "Artichaut", "Girofle", "Lavande", "Chamois", "Tabac", "Groseille", "Gesse", "Cerise", "Parc", "Menthe", "Cumin", "Haricot", "Orcanète", "Pintade", "Sauge", "Ail", "Vesce", "Blé", "Chalémie", ], 11: [ "Épeautre", "Bouillon blanc", "Melon", "Ivraie", "Bélier", "Prêle", "Armoise", "Carthame", "Mûre", "Arrosoir", "Panic", "Salicorne", "Abricot", "Basilic", "Brebis", "Guimauve", "Lin", "Amande", "Gentiane", "Écluse", "Carline", "Câprier", "Lentille", "Aunée", "Loutre", "Myrte", "Colza", "Lupin", "Coton", "Moulin", ], 12: [ "Prune", "Millet", "Lycoperdon", "Escourgeon", "Saumon", "Tubéreuse", "Sucrion", "Apocyn", "Réglisse", "Échelle", "Pastèque", "Fenouil", "Épine vinette", "Noix", "Truite", "Citron", "Cardère", "Nerprun", "Tagette", "Hotte", "Églantier", "Noisette", "Houblon", "Sorgho", "Écrevisse", "Bigarade", "Verge d'or", "Maïs", "Marron", "Panier", ], 13: [ "La Fête de la Vertu", "La Fête du Génie", "La Fête du Travail", "La Fête de l'Opinion", "La Fête des Récompenses", "La Fête de la Révolution", ], } convertdate-2.3.2/src/convertdate/data/positivist.py000066400000000000000000000302251401655151000226410ustar00rootroot00000000000000# -*- coding: utf-8 -*- DAY_NAMES = ( "Prometheus", "Hercules", "Orpheus", "Ulysses", "Lycurgus", "Romulus", "Numa", "Belus", "Sesostris", "Menu", "Cyrus", "Zoroaster", "The Druids", "Buddha", "Fuxi", "Laozi", "Mencius", "Theocrats of Tibet", "Theocrats of Japan", "Manco Cápac", "Confucius", "Abraham", "Samuel", "Solomon", "Isaiah", "St. John the Baptist", "Haroun-al-Raschid", "Muhammad", "Hesiod", "Tyrtéus", "Anacreon", "Pindar", "Sophocles", "Theocritus", "Aeschylus", "Scopas", "Zeuxis", "Ictinus", "Praxiteles", "Lysippus", "Apelles", "Phidias", "Aesop", "Plautus", "Terence", "Phaedrus", "Juvenal", "Lucian", "Aristophanes", "Ennius", "Lucretius", "Horace", "Tibullus", "Ovid", "Lucan", "Virgil", "Anaximander", "Anaximenes", "Heraclitus", "Anaxagoras", "Democritus", "Herodotus", "Thales", "Solon", "Xenophanes", "Empodocles", "Thucydides", "Archytas", "Apollonius of Tyana", "Pythagoras", "Aristippus", "Antisthenes", "Zeno", "Cicero", "Epictetus", "Tacitus", "Socrates", "Xenocrates", "Philo of Alexandria", "St. John the Evangelist", "St. Justin", "St. Clement of Alexandria", "Origen", "Plato", "Theophrastus", "Herophilus", "Erasistratus", "Celsus", "Galen", "Avicenna", "Hippocrates", "Euclid", "Aristéus", "Theodisius of Bithynia", "Hero", "Pappus", "Diophantus", "Apollonius", "Eudoxus", "Pytheas", "Aristarchus", "Eratos-thenes", "Ptolemy", "Albategnius", "Hipparchus", "Varro", "Columella", "Vitruvius", "Strabo", "Frontinus", "Plutarch", "Pliny the Elder", "Miltiades", "Leonidas", "Aristides", "Cimon", "Xenophon", "Phocion", "Themistocles", "Pericles", "Philip", "Demosthenes", "PtolemyLagus", "Philopoemen", "Polybius", "Alexander", "JuniusBrutus", "Camillus", "Fabricius", "Hannibal", "Paulus Aemilius", "Marius", "Scipio", "Augustus", "Vespasian", "Hadrian", "Antonius", "Papinian", "Alexander Severus", "Trajan", "St. Luke", "St. Cyprian", "St. Athanasius", "St. Jerome", "St. Ambrose", "St. Monica", "St. Augustine", "Constantine", "Theodosius", "St. Chrysostom", "St. Genevieve of Paris", "St. Pulcheria", "St. Gregory the Great", "Hildebrand", "St. Benedict", "St. Boniface", "St. Isidore of Seville", "Lanfranc", "Heloise", "the architects of the Middle Ages", "St. Bernard", "St. Francis Xavier", "St. Charles Borromeo", "St. Theresa", "St. Vincent de Paul", "Bourdaloue", "William Penn", "Bossuet", "Theodoric the Great", "Pelayo", "Otho the Great", "St. Henry", "Villers", "Don John of Austria", "Alfred", "Charles Martel", "El Cid", "Richard I", "Joan of Arc", "Albuquerque", "Bayard", "Godfrey", "St. Leo the Great", "Gerbert", "Peter the Hermit", "Suger", "Alexander III", "St. Francis of Assisi", "Innocent III", "St. Clotilde", "St. Bathilda", "St. Stephen of Hungary", "St. Elizabeth of Hungary", "Blanche of Castille", "St. Ferdinand III", "St. Louis", "the Troubadours", "Boccaccio", "Rabelais", "Cervantes", "La Fontain", "Defoe", "Aristo", "Leonardo da Vinci", "Michael Angelo", "Holbein", "Poussin", "Velásquez", "Teniers", "Raphael", "Froissart", "Camoens", "The Spanish Romancers", "Chateaubriand", "Walter Scott", "Manzoni", "Tasso", "Petrarca", "Thomas of Kempis", "Mademoiselle de Lafayette", "Fénélon", "Klopstock", "Byron", "Milton", "Marco Polo", "Jacques Coeur", "Vasco de Gama", "Napier", "Lacaille", "Cook", "Columbus", "Benvenuto Cellini", "Amontons", "Harrison", "Dollond", "Arkwright", "Conté", "Vaucanson", "Stevin", "Mariotte", "Papin", "Black", "Jouffroy", "Dalton", "Watt", "Bernard de Palissy", "Guglielmini", "Duhamel du Monceau", "Saussure", "Coulomb", "Carnot", "Montgolfier", "Lope de Vega", "Moreto", "Rojas", "Otway", "Lessing", "Goethe", "Calderon", "Tirso", "Vondel", "Racine", "Voltaire", "Metastasio", "Schiller", "Corneille", "Almarcon", "Mademoiselle de Motteville", "Mademoiselle de Sévigné", "Lesage", "Mademoiselle deStaal", "Fielding", "Moliere", "Pergolese", "Sacchini", "Gluck", "Beethoven", "Rossini", "Bellini", "Mozart", "Albertus Magnus", "Roger Bacon", "St. Bonaventura", "Ramus", "Montaigne", "Campanella", "St. Thomas Aquinas", "Hobbes", "Pascal", "Locke", "Vauvenargues", "Diderot", "Cabanis", "Lordbacon", "Grotius", "Fontenelle", "Vico", "Fréret", "Montesquieu", "Buffon", "Leibnitz", "Robertson", "Adam Smith", "Kant", "Condercet", "Joseph de Maistre", "Hegel", "Hume", "Marie de Molina", "Cosimo de Medici the Elder", "Philippe de Comines", "Isabella of Castille", "Charles V", "Henry Iv", "Louis Xi", "L'Hôpital", "Barneveldt", "Gustavus Adolphus", "De Witt", "Ruyter", "William III", "William the Silent", "Ximenes", "Sully", "Mazarin", "Colbert", "D'Aranda", "Turgot", "Richelieu", "Sidney", "Franklin", "Washington", "Jefferson", "Bolivar", "Francia", "Cromwell", "Copernicus", "Kepler", "Huyghens", "James Bernouilli", "Bradley", "Volta", "Galileo", "Vieta", "Wallis", "Clairaut", "Euler", "D'Alembert", "Lagrange", "Newton", "Bergmann", "Priestley", "Cavendish", "Guyton Morveau", "Berthollet", "Berzelius", "Lavoisier", "Harvey", "Boerhaave", "Linnaeus", "Haller", "Lamarck", "Broussais", "Gall", "the Dead", "Sainted Women", ) leap_day_replacements = { 0: "Cadmus", 1: "Theseus", 2: "Tiresias", 7: "Semiramus", 12: "Ossian", 19: "Tamehameha", 21: "Joseph", 23: "David", 26: "Abderrahman", 29: "Sappho", 32: "Euripides", 33: "Longus", 42: "Pilpay", 44: "Menander", 60: "Leucippus", 67: "Philolaus", 73: "Pliny the Younger", 74: "Arrian", 80: "St. Irenaeus", 82: "Tertullian", 89: "Averrhoes", 94: "Ctesibius", 98: "Aratus", 99: "Nearchus", 100: "Berosus", 101: "Sosigenes", 103: "Nasreddin", 117: "Epaminondas", 127: "Cincinnatus", 128: "Regulus", 131: "the Gracchi", 133: "Maecenas", 134: "Titus", 135: "Nerva", 136: "Marcus Aurelius", 137: "Ulpian", 138: "Aetius", 140: "St. James", 149: "St. Basil", 151: "Marcian", 154: "St. Anthony", 155: "St. Austin", 156: "St. Bruno", 157: "St. Anselm", 158: "Beatrice", 159: "St. Benezet", 161: "Ignatius Loyola", 162: "Fredrick Borromeo", 163: "St. Catharine of Siena", 164: "Abbé de l'Epée", 165: "Claude Fleury", 166: "George Fox", 170: "Henry the Fowler", 172: "La Valette", 173: "John Sobieski", 176: "Tancred", 177: "Saladin", 178: "Marina", 179: "Sir Walter Raleigh", 182: "Leo IV", 183: "Peter Damian", 185: "St. Eligius", 186: "Becket", 187: "St. Dominic", 190: "St. Mathilda of Tuscany", 191: "Mathias Corvinus", 194: "Alfonso X", 197: "Chaucer", 198: "Swift", 200: "Burns", 201: "Goldsmith", 203: "Titian", 204: "Paul Veronese", 205: "Rembrandt", 206: "Lesueuer", 207: "Murillo", 208: "Rubens", 210: "Joinville", 211: "Spenser", 214: "James Fenimore Cooper", 218: "Louis of Granada & Bunyan", 219: "Mademoiselle de Staël", 220: "St. Francis of Sales", 221: "Gessner", 222: "Élisa Mercœur & Shelly", 224: "Chardin", 225: "Gresham", 226: "Magellan", 227: "Briggs", 228: "Delambre", 229: "Tasman", 232: "Wheatstone", 233: "Pierre Leroy", 234: "Graham", 235: "Jacquard", 238: "Torricelli", 239: "Boyle", 240: "Worcester", 242: "Fulton", 243: "Thilorier", 246: "Riquet", 247: "Bourgelat", 248: "Bouguer", 249: "Borda", 250: "Vauban", 252: "Montalvan", 253: "Guillem de Castro", 254: "Guevara", 263: "Alfieri", 267: "Mademoiselle Roland", 268: "Lady Montagu", 269: "Sterne", 270: "Miss Edgeworth", 271: "Richardson", 273: "Palestrina", 274: "Grétry", 275: "Lully", 276: "Handel", 277: "Weber", 278: "Donizeti", 280: "John of Salisbury", 281: "Raymond Lully", 282: "Joachim", 283: "Nicholas of Cusa", 284: "Erasmus", 285: "Sir Thomas More", 287: "Spinoza", 288: "Giordano Bruno", 289: "Malebranche", 290: "Mademoiselle de Lambert", 291: "Duclos", 292: "George Leroy", 294: "Cujas", 295: "Maupertuis", 296: "Herder", 297: "Wincklemann", 298: "D'Aguesseau", 299: "Oken", 301: "Gibbon", 302: "Dunoyer", 303: "Fichte", 304: "Ferguson", 305: "Bonald", 306: "Sophie Germain", 310: "Guicciardini", 312: "Sixtus V", 323: "Oxenstiern", 324: "Walpole", 325: "Louis XIV", 326: "Pombal", 327: "Campomanes", 329: "Lambert", 330: "Hampden", 331: "Kosciusko", 332: "Madison", 333: "Toussaint L'Ouverture", 336: "Tycho Brahe", 337: "Halley", 338: "Varignon", 339: "John Bernouilli", 340: "Römer", 341: "Sauveur", 343: "Harriot", 344: "Fermat", 345: "Poinsot", 346: "Monge", 347: "Daniel Bernouilli", 348: "Joseph Fourier", 350: "Scheele", 351: "Davy", 353: "Geoffroy", 355: "Ritter", 357: "Charles Bell", 358: "Stahl & Barthez", 359: "Bernard de Jussieu", 360: "Félix Vicq-d'Azyr", 361: "Blainville", 362: "Morgagni", } DAY_NAMES_LEAP = [leap_day_replacements.get(i, x) for i, x in enumerate(DAY_NAMES)] FESTIVALS = { (1, 1): "the Great Being", (1, 7): "religion", (1, 14): "history", (1, 21): "nation", (1, 28): "community", (2, 7): "complete marriage", (2, 14): "chaste marriage", (2, 21): "unequal marriage", (2, 28): "subjective marriage", (3, 7): "natural fatherhood", (3, 14): "artificial fatherhood", (3, 21): "spiritual fatherhood", (3, 28): "temporal fatherhood", (4, 7): "natural filiation", (4, 14): "artificial filiation", (4, 21): "spiritual filiation", (4, 28): "temporal filiation", (5, 7): "natural brotherhood", (5, 14): "artificial brotherhood", (5, 21): "spiritual brotherhood", (5, 28): "temporal brotherhood", (6, 7): "complete permanent domesticity", (6, 14): "incomplete permanent domesticity", (6, 21): "complete passing domesticity", (6, 28): "incomplete passing domesticity", (7, 7): "animal gods", (7, 14): "fire gods", (7, 21): "sun gods", (7, 28): "war gods", (8, 7): "castes", (8, 14): "polytheistic arts", (8, 21): "polytheistic theory", (8, 28): "polytheistic society", (9, 7): "monotheistic theology", (9, 14): "Catholocism", (9, 21): "Islam", (9, 28): "metaphysics", (10, 7): "the mother", (10, 14): "the wife", (10, 21): "the daughter", (10, 28): "the sister", (11, 7): "artistic intellectuals", (11, 14): "scientific intellectuals", (11, 21): "secondary intellectual providence", (11, 28): "the elderly", (12, 7): "the bank", (12, 14): "commerce", (12, 21): "manufacturing", (12, 28): "agriculture", (13, 7): "inventors", (13, 14): "emotional labor", (13, 21): "meditation", (13, 28): "passive labor", (14, 1): "the Dead", (14, 2): "Sainted Women", } convertdate-2.3.2/src/convertdate/daycount.py000066400000000000000000000023171401655151000213420ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr from . import gregorian, julian, julianday class DayCount: '''A day count converter for the given epoch (in terms of Julian Day Count)''' def __init__(self, epoch): self.epoch = epoch def to_gregorian(self, dc): '''From day count to Gregorian (year, month, day) tuple''' return gregorian.from_jd(self.to_jd(dc)) def from_gregorian(self, year, month, day): return self.from_jd(gregorian.to_jd(year, month, day)) def to_jd(self, dc): return dc + self.epoch def from_jd(self, jdc): return jdc - self.epoch def from_julian(self, year, month, day): return self.from_jd(julian.to_jd(year, month, day)) def to_julian(self, dc): '''From day count to Julian (year, month, day) tuple''' return julian.from_jd(self.to_jd(dc)) def to_datetime(self, dc): return julianday.to_datetime(self.to_jd(dc)) def from_datetime(self, date): return self.from_jd(julianday.from_datetime(date)) convertdate-2.3.2/src/convertdate/dublin.py000066400000000000000000000014441401655151000207710ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr ''' The Dublin day count is a truncated `Julian day `__ with an epoch of noon on December 31, 1899. This is a convenience module, it uses :doc:`daycount` class for all functions. ''' from . import daycount EPOCH = 2415020 # Julian Day Count for Dublin Count 0 _dublin = daycount.DayCount(EPOCH) to_gregorian = _dublin.to_gregorian from_gregorian = _dublin.from_gregorian to_jd = _dublin.to_jd from_jd = _dublin.from_jd from_julian = _dublin.from_julian to_julian = _dublin.to_julian to_datetime = _dublin.to_datetime from_datetime = _dublin.from_datetime convertdate-2.3.2/src/convertdate/french_republican.py000066400000000000000000000261221401655151000231650ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr # Licensed under the MIT license """ The `French Republican calendar `__ was created during the heroic overthrow of the Ancien Regime. Leap year calculations in the French Republican calendar are a matter of dispute. By default, `convertdate` calculates leap years using the autumnal equinox. You can also use one of three more systematic methods proposed over the years. - Romme, a co-creator of the calendar, proposed leap years in years divisible by four, except for years divisible by 100. - Some concordances were drawn up in the 19th century that gave leap years every 4 years, in years that give a remainder of three when divided by four (19, 23, 27, etc...). - Von Mädler proposed leap years in years divisible by four, except for years divisible by 128. You can specify any of these three methods with the method keyword argument in `french_republican` conversion functions. .. code-block:: python from convertdate import french_republican french_republican.to_gregorian(20, 1, 1), method='romme') # (1811, 9, 23) french_republican.to_gregorian(20, 1, 1), method='continuous') # (1811, 9, 24) french_republican.to_gregorian(20, 1, 1), method='madler') # (1811, 9, 23) All the conversion methods correctly assign the leap years implemented while calendar was in use (3, 7, 11). """ from math import trunc from pymeeus.Sun import Sun from . import gregorian from .data.french_republican_days import french_republican_days # julian day (1792, 9, 22) EPOCH = 2375839.5 YEAR_EPOCH = 1791.0 DAYS_IN_YEAR = 365.0 MOIS = MONTHS = [ "Vendémiaire", "Brumaire", "Frimaire", "Nivôse", "Pluviôse", "Ventôse", "Germinal", "Floréal", "Prairial", "Messidor", "Thermidor", "Fructidor", "Sansculottides", ] LEAP_CYCLE_DAYS = 1461.0 # 365 * 4 + 1 LEAP_CYCLE_YEARS = 4.0 def leap(year, method=None): """ Determine if this is a leap year in the FR calendar using one of three methods: 4, 100, 128 (every 4th years, every 4th or 400th but not 100th, every 4th but not 128th) Methods: * 4 (concordance rule): leap every four years: 3, 7, 11, 15, ... etc * 100 (Romme's rule): leap every 4th and 400th year, but not 100th: 20, 24, ... 96, 104, ... 396, 400, 404 ... * 128 (von Mädler's rule): leap every 4th but not 128th: 20, 24, ... 124, 132, ... * equinox [default]: use calculation of the equinox to determine date, never returns a leap year """ method = method or 'equinox' if year in (3, 7, 11): return True if year < 15: return False if method in (4, 'continuous') or (year <= 16 and method in (128, 'madler', 4, 'continuous')): return year % 4 == 3 if method in (100, 'romme'): return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0 if method in (128, 'madler'): return year % 4 == 0 and year % 128 != 0 if method == 'equinox': # Is equinox on 366th day after (year, 1, 1) startjd = to_jd(year, 1, 1, method='equinox') if premier_da_la_annee(startjd + 367) - startjd == 366.0: return True else: raise ValueError("Unknown leap year method. Try: continuous, romme, madler or equinox") return False def _previous_fall_equinox(jd): '''Return the julian day count of the previous fall equinox.''' y, _, _ = gregorian.from_jd(jd) eqx = Sun.get_equinox_solstice(y, "autumn").jde() if eqx > jd: eqx = Sun.get_equinox_solstice(y - 1, "autumn").jde() return eqx def _next_fall_equinox(jd): '''Return the julian day count of the previous fall equinox.''' y, _, _ = gregorian.from_jd(jd) eqx = Sun.get_equinox_solstice(y, "autumn").jde() if eqx < jd: eqx = Sun.get_equinox_solstice(y + 1, "autumn").jde() return eqx def premier_da_la_annee(jd): """ Returns Julian day number containing fall equinox (first day of the FR year) of the current FR year. """ previous = trunc(_previous_fall_equinox(jd) - 0.5) + 0.5 if previous + 364 < jd: # test if current day is the equinox if the previous equinox was a long time ago nxt = trunc(_next_fall_equinox(jd) - 0.5) + 0.5 if nxt <= jd: return nxt return previous def to_jd(year, month, day, method=None): '''Obtain Julian day from a given French Revolutionary calendar date.''' method = method or 'equinox' if day < 1 or day > 30: raise ValueError("Invalid day for this calendar") if month > 13: raise ValueError("Invalid month for this calendar") if month == 13 and day > 5 + leap(year, method=method): raise ValueError("Invalid day for this month in this calendar") if method == 'equinox': return _to_jd_equinox(year, month, day) return _to_jd_schematic(year, month, day, method) def _to_jd_schematic(year, month, day, method): '''Calculate JD using various leap-year calculation methods''' y0, y1, y2, y3, y4, y5 = 0, 0, 0, 0, 0, 0 intercal_cycle_yrs, over_cycle_yrs, leap_suppression_yrs = None, None, None # Use the every-four-years method below year 16 (madler) or below 15 (romme) if (method in (100, 'romme') and year < 15) or (method in (128, 'madler') and year < 17): method = 4 if method in (4, 'continuous'): # Leap years: 15, 19, 23, ... y5 = -365 elif method in (100, 'romme'): year = year - 13 y5 = DAYS_IN_YEAR * 12 + 3 leap_suppression_yrs = 100.0 leap_suppression_days = 36524 # leap_cycle_days * 25 - 1 intercal_cycle_yrs = 400.0 intercal_cycle_days = 146097 # leap_suppression_days * 4 + 1 over_cycle_yrs = 4000.0 over_cycle_days = 1460969 # intercal_cycle_days * 10 - 1 elif method in (128, 'madler'): year = year - 17 y5 = DAYS_IN_YEAR * 16 + 4 leap_suppression_days = 46751 # 32 * leap_cycle_days - 1 leap_suppression_yrs = 128 else: raise ValueError("Unknown leap year method. Try: continuous, romme, madler or equinox") if over_cycle_yrs: y0 = trunc(year / over_cycle_yrs) * over_cycle_days year = year % over_cycle_yrs # count intercalary cycles in days (400 years long or None) if intercal_cycle_yrs: y1 = trunc(year / intercal_cycle_yrs) * intercal_cycle_days year = year % intercal_cycle_yrs # count leap suppresion cycles in days (100 or 128 years long) if leap_suppression_yrs: y2 = trunc(year / leap_suppression_yrs) * leap_suppression_days year = year % leap_suppression_yrs y3 = trunc(year / LEAP_CYCLE_YEARS) * LEAP_CYCLE_DAYS year = year % LEAP_CYCLE_YEARS # Adjust 'year' by one to account for lack of year 0 y4 = year * DAYS_IN_YEAR yj = y0 + y1 + y2 + y3 + y4 + y5 mj = (month - 1) * 30 return EPOCH + yj + mj + day - 1 def _to_jd_equinox(an, mois, jour): '''Return jd of this FR date, counting from the previous equinox.''' day_of_adr = (30 * (mois - 1)) + (jour - 1) equinoxe = _next_fall_equinox(gregorian.to_jd(an + YEAR_EPOCH, 1, 1)) return trunc(equinoxe - 0.5) + 0.5 + day_of_adr def from_jd(jd, method=None): """Calculate date in the French Revolutionary calendar from Julian day. The five or six "sansculottides" are considered a thirteenth month in the results of this function.""" method = method or 'equinox' if method == 'equinox': return _from_jd_equinox(jd) return _from_jd_schematic(jd, method) def _from_jd_schematic(jd, method): '''Convert from JD using various leap-year calculation methods''' if jd < EPOCH: raise ValueError("Can't convert days before the French Revolution") # days since Epoch J = trunc(jd) + 0.5 - EPOCH y0, y1, y2, y3, y4, y5 = 0, 0, 0, 0, 0, 0 intercal_cycle_days = leap_suppression_days = over_cycle_days = None # Use the every-four-years method below year 17 if (J <= DAYS_IN_YEAR * 12 + 3 and method in (100, 'romme')) or ( J <= DAYS_IN_YEAR * 17 + 4 and method in (128, 'madler') ): method = 4 # set p and r in Hatcher algorithm if method in (4, 'continuous'): # Leap years: 15, 19, 23, ... # Reorganize so that leap day is last day of cycle J = J + 365 y5 = -1 elif method in (100, 'romme'): # Year 15 is not a leap year # Year 16 is leap, then multiples of 4, not multiples of 100, yes multiples of 400 y5 = 12 J = J - DAYS_IN_YEAR * 12 - 3 leap_suppression_yrs = 100.0 leap_suppression_days = 36524 # LEAP_CYCLE_DAYS * 25 - 1 intercal_cycle_yrs = 400.0 intercal_cycle_days = 146097 # leap_suppression_days * 4 + 1 over_cycle_yrs = 4000.0 over_cycle_days = 1460969 # intercal_cycle_days * 10 - 1 y0 = trunc(J / over_cycle_days) * over_cycle_yrs J = J % over_cycle_days y1 = trunc(J / intercal_cycle_days) * intercal_cycle_yrs J = J % intercal_cycle_days elif method in (128, 'madler'): # Year 15 is a leap year, then year 20 and multiples of 4, not multiples of 128 y5 = 16 J = J - DAYS_IN_YEAR * 16 - 4 leap_suppression_yrs = 128 leap_suppression_days = 46751 # 32 * leap_cycle_days - 1 else: raise ValueError("Unknown leap year method. Try: continuous, romme, madler or equinox") if leap_suppression_days: y2 = trunc(J / leap_suppression_days) * leap_suppression_yrs J = J % leap_suppression_days y3 = trunc(J / LEAP_CYCLE_DAYS) * LEAP_CYCLE_YEARS if J % LEAP_CYCLE_DAYS == LEAP_CYCLE_DAYS - 1: J = 1460 else: J = J % LEAP_CYCLE_DAYS # 0 <= J <= 1460 # J needs to be 365 here on leap days ONLY y4 = trunc(J / DAYS_IN_YEAR) if J == DAYS_IN_YEAR * 4: y4 = y4 - 1 J = 365.0 else: J = J % DAYS_IN_YEAR year = y0 + y1 + y2 + y3 + y4 + y5 month = trunc(J / 30.0) J = J - month * 30 return trunc(year) + 1, month + 1, trunc(J) + 1 def _from_jd_equinox(jd): '''Calculate the FR day using the equinox as day 1''' jd = trunc(jd) + 0.5 equinoxe = premier_da_la_annee(jd) an = int(gregorian.from_jd(equinoxe)[0] - YEAR_EPOCH) mois = trunc((jd - equinoxe) / 30.0) + 1 jour = int((jd - equinoxe) % 30) + 1 return (an, mois, jour) def decade(jour): return trunc(jour / 100.0) + 1 def day_name(month, day): return french_republican_days[month][day - 1] def from_gregorian(year, month, day, method=None): return from_jd(gregorian.to_jd(year, month, day), method=method) def to_gregorian(an, mois, jour, method=None): return gregorian.from_jd(to_jd(an, mois, jour, method=method)) def format(an, mois, jour): """Convert a FR date into a string with the format DD MONTH YYYY.""" # pylint: disable=redefined-builtin return "{0} {1} {2}".format(jour, MOIS[mois - 1], an) convertdate-2.3.2/src/convertdate/gregorian.py000066400000000000000000000103551401655151000214720ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """ The Gregorian calendar was introduced by Pope Gregory XII in October 1582. It reforms the Julian calendar by adjusting leap year rules to reduce the drift versus solar year. The Gregorian calendar, like the Julian, does not include a year 0. However, for dates before 1, this module uses the astronomical convention of including a year 0 to simplify mathematical comparisons across epochs. To present a date in the standard convention, use the :meth:`gregorian.format` function. """ from calendar import isleap, monthrange from datetime import date from .utils import floor, jwday, monthcalendarhelper EPOCH = 1721425.5 INTERCALATION_CYCLE_YEARS = 400 INTERCALATION_CYCLE_DAYS = 146097 LEAP_SUPPRESSION_YEARS = 100 LEAP_SUPPRESSION_DAYS = 36524 LEAP_CYCLE_YEARS = 4 LEAP_CYCLE_DAYS = 1461 YEAR_DAYS = 365 HAVE_30_DAYS = (4, 6, 9, 11) HAVE_31_DAYS = (1, 3, 5, 7, 8, 10, 12) def legal_date(year, month, day): '''Check if this is a legal date in the Gregorian calendar''' if month == 2: daysinmonth = 29 if isleap(year) else 28 else: daysinmonth = 30 if month in HAVE_30_DAYS else 31 if not 0 < day <= daysinmonth: raise ValueError("Month {} doesn't have a day {}".format(month, day)) return True def to_jd2(year, month, day): '''Gregorian to Julian Day Count for years between 1801-2099''' # http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html legal_date(year, month, day) if month <= 2: year = year - 1 month = month + 12 a = floor(year / 100) b = floor(a / 4) c = 2 - a + b e = floor(365.25 * (year + 4716)) f = floor(30.6001 * (month + 1)) return c + day + e + f - 1524.5 def to_jd(year, month, day): '''Convert gregorian date to julian day count.''' legal_date(year, month, day) if month <= 2: leap_adj = 0 elif isleap(year): leap_adj = -1 else: leap_adj = -2 return ( EPOCH - 1 + (YEAR_DAYS * (year - 1)) + floor((year - 1) / LEAP_CYCLE_YEARS) + (-floor((year - 1) / LEAP_SUPPRESSION_YEARS)) + floor((year - 1) / INTERCALATION_CYCLE_YEARS) + floor((((367 * month) - 362) / 12) + leap_adj + day) ) def from_jd(jd): '''Return Gregorian date in a (Y, M, D) tuple''' wjd = floor(jd - 0.5) + 0.5 depoch = wjd - EPOCH quadricent = floor(depoch / INTERCALATION_CYCLE_DAYS) dqc = depoch % INTERCALATION_CYCLE_DAYS cent = floor(dqc / LEAP_SUPPRESSION_DAYS) dcent = dqc % LEAP_SUPPRESSION_DAYS quad = floor(dcent / LEAP_CYCLE_DAYS) dquad = dcent % LEAP_CYCLE_DAYS yindex = floor(dquad / YEAR_DAYS) year = quadricent * INTERCALATION_CYCLE_YEARS + cent * LEAP_SUPPRESSION_YEARS + quad * LEAP_CYCLE_YEARS + yindex if not (cent == 4 or yindex == 4): year += 1 yearday = wjd - to_jd(year, 1, 1) leap = isleap(year) if yearday < 58 + leap: leap_adj = 0 elif leap: leap_adj = 1 else: leap_adj = 2 month = floor((((yearday + leap_adj) * 12) + 373) / 367) day = int(wjd - to_jd(year, month, 1)) + 1 return (year, month, day) def month_length(year, month): '''Calculate the length of a month in the Gregorian calendar''' return monthrange(year, month)[1] def monthcalendar(year, month): ''' Return a list of lists that describe the calender for one month. Each inner list have 7 items, one for each weekday, starting with Sunday. These items are either ``None`` or an integer, counting from 1 to the number of days in the month. For Gregorian, this is very similiar to the built-in :meth:``calendar.monthcalendar``. ''' start_weekday = jwday(to_jd(year, month, 1)) monthlen = month_length(year, month) return monthcalendarhelper(start_weekday, monthlen) def format(year, month, day, format_string="%-d %B %y"): # pylint: disable=redefined-builtin epoch = '' if year <= 0: year = (year - 1) * -1 epoch = ' BCE' d = date(year, month, day) return d.strftime(format_string) + epoch convertdate-2.3.2/src/convertdate/hebrew.py000066400000000000000000000123721401655151000207720ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr from math import floor from . import gregorian from .utils import jwday, monthcalendarhelper EPOCH = 347995.5 HEBREW_YEAR_OFFSET = 3760 # Hebrew months NISAN = 1 IYYAR = 2 SIVAN = 3 TAMMUZ = 4 AV = 5 ELUL = 6 TISHRI = 7 HESHVAN = 8 KISLEV = 9 TEVETH = 10 SHEVAT = 11 ADAR = 12 VEADAR = 13 MONTHS = [ 'Nisan', 'Iyyar', 'Sivan', 'Tammuz', 'Av', 'Elul', 'Tishri', 'Heshvan', 'Kislev', 'Teveth', 'Shevat', 'Adar', 'Adar Bet', ] MONTHS_HEB = [ 'ניסן', 'אייר', 'סיוון', 'תמוז', 'אב', 'אלול', 'תשרי', 'חשוון', 'כסלו', 'טבת', 'שבט', 'אדר', 'אדר ב' ] def leap(year): # Is a given Hebrew year a leap year ? return (((year * 7) + 1) % 19) < 7 def year_months(year): '''How many months are there in a Hebrew year (12 = normal, 13 = leap)''' if leap(year): return VEADAR return ADAR def delay_1(year): '''Test for delay of start of the ecclesiastical new year to avoid improper weekdays for holidays.''' # Sunday, Wednesday, and Friday as start of the new year. months = floor(((235 * year) - 234) / 19) parts = 12084 + (13753 * months) day = (months * 29) + floor(parts / 25920) if ((3 * (day + 1)) % 7) < 3: day += 1 return day def delay_2(year): '''Check for delay in start of the ecclesiastical new year due to length of adjacent years''' last = delay_1(year - 1) present = delay_1(year) next_ = delay_1(year + 1) if next_ - present == 356: return 2 if present - last == 382: return 1 return 0 def year_days(year): '''How many days are in a Hebrew year ?''' return to_jd(year + 1, 7, 1) - to_jd(year, 7, 1) def month_days(year, month): '''How many days are in a given month of a given year''' if month > VEADAR: raise ValueError("Incorrect month index") # First of all, dispose of fixed-length 29 day months if month in (IYYAR, TAMMUZ, ELUL, TEVETH, VEADAR): return 29 # If it's not a leap year, Adar has 29 days if month == ADAR and not leap(year): return 29 # If it's Heshvan, days depend on length of year if month == HESHVAN and (year_days(year) % 10) != 5: return 29 # Similarly, Kislev varies with the length of year if month == KISLEV and (year_days(year) % 10) == 3: return 29 # Nope, it's a 30 day month return 30 def to_jd(year, month, day): months = year_months(year) jd = EPOCH + delay_1(year) + delay_2(year) + day + 1 if month < TISHRI: for m in range(TISHRI, months + 1): jd += month_days(year, m) for m in range(NISAN, month): jd += month_days(year, m) else: for m in range(TISHRI, month): jd += month_days(year, m) return int(jd) + 0.5 def from_jd(jd): jd = floor(jd) + 0.5 count = floor(((jd - EPOCH) * 98496.0) / 35975351.0) year = count - 1 i = count while jd >= to_jd(i, TISHRI, 1): i += 1 year += 1 if jd < to_jd(year, NISAN, 1): first = 7 else: first = 1 month = i = first while jd > to_jd(year, i, month_days(year, i)): i += 1 month += 1 day = int(jd - to_jd(year, month, 1)) + 1 return (year, month, day) def to_civil(year, month, day): """Convert a date in the ecclestical calendar (year starts in Nisan) to the civil calendar (year starts in Tishrei).""" if month >= TISHRI: year = year + 1 return year, month, day def to_jd_gregorianyear(gregorianyear, hebrew_month, hebrew_day): '''Returns the Gregorian date when a given Hebrew month and year within a given Gregorian year.''' # gregorian year is either 3760 or 3761 years less than hebrew year # we'll first try 3760 if conversion to gregorian isn't the same # year that was passed to this method, then it must be 3761. for y in (gregorianyear + HEBREW_YEAR_OFFSET, gregorianyear + HEBREW_YEAR_OFFSET + 1): jd = to_jd(y, hebrew_month, hebrew_day) gd = gregorian.from_jd(jd) if gd[0] == gregorianyear: break jd = None if not jd: # should never occur, but just incase... raise ValueError("Could not determine gregorian year") return gregorian.to_jd(gd[0], gd[1], gd[2]) def from_gregorian(year, month, day): return from_jd(gregorian.to_jd(year, month, day)) def to_gregorian(year, month, day): return gregorian.from_jd(to_jd(year, month, day)) def monthcalendar(year, month): start_weekday = jwday(to_jd(year, month, 1)) monthlen = month_days(year, month) return monthcalendarhelper(start_weekday, monthlen) def format(year, month, day, lang=None): """Convert a Hebrew date into a string with the format DD MONTH YYYY.""" # pylint: disable=redefined-builtin lang = lang or "en" if lang[0:2] == "he": month_name = MONTHS_HEB[month - 1] else: month_name = MONTHS[month - 1] return "{0} {1} {2}".format(day, month_name, year) convertdate-2.3.2/src/convertdate/holidays.py000066400000000000000000000364271401655151000213410ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """ Generate the dates of common North American and Jewish holidays. Jewish holidays begin the sunset before the first (secular) day of the holiday With the ``eve`` option set to ``True``, the day of this sunset is returned without the ``eve`` option, the (secular) day is returned. This is the default. """ import calendar import time from math import trunc from .utils import jwday, nth_day_of_month from . import gregorian, hebrew, islamic, julian # weekdays MON = 0 TUE = 1 WED = 2 THU = 3 FRI = 4 SAT = 5 SUN = 6 # months JAN = 1 FEB = 2 MAR = 3 APR = 4 MAY = 5 JUN = 6 JUL = 7 AUG = 8 SEP = 9 OCT = 10 NOV = 11 DEC = 12 def new_years(year, observed=None): '''Jan 1st, possibly observed on last day of previous year''' if observed: weekday = calendar.weekday(year, JAN, 1) if weekday == SAT: return (year - 1, DEC, 31) if weekday == SUN: return (year, JAN, 2) return (year, JAN, 1) def martin_luther_king_day(year): '''third monday in January''' return nth_day_of_month(3, MON, JAN, year) def lincolns_birthday(year): '''Feb 12''' return (year, FEB, 12) def valentines_day(year): '''feb 14th''' return (year, FEB, 14) def washingtons_birthday(year, observed=None): '''Feb 22, possibly observed on 3rd Monday in February''' if observed: return nth_day_of_month(3, MON, FEB, year) return (year, FEB, 22) def presidents_day(year): '''3rd Monday of Feb''' return nth_day_of_month(3, MON, FEB, year) def pulaski_day(year): '''1st monday in March''' return nth_day_of_month(1, MON, MAR, year) def easter(year, church=None): '''Calculate Easter in the given church according to the given calendar.''' church = church or "western" if church == "western": return _easter_western(year) if church == "orthodox": return julian.to_gregorian(*_easter_julian(year)) if church == "eastern": return julian.to_gregorian(*_easter_julian(year, mode="eastern")) raise ValueError("Unknown value for 'church'") def _easter_western(year): '''Calculate western easter''' # formula taken from http://aa.usno.navy.mil/faq/docs/easter.html c = trunc(year / 100) n = year - 19 * trunc(year / 19) k = trunc((c - 17) / 25) i = c - trunc(c / 4) - trunc((c - k) / 3) + (19 * n) + 15 i = i - 30 * trunc(i / 30) i = i - trunc(i / 28) * (1 - trunc(i / 28) * trunc(29 / (i + 1)) * trunc((21 - n) / 11)) j = year + trunc(year / 4) + i + 2 - c + trunc(c / 4) j = j - 7 * trunc(j / 7) L = i - j month = 3 + trunc((L + 40) / 44) day = L + 28 - 31 * trunc(month / 4) date = (year, int(month), int(day)) return date def _easter_julian(year, mode="dionysian"): '''Calculate Easter for the orthodox and eastern churches in the Julian calendar.''' # Uses Meeus's Julian algorithm. meton = year % 19 b = year % 4 c = year % 7 d = (19 * meton + 15) % 30 if mode == "eastern" and meton == 0: d = d + 1 e = (2 * b + 4 * c - d + 6) % 7 fmj = 113 + d # Easter full moon (days after -92 March) dmj = fmj + e + 1 # Easter Sunday (days after -92 March) esmj = trunc(dmj / 31) # month of Easter Sunday esdj = (dmj % 31) + 1 # day of Easter Sunday return year, esmj, esdj def may_day(year): return (year, MAY, 1) def mothers_day(year): '''2nd Sunday in May''' return nth_day_of_month(2, SUN, MAY, year) def memorial_day(year): '''last Monday in May''' return nth_day_of_month(0, MON, MAY, year) def fathers_day(year): '''3rd Sunday in June''' return nth_day_of_month(3, SUN, JUN, year) def juneteenth(year): '''19th of June''' return year, JUN, 19 def flag_day(year): '''June 14th''' return (year, JUN, 14) def independence_day(year, observed=None): """Independence Day in the United States, celebrated on July 4th. May be observed on the previous or following day if it occurs on a Saturday or Sunday. Arguments: year (int): Gregorian year observed (boolean): If ``True``, return the date of observation. """ day = 4 if observed: weekday = calendar.weekday(year, JUL, 4) if weekday == SAT: day = 3 if weekday == SUN: day = 5 return (year, JUL, day) def labor_day(year): '''first Monday in Sep''' return nth_day_of_month(1, MON, SEP, year) def indigenous_peoples_day(year, country='usa'): """Celebrated on the second Monday in October in the United States.""" if country == 'usa': return nth_day_of_month(2, MON, OCT, year) return (year, OCT, 12) def columbus_day(year, country='usa'): raise DeprecationWarning("columbus_day will be removed in a future release, use indigenous_peoples_day instead") return indigenous_peoples_day(year, country) def halloween(year): '''Halloween is celebrated on October 31st.''' return (year, OCT, 31) def election_day(year): """In most jurisdictions in the United States, Election day occurs on the first Tuesday in November.""" return nth_day_of_month(1, TUE, NOV, year) def veterans_day(year, observed=None): '''Nov 11, or the following closest weekday''' day = 11 if observed: weekday = calendar.weekday(year, NOV, 11) if weekday == SAT: day = 10 if weekday == SUN: day = 12 return (year, NOV, day) def rememberance_day(year): return veterans_day(year) def armistice_day(year): return veterans_day(year) def thanksgiving(year, country='usa'): """In the United States, Thanksgiving is celebrated on the last Thursday of November. In Canada, on the second Monday of October. Arguments: year (int): Gregorian year country (str): either ``'usa'`` (default) or ``'canada'`` """ if country == 'usa': if year in [1940, 1941]: return nth_day_of_month(3, THU, NOV, year) elif year == 1939: return nth_day_of_month(4, THU, NOV, year) return nth_day_of_month(0, THU, NOV, year) if country == 'canada': return nth_day_of_month(2, MON, OCT, year) raise NotImplementedError('Unsupported argument for country') def christmas_eve(year): '''The day before Christmas, or 24th of December.''' return (year, DEC, 24) def christmas(year, observed=None): """Christmas is celebrated on the 25th of December. For the purposes of business closings, it may be observed on the previous or following day if the 25th falls on a Saturday or Sunday, respectively. Arguments: year (int): Gregorian year observed (boolean): If ``True``, return the date of observation. """ day = 25 if observed: weekday = calendar.weekday(year, DEC, 25) if weekday == SAT: day = 24 if weekday == SUN: day = 26 return (year, DEC, day) def new_years_eve(year): """The last day of the Gregorian year, December. 31st.""" return (year, DEC, 31) def hanukkah(year, eve=None): jd = hebrew.to_jd_gregorianyear(year, hebrew.KISLEV, 25) if eve: jd = jd - 1 return gregorian.from_jd(jd) def purim(year, eve=None): if not hebrew.leap(year + hebrew.HEBREW_YEAR_OFFSET): jd = hebrew.to_jd_gregorianyear(year, hebrew.ADAR, 14) else: jd = hebrew.to_jd_gregorianyear(year, hebrew.VEADAR, 14) if eve: jd = jd - 1 return gregorian.from_jd(jd) def rosh_hashanah(year, eve=None): jd = hebrew.to_jd_gregorianyear(year, hebrew.TISHRI, 1) if eve: jd = jd - 1 return gregorian.from_jd(jd) def yom_kippur(year, eve=None): jd = hebrew.to_jd_gregorianyear(year, hebrew.TISHRI, 10) if eve: jd = jd - 1 return gregorian.from_jd(jd) def passover(year, eve=None): jd = hebrew.to_jd_gregorianyear(year, hebrew.NISAN, 15) if eve: jd = jd - 1 return gregorian.from_jd(jd) def shavuot(year, eve=None): jd = hebrew.to_jd_gregorianyear(year, hebrew.SIVAN, 6) if eve: jd = jd - 1 return gregorian.from_jd(jd) def sukkot(year, eve=None): """Sukkot, the Feast of Tabernacles or Festival of Shelters, is celebrated on the 15th of Tishri. """ jd = hebrew.to_jd_gregorianyear(year, hebrew.TISHRI, 15) if eve: jd = jd - 1 return gregorian.from_jd(jd) def shemini_azeret(year, eve=None): jd = hebrew.to_jd_gregorianyear(year, hebrew.TISHRI, 22) if eve: jd = jd - 1 return gregorian.from_jd(jd) def lag_baomer(year, eve=None): jd = hebrew.to_jd_gregorianyear(year, hebrew.IYYAR, 18) if eve: jd = jd - 1 return gregorian.from_jd(jd) def tu_beshvat(year, eve=None): """Tu BeShvat, the 'New Year of Trees', is celebrated on the 15th of Shevat.""" jd = hebrew.to_jd_gregorianyear(year, hebrew.SHEVAT, 15) if eve: jd = jd - 1 return gregorian.from_jd(jd) def tisha_bav(year, eve=None): """Tisha B'Av is a fast day generally celebrated on the 9th of Av, but sometimes postponed to the following day. """ jd = hebrew.to_jd_gregorianyear(year, hebrew.AV, 9) if jwday(jd) == SAT: jd = jd + 1 if eve: jd = jd - 1 return gregorian.from_jd(jd) # Mexican holidays def dia_constitucion(year, observed=True): """ Constitution Day, a public holiday in Mexico observed on the first Monday in February. """ if observed: return nth_day_of_month(1, MON, FEB, year) return (year, FEB, 5) def natalicio_benito_juarez(year, observed=True): """ Benito Juárez's Birthday, a public holiday in Mexico observed on the third Monday in March. """ if observed: return nth_day_of_month(3, MON, MAR, year) return (year, MAR, 21) def dia_independencia(year): """ Mexican independence day, observed on September 16. """ return year, SEP, 16 def dia_revolucion(year): """ Revolution Day, a public holiday in Mexico observed on the third Monday in November. """ return nth_day_of_month(3, MON, NOV, year) # Islamic holidays def ramadan(year, eve=None): """The first day of Ramadan, the month of fasting in the Islamic calendar.""" jd = islamic.to_jd_gregorianyear(year, 9, 1) if eve: jd = jd = 1 return gregorian.from_jd(jd) def ashura(year, eve=None): """Ashura is celebrated on the tenth day of Muharram, the first month in the Islamic calendar.""" jd = islamic.to_jd_gregorianyear(year, 1, 10) if eve: jd = jd = 1 return gregorian.from_jd(jd) def eid_alfitr(year, eve=None): """Eid al-Fitr, the 'Festival of Breaking the Fast' is celebrated the first day of the month of Shawwāl.""" jd = islamic.to_jd_gregorianyear(year, 10, 1) if eve: jd = jd = 1 return gregorian.from_jd(jd) def eid_aladha(year, eve=None): """Eid al-Adha, the 'Festival of the Sacrifice' begins on the tenth day of the month of Zū al-Ḥijjah.""" jd = islamic.to_jd_gregorianyear(year, 12, 10) if eve: jd = jd = 1 return gregorian.from_jd(jd) class Holidays: '''Convenience class for fetching many holidays in a given year.''' # pylint: disable=missing-function-docstring def __init__(self, year=None): self.year = year or time.localtime().tm_year def set_year(self, year): self.year = year def __repr__(self): return 'Holidays({})'.format(self.year) # the holidays... @property def christmas(self): return christmas(self.year, True) @property def christmas_eve(self): return christmas_eve(self.year) @property def thanksgiving(self): return thanksgiving(self.year) @property def new_years(self): return new_years(self.year, True) @property def new_years_eve(self): return new_years_eve(self.year) @property def independence_day(self): return independence_day(self.year, observed=True) @property def flag_day(self): return flag_day(self.year) @property def election_day(self): return election_day(self.year) @property def presidents_day(self): return presidents_day(self.year) @property def washingtons_birthday(self): return washingtons_birthday(self.year) @property def lincolns_birthday(self): return lincolns_birthday(self.year) @property def memorial_day(self): return memorial_day(self.year) @property def juneteenth(self): return juneteenth(self.year) @property def labor_day(self): return labor_day(self.year) @property def indigenous_peoples_day(self): return indigenous_peoples_day(self.year) @property def columbus_day(self): return indigenous_peoples_day(self.year) @property def veterans_day(self): return veterans_day(self.year, True) @property def valentines_day(self): return valentines_day(self.year) @property def halloween(self): return halloween(self.year) @property def mothers_day(self): return mothers_day(self.year) @property def fathers_day(self): return fathers_day(self.year) @property def pulaski_day(self): return pulaski_day(self.year) @property def easter(self): return easter(self.year) @property def martin_luther_king_day(self): return martin_luther_king_day(self.year) @property def hanukkah(self): return hanukkah(self.year, eve=False) @property def purim(self): return purim(self.year, eve=False) @property def rosh_hashanah(self): return rosh_hashanah(self.year, eve=False) @property def yom_kippur(self): return yom_kippur(self.year, eve=False) @property def passover(self): return passover(self.year, eve=False) @property def shavuot(self): return shavuot(self.year, eve=False) @property def sukkot(self): return sukkot(self.year, eve=False) @property def tu_beshvat(self): return tu_beshvat(self.year, eve=False) @property def shemini_azeret(self): return shemini_azeret(self.year, eve=False) @property def lag_baomer(self): return lag_baomer(self.year, eve=False) @property def tisha_bav(self): return tisha_bav(self.year, eve=False) @property def dia_constitucion(self): return dia_constitucion(self.year, observed=True) @property def natalicio_benito_juarez(self): return natalicio_benito_juarez(self.year, observed=True) @property def dia_independencia(self): return dia_independencia(self.year) @property def dia_revolucion(self): return dia_revolucion(self.year) @property def ramadan(self): return ramadan(self.year) @property def ashura(self): return ashura(self.year) @property def eid_alfitr(self): return eid_alfitr(self.year) @property def eid_aladha(self): return eid_aladha(self.year) if __name__ == '__main__': holiday = Holidays(time.localtime().tm_year) convertdate-2.3.2/src/convertdate/indian_civil.py000066400000000000000000000066531401655151000221530ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """ The Indian Civil calendar, also called the Indian national calendar, or the Shalivahana Shaka calendar, was instituted following independence. It consists of twelve months of 31 or 30 days, with a leap day every four years. """ from calendar import isleap from math import floor from . import gregorian from .utils import jwday, monthcalendarhelper # 0 = Sunday WEEKDAYS = ( "Ravivāra", "Somavāra", "Maṅgalavāra", "Budhavāra", "Guruvāra", "Śukravāra", "Śanivāra", ) MONTHS = ( "Chaitra", "Vaishākha", "Jyēshtha", "Āshādha", "Shrāvana", "Bhādrapada", "Āshwin", "Kārtika", "Mārgashīrsha", "Pausha", "Māgha", "Phālguna", ) HAVE_31_DAYS = (2, 3, 4, 5, 6) HAVE_30_DAYS = (7, 8, 9, 10, 11, 12) SAKA_EPOCH = 78 def to_jd(year, month, day): '''Obtain Julian day for Indian Civil date''' gyear = year + 78 leap = isleap(gyear) # // Is this a leap year ? # 22 - leap = 21 if leap, 22 non-leap start = gregorian.to_jd(gyear, 3, 22 - leap) if leap: caitra = 31 else: caitra = 30 if month == 1: jd = start + (day - 1) else: jd = start + caitra m = month - 2 m = min(m, 5) jd += m * 31 if month >= 8: m = month - 7 jd += m * 30 jd += day - 1 return jd def from_jd(jd): """Calculate Indian Civil date from Julian day Offset in years from Saka era to Gregorian epoch""" start = 80 # Day offset between Saka and Gregorian jd = floor(jd) + 0.5 gyear, _, _ = gregorian.from_jd(jd) # Gregorian date for Julian day leap = isleap(gyear) # Is this a leap year? # Tentative year in Saka era year = gyear - SAKA_EPOCH # JD at start of Gregorian year greg0 = gregorian.to_jd(gyear, 1, 1) yday = jd - greg0 # Day number (0 based) in Gregorian year if leap: caitra = 31 # Days in Caitra this year. else: caitra = 30 if yday < start: # Day is at the end of the preceding Saka year year -= 1 yday += caitra + (31 * 5) + (30 * 3) + 10 + start yday -= start if yday < caitra: month = 1 day = yday + 1 else: mday = yday - caitra if mday < 31 * 5: month = floor(mday / 31) + 2 day = (mday % 31) + 1 else: mday -= 31 * 5 month = floor(mday / 30) + 7 day = (mday % 30) + 1 return year, month, int(day) def from_gregorian(year, month, day): return from_jd(gregorian.to_jd(year, month, day)) def to_gregorian(year, month, day): return gregorian.from_jd(to_jd(year, month, day)) def month_length(year, month): if month in HAVE_31_DAYS or (month == 1 and isleap(year - SAKA_EPOCH)): return 31 return 30 def monthcalendar(year, month): start_weekday = jwday(to_jd(year, month, 1)) monthlen = month_length(year, month) return monthcalendarhelper(start_weekday, monthlen) def format(year, month, day): """Convert a Indian Civil date into a string with the format DD MONTH YYYY.""" # pylint: disable=redefined-builtin return "{0:d} {1:} {2:d}".format(day, MONTHS[month - 1], year) convertdate-2.3.2/src/convertdate/islamic.py000066400000000000000000000051021401655151000211300ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """Convert dates between the Hijri calendar and the Gregorian and Julian calendars.""" from . import gregorian from .utils import ceil, floor, jwday, monthcalendarhelper EPOCH = 1948439.5 WEEKDAYS = ("al-'ahad", "al-'ithnayn", "ath-thalatha'", "al-'arb`a'", "al-khamis", "al-jum`a", "as-sabt") MONTHS = [ "al-Muḥarram", "Ṣafar", "Rabīʿ al-ʾAwwal", "Rabīʿ ath-Thānī,", "Jumādā al-ʾAwwal,", "Jumādā ath-Thāniyah,", "Rajab", "Shaʿbān", "Ramaḍān", "Shawwāl", "Zū al-Qaʿdah", "Zū al-Ḥijjah", ] HAS_29_DAYS = (2, 4, 6, 8, 10) HAS_30_DAYS = (1, 3, 5, 7, 9, 11) def leap(year): '''Is a given year a leap year in the Islamic calendar''' return (((year * 11) + 14) % 30) < 11 def to_jd(year, month, day): '''Determine Julian day count from Islamic date''' return (day + ceil(29.5 * (month - 1)) + (year - 1) * 354 + floor((3 + (11 * year)) / 30) + EPOCH) - 1 def from_jd(jd): '''Calculate Islamic date from Julian day''' jd = floor(jd) + 0.5 year = floor(((30 * (jd - EPOCH)) + 10646) / 10631) month = min(12, ceil((jd - (29 + to_jd(year, 1, 1))) / 29.5) + 1) day = int(jd - to_jd(year, month, 1)) + 1 return (year, month, day) def to_jd_gregorianyear(gregorianyear, islamic_month, islamic_day): # Gregorian year is either 578 or 623 years greater than Islamic year # we'll first try 622 if conversion to gregorian isn't the same # year that was passed to this method, then it must be 623. jan1 = gregorian.to_jd(gregorianyear, 1, 1) yi, mi, _ = from_jd(jan1) if mi > islamic_month: yi = yi + 1 return to_jd(yi, islamic_month, islamic_day) def from_gregorian(year, month, day): return from_jd(gregorian.to_jd(year, month, day)) def to_gregorian(year, month, day): return gregorian.from_jd(to_jd(year, month, day)) def month_length(year, month): if month in HAS_30_DAYS or (month == 12 and leap(year)): return 30 return 29 def monthcalendar(year, month): start_weekday = jwday(to_jd(year, month, 1)) monthlen = month_length(year, month) return monthcalendarhelper(start_weekday, monthlen) def format(year, month, day): """Convert an Islamic date into a string with the format DD MONTH YYYY.""" # pylint: disable=redefined-builtin return "{0:d} {1:} {2:d}".format(day, MONTHS[month - 1], year) convertdate-2.3.2/src/convertdate/iso.py000066400000000000000000000024371401655151000203110ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr from calendar import isleap from datetime import date from math import trunc from . import gregorian, ordinal from .utils import jwday, n_weeks MON = 0 TUE = 1 WED = 2 THU = 3 FRI = 4 SAT = 5 SUN = 6 def to_jd(year, week, day): '''Return Julian day count of given ISO year, week, and day''' return day + n_weeks(SUN, gregorian.to_jd(year - 1, 12, 28), week) def from_jd(jd): '''Return tuple of ISO (year, week, day) for Julian day''' return from_gregorian(*gregorian.from_jd(jd)) def weeks_per_year(year): '''Number of ISO weeks in a year''' # 53 weeks: any year starting on Thursday and any leap year starting on Wednesday jan1 = jwday(gregorian.to_jd(year, 1, 1)) if jan1 == THU or (jan1 == WED and isleap(year)): return 53 return 52 def from_gregorian(year, month, day): return date(year, month, day).isocalendar() def to_gregorian(year, week, day): return gregorian.from_jd(to_jd(year, week, day)) def format(year, week, day): # pylint: disable=redefined-builtin return "{}-W{:02}-{}".format(year, week, day) convertdate-2.3.2/src/convertdate/julian.py000066400000000000000000000074621401655151000210040ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """ The Julian calendar was implemented by Julius Caesar in 45 BC as a reformation of the Roman calendar. It is designed to follow the solar year, with a standard year of 365 days and a quadrennial leap year with an intercalary day (29 February). For the first several centuries of its use, the Julian calendar did not have a single year-numbering system. The Romans initially specific years with the names of political leaders. Later on, different areas employed different era with various epochs. Between the sixth and eighth centuries, western Europe adopted the Anno Domini convention. This numbering system does not include a year 0. However, for dates before 1, this module uses the astronomical convention of including a year 0 to simplify mathematical comparisons across epochs. To present a date in the standard convention, use the :meth:`julian.format` function. """ from .gregorian import from_jd as gregorian_from_jd from .gregorian import to_jd as gregorian_to_jd from .utils import floor, jwday, monthcalendarhelper J0000 = 1721424.5 # Julian date of Gregorian epoch: 0000-01-01 J1970 = 2440587.5 # Julian date at Unix epoch: 1970-01-01 JMJD = 2400000.5 # Epoch of Modified Julian Date system JULIAN_EPOCH = 1721423.5 J2000 = 2451545.0 # Julian day of J2000 epoch JULIANCENTURY = 36525.0 # Days in Julian century HAVE_30_DAYS = (4, 6, 9, 11) HAVE_31_DAYS = (1, 3, 5, 7, 8, 10, 12) def leap(year): return year % 4 == 0 def month_length(year, month): if month == 2: daysinmonth = 29 if leap(year) else 28 else: daysinmonth = 30 if month in HAVE_30_DAYS else 31 return daysinmonth def legal_date(year, month, day): '''Check if this is a legal date in the Julian calendar''' daysinmonth = month_length(year, month) if not 0 < day <= daysinmonth: raise ValueError("Month {} doesn't have a day {}".format(month, day)) return True def from_jd(jd): '''Calculate Julian calendar date from Julian day''' jd += 0.5 a = floor(jd) b = a + 1524 c = floor((b - 122.1) / 365.25) d = floor(365.25 * c) e = floor((b - d) / 30.6001) if e < 14: month = floor(e - 1) else: month = floor(e - 13) if month > 2: year = floor(c - 4716) else: year = floor(c - 4715) day = b - d - floor(30.6001 * e) return (year, month, day) def to_jd(year, month, day): '''Convert to Julian day using astronomical years (0 = 1 BC, -1 = 2 BC)''' legal_date(year, month, day) # Algorithm as given in Meeus, Astronomical Algorithms, Chapter 7, page 61 if month <= 2: year -= 1 month += 12 return (floor((365.25 * (year + 4716))) + floor((30.6001 * (month + 1))) + day) - 1524.5 def from_gregorian(year, month, day): '''Convert a Gregorian date to a Julian date.''' return from_jd(gregorian_to_jd(year, month, day)) def to_gregorian(year, month, day): '''Convert a Julian date to a Gregorian date.''' return gregorian_from_jd(to_jd(year, month, day)) def monthcalendar(year, month): ''' Returns a matrix representing a month’s calendar. Each row represents a week; days outside of the month are represented by zeros. Each week begins with Sunday. ''' start_weekday = jwday(to_jd(year, month, 1)) monthlen = month_length(year, month) return monthcalendarhelper(start_weekday, monthlen) def format(year, month, day, format_string="%-d %B %y"): # pylint: disable=redefined-builtin epoch = '' if year <= 0: year = (year - 1) * -1 epoch = ' BCE' d = date(year, month, day) return d.strftime(format_string) + epoch convertdate-2.3.2/src/convertdate/julianday.py000066400000000000000000000042351401655151000214750ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """ The `Julian day `__ is a continuous count of days since the beginning of the Julian era on January 1, 4713 BC. """ from datetime import datetime from pytz import utc from . import gregorian, julian def to_datetime(jdc): '''Return a datetime for the input floating point julian day count''' year, month, day = gregorian.from_jd(jdc) # in jdc: 0.0 = noon, 0.5 = midnight # the 0.5 changes it to 0.0 = midnight, 0.5 = noon frac = (jdc + 0.5) % 1 hours = int(24 * frac) mfrac = frac * 24 - hours mins = int(60 * round(mfrac, 6)) sfrac = mfrac * 60 - mins secs = int(60 * round(sfrac, 6)) msfrac = sfrac * 60 - secs # down to ms, which are 1/1000 of a second ms = int(1000 * round(msfrac, 6)) return datetime(year, month, day, int(hours), int(mins), int(secs), int(ms), tzinfo=utc) def from_datetime(dt): '''Convert from ``datetime`` to julian day count.''' # take account of offset (if there isn't one, act like it's utc) try: dt = dt + dt.utcoffset() except TypeError: # Assuming UTC pass jdc = gregorian.to_jd(dt.year, dt.month, dt.day) hfrac = dt.hour / 24.0 mfrac = round(dt.minute / (24.0 * 60), 5) sfrac = round(dt.second / (24.0 * 60 * 60), 5) msfrac = dt.microsecond / (24.0 * 60 * 60 * 1000) return jdc + hfrac + mfrac + sfrac + msfrac def to_gregorian(jdc): '''Convert from julian day count to Gregorian date.''' return gregorian.from_jd(jdc) def from_gregorian(year, month, day): '''Convert from Gregorian ``year``, ``month`` and ``day`` to julian day count.''' return gregorian.to_jd(year, month, day) def to_julian(jdc): '''Convert from julian day count to Julian date.''' return julian.from_jd(jdc) def from_julian(year, month, day): '''Convert from Julian ``year``, ``month`` and ``day`` to julian day count.''' return julian.to_jd(year, month, day) convertdate-2.3.2/src/convertdate/mayan.py000066400000000000000000000204761401655151000206270ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr import itertools from math import trunc from . import gregorian from .utils import amod EPOCH = 584282.5 HAAB = [ "Pop", "Wo'", "Zip", "Sotz'", "Sek", "Xul", "Yaxk'in'", "Mol", "Ch'en", "Yax", "Sak'", "Keh", "Mak", "K'ank'in", "Muwan'", "Pax", "K'ayab", "Kumk'u", "Wayeb'", ] HAAB_TRANSLATIONS = [ "Mat", "Frog", "Red", "Bat", "Bee", "Dog", "First Sun", "Water", "Cave", "Green", "White", "Red", "Encloser", "Yellow Sun", "Screech Owl", "Planting Time", "Turtle", "Ripe Corn", "Nameless", ] TZOLKIN = [ "Imix'", "Ik'", "Ak'b'al", "K'an", "Chikchan", "Kimi", "Manik'", "Lamat", "Muluk", "Ok", "Chuwen", "Eb'", "B'en", "Ix", "Men", "K'ib'", "Kab'an", "Etz'nab'", "Kawak", "Ajaw", ] TZOLKIN_TRANSLATIONS = [ "Water", "Wind", "Darkness", "Net", "Feathered Serpent", "Death", "Deer", "Seed", "Jade", "Dog", "Thread", "Path", "Maize", "Tiger", "Bird", "Will", "Wisdom", "Obsidian Knife", "Thunder", "Sun", ] def to_jd(baktun, katun, tun, uinal, kin): '''Determine Julian day from Mayan long count''' return EPOCH + (baktun * 144000) + (katun * 7200) + (tun * 360) + (uinal * 20) + kin def from_jd(jd): '''Calculate Mayan long count from Julian day''' d = jd - EPOCH if d < 0: raise ValueError("Day out of range") baktun = trunc(d / 144000) d = d % 144000 katun = trunc(d / 7200) d = d % 7200 tun = trunc(d / 360) d = d % 360 uinal = trunc(d / 20) kin = int((d % 20)) return (baktun, katun, tun, uinal, kin) def to_gregorian(baktun, katun, tun, uinal, kin): jd = to_jd(baktun, katun, tun, uinal, kin) return gregorian.from_jd(jd) def from_gregorian(year, month, day): jd = gregorian.to_jd(year, month, day) return from_jd(jd) def to_haab(jd): '''Determine Mayan Haab "month" and day from Julian day''' # Number of days since the start of the long count lcount = trunc(jd) + 0.5 - EPOCH # Long Count begins 348 days after the start of the cycle day = (lcount + 348) % 365 count = day % 20 month = trunc(day / 20) return int(count), HAAB[month] def to_tzolkin(jd): '''Determine Mayan Tzolkin "month" and day from Julian day''' lcount = trunc(jd) + 0.5 - EPOCH day = amod(lcount + 4, 13) name = amod(lcount + 20, 20) return int(day), TZOLKIN[int(name) - 1] def lc_to_haab(baktun, katun, tun, uinal, kin): jd = to_jd(baktun, katun, tun, uinal, kin) return to_haab(jd) def lc_to_tzolkin(baktun, katun, tun, uinal, kin): jd = to_jd(baktun, katun, tun, uinal, kin) return to_tzolkin(jd) def lc_to_haab_tzolkin(baktun, katun, tun, uinal, kin): jd = to_jd(baktun, katun, tun, uinal, kin) dates = to_tzolkin(jd) + to_haab(jd) return "{0} {1} {2} {3}".format(*dates) def translate_haab(h): return dict(list(zip(HAAB, HAAB_TRANSLATIONS))).get(h) def translate_tzolkin(tz): return dict(list(zip(TZOLKIN, TZOLKIN_TRANSLATIONS))).get(tz) def _haab_count(day, month): '''Return the count of the given haab in the cycle. e.g. 0 Pop == 1, 5 Wayeb' == 365''' if day < 0 or day > 19: raise IndexError("Invalid day number") try: i = HAAB.index(month) except ValueError as err: raise ValueError("'{0}' is not a valid Haab' month".format(month)) from err return min(i * 20, 360) + day def _tzolkin_from_count(count): number = amod(count, 13) name = TZOLKIN[count % 20 - 1] return number, name def _tzolkin_count(day, name): if day < 1 or day > 13: raise IndexError("Invalid day number") days = set(x + day for x in range(0, 260, 13)) try: n = 1 + TZOLKIN.index(name) except ValueError as err: raise ValueError("'{0}' is not a valid Tzolk'in day name".format(name)) from err names = set(y + n for y in range(0, 260, 20)) return days.intersection(names).pop() def tzolkin_generator(number=None, name=None): """For a given tzolkin name/number combination, return a generator that gives cycle, starting with the input""" # By default, it will start at the beginning number = number or 13 name = name or "Ajaw" if number > 13: raise ValueError("Invalid day number") if name not in TZOLKIN: raise ValueError("Invalid day name") count = _tzolkin_count(number, name) ranged = itertools.chain(list(range(count, 260)), list(range(1, count))) for i in ranged: yield _tzolkin_from_count(i) def longcount_generator(baktun, katun, tun, uinal, kin): '''Generate long counts, starting with input''' j = to_jd(baktun, katun, tun, uinal, kin) while True: yield from_jd(j) j = j + 1 def next_haab(month, jd): '''For a given haab month and a julian day count, find the next start of that month on or after the JDC''' if jd < EPOCH: raise IndexError("Input day is before Mayan epoch.") hday, hmonth = to_haab(jd) if hmonth == month: days = 1 - hday else: count1 = _haab_count(hday, hmonth) count2 = _haab_count(1, month) # Find number of days between haab of given jd and desired haab days = (count2 - count1) % 365 # add in the number of days and return new jd return jd + days def next_tzolkin(tzolkin, jd): '''For a given tzolk'in day, and a julian day count, find the next occurrance of that tzolk'in after the date''' if jd < EPOCH: raise IndexError("Input day is before Mayan epoch.") count1 = _tzolkin_count(*to_tzolkin(jd)) count2 = _tzolkin_count(*tzolkin) add_days = (count2 - count1) % 260 return jd + add_days def next_tzolkin_haab(tzolkin, haab, jd): '''For a given haab-tzolk'in combination, and a Julian day count, find the next occurrance of the combination after the date''' # get H & T of input jd, and their place in the 18,980 day cycle haabcount = _haab_count(*to_haab(jd)) haab_desired_count = _haab_count(*haab) # How many days between the input day and the desired day? haab_days = (haab_desired_count - haabcount) % 365 possible_haab = set(h + haab_days for h in range(0, 18980, 365)) tzcount = _tzolkin_count(*to_tzolkin(jd)) tz_desired_count = _tzolkin_count(*tzolkin) # How many days between the input day and the desired day? tzolkin_days = (tz_desired_count - tzcount) % 260 possible_tz = set(t + tzolkin_days for t in range(0, 18980, 260)) try: return possible_tz.intersection(possible_haab).pop() + jd except KeyError: raise IndexError("That Haab'-Tzolk'in combination isn't possible") def month_length(month): """Not the actual length of the month, but accounts for the 5 unlucky/nameless days""" if month == "Wayeb'": return 5 else: return 20 def haab_monthcalendar(baktun=None, katun=None, tun=None, uinal=None, kin=None, jdc=None): '''For a given long count, return a calender of the current haab month, divided into tzolkin "weeks"''' if not jdc: jdc = to_jd(baktun, katun, tun, uinal, kin) haab_number, haab_month = to_haab(jdc) first_j = jdc - haab_number + 1 tzolkin_start_number, tzolkin_start_name = to_tzolkin(first_j) gen_longcount = longcount_generator(*from_jd(first_j)) gen_tzolkin = tzolkin_generator(tzolkin_start_number, tzolkin_start_name) # 13 day long tzolkin 'weeks' lpad = tzolkin_start_number - 1 rpad = 13 - (tzolkin_start_number + 19 % 13) monlen = month_length(haab_month) days = [None] * lpad + list(range(1, monlen + 1)) + rpad * [None] def g(x, generate): if x is None: return None return next(generate) return [[(k, g(k, gen_tzolkin), g(k, gen_longcount)) for k in days[i : i + 13]] for i in range(0, len(days), 13)] def haab_monthcalendar_prospective(haabmonth, jdc): '''Give the monthcalendar for the next occurance of given haab month after jdc''' return haab_monthcalendar(jdc=next_haab(haabmonth, jdc)) convertdate-2.3.2/src/convertdate/ordinal.py000066400000000000000000000027521401655151000211470ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """ The `ordinal date ` specifies the day of year as a number between 1 and 366. Ordinal dates are represented by a tuple: ``(year, dayofyear)`` """ from calendar import isleap from math import trunc from . import gregorian def to_jd(year, dayofyear): '''Return Julian day count of given ordinal date.''' return gregorian.to_jd(year, 1, 1) + dayofyear - 1 def from_jd(jd): '''Convert a Julian day count to an ordinal date.''' year, _, _ = gregorian.from_jd(jd) return year, round(jd - gregorian.to_jd(year, 1, 1) + 1) def from_gregorian(year, month, day): """Convert a Gregorian date to an ordinal date.""" m = month + 1 if m <= 3: m = m + 12 leap = isleap(year) t = trunc(30.6 * m) + day - 122 + 59 + leap if t > 365 + leap: t = t - 365 - leap return year, t def to_gregorian(year, dayofyear): """Convert an ordinal date to a Gregorian date.""" leap = isleap(year) if dayofyear < 59 + leap: leap_adj = 0 elif leap: leap_adj = 1 else: leap_adj = 2 month = trunc((((dayofyear - 1 + leap_adj) * 12) + 373) / 367) startofmonth = from_gregorian(year, month, 1) return year, month, dayofyear - startofmonth[1] + 1 convertdate-2.3.2/src/convertdate/persian.py000066400000000000000000000100101401655151000211420ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr """ The modern Persian calendar, or the Solar Hijri calendar, was adopted in 1911. It consists of twelve months of 30 or 31 days. The new year always falls on the March equinox. """ from math import floor, trunc from pymeeus.Sun import Sun from pymeeus.Epoch import Epoch from . import gregorian from .utils import ceil, jwday, monthcalendarhelper, TROPICALYEAR EPOCH = 1948320.5 WEEKDAYS = ("Doshanbeh", "Seshhanbeh", "Chaharshanbeh", "Panjshanbeh", "Jomeh", "Shanbeh", "Yekshanbeh") MONTHS = [ "Farvardin", "Ordibehesht", "Khordad", "Tir", "Mordad", "Shahrivar", "Mehr", "Aban", "Azar", "Dey", "Bahman", "Esfand", ] HAS_31_DAYS = (1, 2, 3, 4, 5, 6) HAS_30_DAYS = (7, 8, 9, 10, 11) def leap(year): '''Is a given year a leap year in the Persian calendar ?''' return (to_jd(year + 1, 1, 1) - to_jd(year, 1, 1)) > 365 def equinox_jd(gyear): """Calculate Julian day during which the March equinox, reckoned from the Tehran meridian, occurred for a given Gregorian year.""" mean_jd = Sun.get_equinox_solstice(gyear, target='spring') deltat_jd = mean_jd - Epoch.tt2ut(gyear, 3) / (24 * 60 * 60.) # Apparent JD in universal time apparent_jd = deltat_jd + (Sun.equation_of_time(deltat_jd)[0] / (24 * 60.)) # Correct for meridian of Tehran + 52.5 degrees return floor(apparent_jd.jde() + (52.5 / 360)) def last_equinox_jd(jd): """Return the Julian date of spring equinox immediately preceeding the given Julian date.""" guessyear = gregorian.from_jd(jd)[0] last_equinox = equinox_jd(guessyear) while last_equinox > jd: guessyear = guessyear - 1 last_equinox = equinox_jd(guessyear) next_equinox = last_equinox - 1 while not (last_equinox <= jd and jd < next_equinox): last_equinox = next_equinox guessyear = guessyear + 1 next_equinox = equinox_jd(guessyear) return last_equinox def jd_to_pyear(jd): """ Determine the year in the Persian astronomical calendar in which a given Julian day falls. Returns: tuple - (Persian year, Julian day number containing equinox for this year) """ lasteq = last_equinox_jd(jd) return round((lasteq - EPOCH) / TROPICALYEAR) + 1, lasteq def to_jd(year, month, day): '''Determine Julian day from Persian date''' guess = (EPOCH - 1) + (TROPICALYEAR * ((year - 1) - 1)) y0, equinox = year - 1, 0 while y0 < year: y0, equinox = jd_to_pyear(guess) guess = equinox + TROPICALYEAR + 2 if month <= 7: m = (month - 1) * 31 else: m = ((month - 1) * 30) + 6 return equinox + m + day + 0.5 def from_jd(jd): '''Calculate Persian date from Julian day''' jd = floor(jd) + 0.5 equinox = last_equinox_jd(jd) year = round((equinox - EPOCH) / TROPICALYEAR) + 1 yday = jd - (equinox + 0.5) if yday <= 186: month = ceil(yday / 31) day = yday - ((month - 1) * 31) else: month = ceil((yday - 6) / 30) day = yday - ((month - 1) * 30) - 6 return int(year), int(month), int(day) def from_gregorian(year, month, day): return from_jd(gregorian.to_jd(year, month, day)) def to_gregorian(year, month, day): return gregorian.from_jd(to_jd(year, month, day)) def month_length(year, month): if month in HAS_30_DAYS or (month == 12 and leap(year)): return 30 if month in HAS_31_DAYS: return 31 return 29 def monthcalendar(year, month): start_weekday = jwday(to_jd(year, month, 1)) monthlen = month_length(year, month) return monthcalendarhelper(start_weekday, monthlen) def format(year, month, day): """Convert a Persian date into a string with the format DD MONTH YYYY.""" # pylint: disable=redefined-builtin return "{0:d} {1:} {2:d}".format(day, MONTHS[month - 1], year) convertdate-2.3.2/src/convertdate/positivist.py000066400000000000000000000077151401655151000217400ustar00rootroot00000000000000# -*- coding: utf-8 -*- ''' Convert between Gregorian/Julian Day and Comte's Positivist calendar. The Positivist calendar has 13 months and one or two festival days. Festival days are given as the fourteenth month. The Gregorian date 1789-01-01 is Positivist 0001-01-01. ''' # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr from calendar import isleap from . import gregorian from .data import positivist as data from .utils import floor # Positivist calendar has 13 28-day months and one festival day EPOCH = 2374479.5 YEAR_EPOCH = 1789 DAYS_IN_YEAR = 365 MONTHS = ( 'Moses', 'Homer', 'Aristotle', 'Archimedes', 'Caesar', 'Saint Paul', 'Charlemagne', 'Dante', 'Gutenberg', 'Shakespeare', 'Descartes', 'Frederic', 'Bichat', '', ) def legal_date(year, month, day): '''Checks if a given date is a legal positivist date''' try: assert year >= 1 assert 0 < month <= 14 assert 0 < day <= 28 if month == 14: if isleap(year + YEAR_EPOCH - 1): assert day <= 2 else: assert day == 1 except AssertionError as err: raise ValueError("Invalid Positivist date: ({}, {}, {})".format(year, month, day)) from err return True def to_jd(year, month, day): '''Convert a Positivist date to Julian day count.''' legal_date(year, month, day) gyear = year + YEAR_EPOCH - 1 return ( gregorian.EPOCH - 1 + (365 * (gyear - 1)) + floor((gyear - 1) / 4) + (-floor((gyear - 1) / 100)) + floor((gyear - 1) / 400) + (month - 1) * 28 + day ) def from_jd(jd): '''Convert a Julian day count to Positivist date.''' try: assert jd >= EPOCH except AssertionError as err: raise ValueError('Invalid Julian day') from err depoch = floor(jd - 0.5) + 0.5 - gregorian.EPOCH quadricent = floor(depoch / gregorian.INTERCALATION_CYCLE_DAYS) dqc = depoch % gregorian.INTERCALATION_CYCLE_DAYS cent = floor(dqc / gregorian.LEAP_SUPPRESSION_DAYS) dcent = dqc % gregorian.LEAP_SUPPRESSION_DAYS quad = floor(dcent / gregorian.LEAP_CYCLE_DAYS) dquad = dcent % gregorian.LEAP_CYCLE_DAYS yindex = floor(dquad / gregorian.YEAR_DAYS) year = ( quadricent * gregorian.INTERCALATION_CYCLE_YEARS + cent * gregorian.LEAP_SUPPRESSION_YEARS + quad * gregorian.LEAP_CYCLE_YEARS + yindex ) if yindex == 4: yearday = 365 year = year - 1 else: yearday = ( depoch - quadricent * gregorian.INTERCALATION_CYCLE_DAYS - cent * gregorian.LEAP_SUPPRESSION_DAYS - quad * gregorian.LEAP_CYCLE_DAYS - yindex * gregorian.YEAR_DAYS ) month = floor(yearday / 28) return (year - YEAR_EPOCH + 2, month + 1, int(yearday - (month * 28)) + 1) def from_gregorian(year, month, day): return from_jd(gregorian.to_jd(year, month, day)) def to_gregorian(year, month, day): return gregorian.from_jd(to_jd(year, month, day)) def dayname(year, month, day): """ Give the name of the month and day for a given date. Returns: tuple month_name, day_name """ legal_date(year, month, day) yearday = (month - 1) * 28 + day if isleap(year + YEAR_EPOCH - 1): dname = data.DAY_NAMES_LEAP[yearday - 1] else: dname = data.DAY_NAMES[yearday - 1] return MONTHS[month - 1], dname def weekday(day): """ Gives the weekday (0=Monday) of a positivist month and day. Note that the festival month does not have a day. """ return (day % 7) - 1 def festival(month, day): """ Gives the festival day for a month and day. Returns None if inapplicable. """ return data.FESTIVALS.get((month, day)) convertdate-2.3.2/src/convertdate/utils.py000066400000000000000000000061161401655151000206550ustar00rootroot00000000000000# -*- coding: utf-8 -*- # This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr import calendar import math TROPICALYEAR = 365.24219878 # Mean solar tropical year def ceil(x): return int(math.ceil(x)) def floor(x): return int(math.floor(x)) def amod(a, b): '''Modulus function which returns numerator if modulus is zero''' modded = int(a % b) return b if modded == 0 else modded def jwday(j): '''Calculate day of week from Julian day. Consider using ``calendar.weekday``!''' return math.trunc((j + 0.5)) % 7 def weekday_before(weekday, jd): return jd - jwday(jd - weekday) def search_weekday(weekday, jd, direction, offset): ''' Determine the Julian date for the next or previous weekday Arguments: weekday (int): Day of week desired, 0 = Monday jd (float): Julian date to begin search direction(int): 1 = next weekday, -1 = last weekday offset(int): Offset from jd to begin search. ''' return weekday_before(weekday, jd + (direction * offset)) # Utility weekday functions, just wrappers for search_weekday def nearest_weekday(weekday, jd): return search_weekday(weekday, jd, 1, 3) def next_weekday(weekday, jd): return search_weekday(weekday, jd, 1, 7) def next_or_current_weekday(weekday, jd): return search_weekday(weekday, jd, 1, 6) def previous_weekday(weekday, jd): return search_weekday(weekday, jd, -1, 1) def previous_or_current_weekday(weekday, jd): return search_weekday(weekday, jd, 1, 0) def n_weeks(weekday, jd, nthweek): j = 7 * nthweek if nthweek > 0: j += previous_weekday(weekday, jd) else: j += next_weekday(weekday, jd) return j def monthcalendarhelper(start_weekday, month_length): end_weekday = start_weekday + (month_length - 1) % 7 lpad = (start_weekday + 1) % 7 rpad = (5 - end_weekday % 7) % 6 days = [None] * lpad + list(range(1, 1 + month_length)) + rpad * [None] return [days[i : i + 7] for i in range(0, len(days), 7)] def nth_day_of_month(n, weekday, month, year): """ Return (year, month, day) tuple that represents nth weekday of month in year. If n==0, returns last weekday of month. Weekdays: Monday=0 """ if not 0 <= n <= 5: raise IndexError("Nth day of month must be 0-5. Received: {}".format(n)) if not 0 <= weekday <= 6: raise IndexError("Weekday must be 0-6") firstday, daysinmonth = calendar.monthrange(year, month) # Get first WEEKDAY of month first_weekday_of_kind = 1 + (weekday - firstday) % 7 if n == 0: # find last weekday of kind, which is 5 if these conditions are met, else 4 if first_weekday_of_kind in [1, 2, 3] and first_weekday_of_kind + 28 <= daysinmonth: n = 5 else: n = 4 day = first_weekday_of_kind + ((n - 1) * 7) if day > daysinmonth: raise IndexError("No {}th day of month {}".format(n, month)) return (year, month, day) convertdate-2.3.2/tests/000077500000000000000000000000001401655151000151745ustar00rootroot00000000000000convertdate-2.3.2/tests/__init__.py000066400000000000000000000021001401655151000172760ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Most of this code is ported from Fourmilab's javascript calendar converter # http://www.fourmilab.ch/documents/calendar/ # which was developed by John Walker # # The algorithms are believed to be derived from the following source: # Meeus, Jean. Astronomical Algorithms . Richmond: Willmann-Bell, 1991. ISBN 0-943396-35-2. # The essential reference for computational positional astronomy. # import unittest JDCS = range(2159677, 2488395, 2000) class CalTestCase(unittest.TestCase): def reflexive(self, module, dates=None): """Check that the to_func and from_func work for a range of Julian dates.""" to_func = getattr(module, 'to_jd') from_func = getattr(module, 'from_jd') dates = dates or JDCS for j in dates: j = j + 0.5 self.assertEqual(j, to_func(*from_func(j)), 'checking from_jd(to_jd({0}))'.format(j)) def assertSequenceType(self, seq, cls): '''Assert that all members of `seq` are of the type `cls`.''' for x in seq: self.assertIs(type(x), cls) convertdate-2.3.2/tests/test_armenian.py000066400000000000000000000102171401655151000204000ustar00rootroot00000000000000# -*- coding: utf-8 -*- import time import unittest from convertdate import julianday from convertdate.armenian import ( _valid_date, from_gregorian, from_jd, from_julian, leap, month_length, to_gregorian, to_jd, to_julian, tostring, ) from . import CalTestCase class TestArmenian(CalTestCase): def setUp(self): self.now = time.localtime() self.today = julianday.from_gregorian(self.now[0], self.now[1], self.now[2]) def testValidDate(self): self.assertTrue(_valid_date(1, 1, 1)) self.assertTrue(_valid_date(533, 1, 1, method="sarkawag")) with self.assertRaises(ValueError): _valid_date(401, 1, 1, method="sarkawag") with self.assertRaises(ValueError): _valid_date(30, 4, 31) with self.assertRaises(ValueError): _valid_date(536, 13, 6) with self.assertRaises(ValueError): from_jd(1.5) self.assertTrue(_valid_date(536, 13, 6, method="sarkawag")) def testReflexive(self): self.assertEqual(self.today, to_jd(*from_jd(self.today))) self.assertEqual(self.today, to_jd(*from_jd(self.today, "sarkawag"), method="sarkawag")) for jd in range(2159677, 2488395, 2000): jd = jd + 0.5 self.assertEqual(jd, to_jd(*from_jd(jd))) self.assertEqual(jd, to_jd(*from_jd(jd, "sarkawag"), method="sarkawag")) def testLeap(self): self.assertEqual(True, leap(600)) self.assertEqual(False, leap(601)) def testGregorian(self): self.assertEqual((2019, 11, 3), to_gregorian(1469, 4, 14)) self.assertEqual((1469, 4, 14), from_gregorian(2019, 11, 3)) def testMonthLength(self): self.assertEqual(30, month_length(600, 1)) self.assertEqual(5, month_length(600, 13)) self.assertEqual(6, month_length(600, 13, "sarkawag")) def testJulian(self): cases = [ # first date of the calendar [(1, 1, 1), (552, 7, 11)], # last day of the year [(1, 13, 5), (553, 7, 10)], # leap year moves the calendar [(4, 13, 5), (556, 7, 9)], [(5, 1, 1), (556, 7, 10)], # check month boundaries for an entire year [(420, 1, 1), (971, 3, 29)], [(420, 1, 30), (971, 4, 27)], [(420, 2, 1), (971, 4, 28)], [(420, 2, 30), (971, 5, 27)], [(420, 3, 1), (971, 5, 28)], [(420, 3, 30), (971, 6, 26)], [(420, 4, 1), (971, 6, 27)], [(420, 4, 30), (971, 7, 26)], [(420, 5, 1), (971, 7, 27)], [(420, 5, 30), (971, 8, 25)], [(420, 6, 1), (971, 8, 26)], [(420, 6, 30), (971, 9, 24)], [(420, 7, 1), (971, 9, 25)], [(420, 7, 30), (971, 10, 24)], [(420, 8, 1), (971, 10, 25)], [(420, 8, 30), (971, 11, 23)], [(420, 9, 1), (971, 11, 24)], [(420, 9, 30), (971, 12, 23)], [(420, 10, 1), (971, 12, 24)], [(420, 10, 30), (972, 1, 22)], [(420, 11, 1), (972, 1, 23)], [(420, 11, 30), (972, 2, 21)], [(420, 12, 1), (972, 2, 22)], [(420, 12, 30), (972, 3, 22)], [(420, 13, 1), (972, 3, 23)], [(420, 13, 5), (972, 3, 27)], # check month boundaries around Julian leap year [(512, 13, 1), (1064, 2, 29)], [(512, 13, 2), (1064, 3, 1)], [(513, 1, 1), (1064, 3, 5)], # check the two calendars in 1084 [(533, 6, 15), (1084, 8, 11)], ] for a, j in cases: self.assertEqual(a, from_julian(*j)) for a, j in cases: self.assertEqual(j, to_julian(*a)) self.assertEqual((533, 1, 1), from_julian(1084, 8, 11, method="sarkawag")) self.assertEqual((533, 13, 5), from_julian(1085, 8, 10, method="sarkawag")) self.assertEqual((536, 13, 6), from_julian(1088, 8, 10, method="sarkawag")) self.assertEqual((537, 1, 1), from_julian(1088, 8, 11, method="sarkawag")) def testTostring(self): self.assertEqual('14 trē 1469', tostring(1469, 4, 14)) convertdate-2.3.2/tests/test_bahai.py000066400000000000000000000147021401655151000176550ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Test the Bahá’í calendar""" import time import unittest from convertdate import bahai, gregorian from . import CalTestCase class TestBahai(CalTestCase): pairs = { (2041, 11, 27): (198, bahai.QAWL, 6), # ascension of Abdu'l-Bahá 2041 (2043, 11, 28): (200, bahai.QAWL, 6), # ascension of Abdu'l-Bahá 2043 (2038, 3, 1): (194, bahai.ALA, 1), # beginning of fast 2038 (2039, 3, 2): (195, bahai.ALA, 1), # beginning of fast 2039 (2040, 3, 1): (196, bahai.ALA, 1), # beginning of fast 2040 (2041, 3, 1): (197, bahai.ALA, 1), # beginning of fast 2041 (2042, 3, 1): (198, bahai.ALA, 1), # beginning of fast 2042 (2043, 3, 2): (199, bahai.ALA, 1), # beginning of fast 2043 (2031, 10, 17): (188, bahai.ILM, 2), # twin holy days, 2031 (2031, 10, 18): (188, bahai.ILM, 3), (2051, 11, 5): (208, bahai.QUDRAT, 2), (2052, 10, 24): (209, bahai.ILM, 10), (2053, 11, 11): (210, bahai.QUDRAT, 9), (2054, 11, 1): (211, bahai.ILM, 18), (2055, 10, 21): (212, bahai.ILM, 6), (2056, 11, 8): (213, bahai.QUDRAT, 6), (2057, 10, 29): (214, bahai.ILM, 15), (2058, 10, 18): (215, bahai.ILM, 4), (2059, 11, 6): (216, bahai.QUDRAT, 4), (2060, 10, 25): (217, bahai.ILM, 11), (2061, 10, 14): (218, bahai.MASHIYYAT, 19), (2062, 11, 2): (219, bahai.ILM, 19), (2063, 10, 23): (220, bahai.ILM, 9), (2064, 11, 10): (221, bahai.QUDRAT, 8), } def setUp(self): self.tm = time.localtime() self.gregoriandate = (self.tm[0], self.tm[1], self.tm[2]) def test_reflexive(self): self.reflexive(bahai) def test_monthlength(self): self.assertEqual(bahai.month_length(1, 3), 19) self.assertEqual(bahai.month_length(1, 1), 19) def test_gregorian_nawruz(self): nawruz_official = { 20: [ 2016, 2017, 2020, 2021, 2024, 2025, 2028, 2029, 2030, 2032, 2033, 2034, 2036, 2037, 2038, 2040, 2041, 2042, 2044, 2045, 2046, 2048, 2049, 2050, 2052, 2053, 2054, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, ], 21: [ 2015, 2018, 2019, 2022, 2023, 2026, 2027, 2031, 2035, 2039, 2043, 2047, 2051, 2055, ], } for date, gyears in nawruz_official.items(): for gyear in gyears: self.assertEqual((3, date), bahai.gregorian_nawruz(gyear)) def test_ayyam_i_ha(self): # source: https://www.bahai.us/events/holy-days/ # years with four days in Ayyám-i-Há # bahai_year: gregorian start of Ayyám-i-Há ayyamiha = [ {"byear": 208, "gdate": (2052, 2, 26), "days": 4}, {"byear": 209, "gdate": (2053, 2, 25), "days": 4}, {"byear": 210, "gdate": (2054, 2, 25), "days": 4}, {"byear": 211, "gdate": (2055, 2, 25), "days": 5}, {"byear": 212, "gdate": (2056, 2, 26), "days": 4}, {"byear": 213, "gdate": (2057, 2, 25), "days": 4}, {"byear": 214, "gdate": (2058, 2, 25), "days": 4}, {"byear": 215, "gdate": (2059, 2, 25), "days": 4}, {"byear": 216, "gdate": (2060, 2, 25), "days": 5}, {"byear": 217, "gdate": (2061, 2, 25), "days": 4}, {"byear": 218, "gdate": (2062, 2, 25), "days": 4}, {"byear": 219, "gdate": (2063, 2, 25), "days": 4}, {"byear": 220, "gdate": (2064, 2, 25), "days": 5}, {"byear": 221, "gdate": (2065, 2, 25), "days": 4}, ] with self.subTest(): for case in ayyamiha: start_jd = gregorian.to_jd(*case["gdate"]) for i in range(case["days"]): b = bahai.to_jd(case["byear"], bahai.AYYAMIHA, i + 1) self.assertEqual(start_jd + i, b, "%s Ayyám-i-Há %s" % (i + 1, case["byear"])) def test_reflexive(self): for jd in range(2159677, 2488395, 1867): self.assertEqual(jd + 0.5, bahai.to_jd(*bahai.from_jd(jd + 0.5))) def test_to_gregorian(self): for g, b in self.pairs.items(): self.assertEqual(g, bahai.to_gregorian(*b)) def test_from_gregorian(self): for g, b in self.pairs.items(): self.assertEqual(b, bahai.from_gregorian(*g)) def test_month_length(self): for x in range(1, 19): self.assertEqual(bahai.month_length(2019, x), 19) def test_month_length_ha(self): official = { 4: [ 2016, 2017, 2019, 2020, 2021, 2023, 2024, 2025, 2027, 2028, 2029, 2030, 2032, 2033, 2034, 2036, 2037, 2038, 2040, 2041, 2042, 2044, 2045, 2046, 2048, 2049, 2050, 2052, 2053, 2054, 2056, 2057, 2058, 2059, 2061, 2062, 2063, 2065, ], 5: [2018, 2022, 2026, 2031, 2035, 2039, 2043, 2047, 2051, 2055, 2060, 2064], } for length, gyears in official.items(): for gyear in gyears: byear = gyear - 1844 self.assertEqual(length, bahai.month_length(byear, 19)) def test_returntype(self): self.assertSequenceType(bahai.from_gregorian(2020, 6, 4), int) convertdate-2.3.2/tests/test_french_republican.py000066400000000000000000000274201401655151000222630ustar00rootroot00000000000000# -*- coding: utf-8 -*- import time import unittest from convertdate import french_republican as fr from convertdate import gregorian year_starts = [ ((1, 1, 1), (1792, 9, 22)), ((2, 1, 1), (1793, 9, 22)), ((3, 1, 1), (1794, 9, 22)), ((4, 1, 1), (1795, 9, 23)), ((5, 1, 1), (1796, 9, 22)), ((6, 1, 1), (1797, 9, 22)), ((7, 1, 1), (1798, 9, 22)), ((8, 1, 1), (1799, 9, 23)), ((9, 1, 1), (1800, 9, 23)), ((10, 1, 1), (1801, 9, 23)), ((11, 1, 1), (1802, 9, 23)), ((12, 1, 1), (1803, 9, 24)), ((13, 1, 1), (1804, 9, 23)), ((14, 1, 1), (1805, 9, 23)), ] leaps = [ ((3, 13, 6), (1795, 9, 22)), ((7, 13, 6), (1799, 9, 22)), ((11, 13, 6), (1803, 9, 23)), ] romme = [ ((15, 1, 1), (1806, 9, 23)), ((15, 13, 5), (1807, 9, 22)), ((16, 1, 1), (1807, 9, 23)), ((16, 13, 6), (1808, 9, 22)), ((17, 1, 1), (1808, 9, 23)), ((17, 13, 5), (1809, 9, 22)), ((18, 1, 1), (1809, 9, 23)), ((19, 1, 1), (1810, 9, 23)), ((20, 1, 1), (1811, 9, 23)), ((20, 13, 6), (1812, 9, 22)), ((222, 1, 1), (2013, 9, 22)), ((223, 1, 1), (2014, 9, 22)), ((225, 1, 1), (2016, 9, 22)), ] continuous = [ ((15, 1, 1), (1806, 9, 23)), ((15, 13, 5), (1807, 9, 22)), ((15, 13, 6), (1807, 9, 23)), ((16, 1, 1), (1807, 9, 24)), ((17, 1, 1), (1808, 9, 23)), ((18, 1, 1), (1809, 9, 23)), ((19, 1, 1), (1810, 9, 23)), ((19, 13, 6), (1811, 9, 23)), ((20, 1, 1), (1811, 9, 24)), ((220, 1, 1), (2011, 9, 25)), ((221, 1, 1), (2012, 9, 24)), ((222, 1, 1), (2013, 9, 24)), ((223, 1, 1), (2014, 9, 24)), ((223, 13, 6), (2015, 9, 24)), ((224, 1, 1), (2015, 9, 25)), ((225, 1, 1), (2016, 9, 24)), ] madler = [ ((15, 1, 1), (1806, 9, 23)), ((15, 13, 6), (1807, 9, 23)), ((16, 1, 1), (1807, 9, 24)), ((16, 13, 5), (1808, 9, 22)), ((17, 1, 1), (1808, 9, 23)), ((18, 1, 1), (1809, 9, 23)), ((18, 13, 5), (1810, 9, 22)), ((19, 1, 1), (1810, 9, 23)), ((19, 13, 5), (1811, 9, 22)), ((20, 1, 1), (1811, 9, 23)), ((20, 13, 6), (1812, 9, 22)), ((222, 1, 1), (2013, 9, 23)), ((223, 1, 1), (2014, 9, 23)), ((224, 1, 1), (2015, 9, 23)), ((224, 13, 6), (2016, 9, 22)), ((225, 1, 1), (2016, 9, 23)), ] class TestFrenchRepublican(unittest.TestCase): def setUp(self): self.tm = time.localtime() self.gregoriandate = (self.tm[0], self.tm[1], self.tm[2]) self.jd = gregorian.to_jd(self.gregoriandate[0], self.gregoriandate[1], self.gregoriandate[2]) self.x = gregorian.to_jd(2016, 2, 29) self.j = gregorian.to_jd(2015, 9, 24) # around the autumnal equinox self.start = 2457285 def test_french_republican(self): assert self.jd == fr.to_jd(*fr.from_jd(self.jd)) assert fr.from_gregorian(2014, 6, 14) == (222, 9, 26) assert (2014, 6, 14) == fr.to_gregorian(222, 9, 26) assert (3, 13, 6) == fr.from_gregorian(1795, 9, 22) for jd in range(2378822, 2488395, 2000): self.assertEqual(jd + 0.5, gregorian.to_jd(*gregorian.from_jd(jd + 0.5))) def test_french_republican_leap(self): self.assertTrue(fr.leap(3)) self.assertTrue(fr.leap(3, 'madler')) self.assertTrue(fr.leap(3, 'romme')) self.assertTrue(fr.leap(3, 'continuous')) self.assertTrue(fr.leap(7)) self.assertTrue(fr.leap(7, 'madler')) self.assertTrue(fr.leap(7, 'romme')) self.assertTrue(fr.leap(7, 'continuous')) self.assertTrue(fr.leap(11)) self.assertTrue(fr.leap(11, 'madler')) self.assertTrue(fr.leap(11, 'romme')) self.assertTrue(fr.leap(11, 'continuous')) self.assertFalse(fr.leap(4)) self.assertFalse(fr.leap(14)) self.assertTrue(fr.leap(15)) self.assertTrue(fr.leap(15, 'madler')) self.assertFalse(fr.leap(15, 'romme')) self.assertTrue(fr.leap(15, 'continuous')) self.assertTrue(fr.leap(20)) self.assertTrue(fr.leap(20, 'madler')) self.assertTrue(fr.leap(20, 'romme')) self.assertFalse(fr.leap(20, 'continuous')) self.assertFalse(fr.leap(23)) self.assertFalse(fr.leap(23, 'madler')) self.assertFalse(fr.leap(23, 'romme')) self.assertTrue(fr.leap(23, 'continuous')) self.assertRaises(ValueError, fr.leap, 100, method='foo') def test_french_republican_decade(self): self.assertEqual(fr.decade(1), 1) def test_french_republican_format(self): self.assertEqual(fr.format(8, 2, 18), '18 Brumaire 8') def test_french_republican_to_jd_errors(self): self.assertRaises(ValueError, fr.to_jd, 100, 1, 0) self.assertRaises(ValueError, fr.to_jd, 100, 1, 31) self.assertRaises(ValueError, fr.to_jd, 100, 14, 1) self.assertRaises(ValueError, fr.to_jd, 4, 13, 6) self.assertRaises(ValueError, fr.to_jd, 100, 12, 1, method='foo') def test_french_republican_from_jd_errors(self): self.assertRaises(ValueError, fr.from_gregorian, 1789, 1, 1, 'romme') def test_french_republican_start_of_years_from_gregorian_equinoctal(self): for f, g in year_starts: self.assertEqual(f, fr.from_gregorian(*g)) def test_french_republican_start_of_years_to_gregorian_equinoctal(self): for f, g in year_starts: self.assertEqual(g, fr.to_gregorian(*f)) def test_french_republican_leap_days_from_gregorian_equinoctal(self): for f, g in leaps: self.assertEqual(f, fr.from_gregorian(*g)) def test_french_republican_leap_days_to_gregorian_equinoctal(self): for f, g in leaps: self.assertEqual(g, fr.to_gregorian(*f)) # Madler (128) def test_french_republican_leap_days_from_gregorian_madler(self): for f, g in leaps: self.assertEqual(f, fr.from_gregorian(*g, method='madler')) def test_french_republican_leap_days_to_gregorian_madler(self): for f, g in leaps: self.assertEqual(g, fr.to_gregorian(*f, method='madler')) def test_french_republican_schematic_madler_to_gregorian(self): for f, g in year_starts: self.assertEqual(g, fr.to_gregorian(*f, method=128)) for f, g in madler: self.assertEqual(g, fr.to_gregorian(*f, method=128)) def test_french_republican_schematic_madler_from_gregorian(self): for f, g in year_starts: self.assertEqual(g, fr.to_gregorian(*f, method=128)) for f, g in madler: self.assertEqual(f, fr.from_gregorian(*g, method=128)) def test_french_republican_schematic_madler(self): self.assertEqual(self.j, fr.to_jd(*fr.from_jd(self.j, method=128), method=128)) self.assertEqual(self.x, fr.to_jd(*fr.from_jd(self.x, method=128), method=128)) self.assertEqual(self.jd, fr.to_jd(*fr.from_jd(self.jd, method=128), method=128)) # # Romme (100) def test_french_republican_leap_days_from_gregorian_romme(self): for f, g in leaps: self.assertEqual(f, fr.from_gregorian(*g, method=100)) def test_french_republican_leap_days_to_gregorian_romme(self): for f, g in leaps: self.assertEqual(g, fr.to_gregorian(*f, method=100)) def test_french_republican_schematic_romme_to_gregorian(self): for f, g in year_starts: self.assertEqual(g, fr.to_gregorian(*f, method=100)) for f, g in romme: self.assertEqual(g, fr.to_gregorian(*f, method='romme')) def test_french_republican_schematic_romme_from_gregorian(self): for f, g in year_starts: self.assertEqual(f, fr.from_gregorian(*g, method='romme')) for f, g in romme: self.assertEqual(f, fr.from_gregorian(*g, method=100)) def test_french_republican_schematic_romme(self): self.assertEqual( self.gregoriandate, fr.to_gregorian(*fr.from_gregorian(*self.gregoriandate, method=100), method=100), ) self.assertEqual(self.jd, fr.to_jd(*fr.from_jd(self.jd, method='romme'), method=100)) self.assertEqual(self.x, fr.to_jd(*fr.from_jd(self.x, method=100), method=100)) assert self.j == fr.to_jd(*fr.from_jd(self.j, method=100), method=100) # Continuous (4) def test_french_republican_leap_days_from_gregorian_continuous(self): for f, g in leaps: self.assertEqual(f, fr.from_gregorian(*g, method=4)) def test_french_republican_leap_days_to_gregorian_continuous(self): for f, g in leaps: self.assertEqual(g, fr.to_gregorian(*f, method=4)) def test_french_republican_schematic_continuous_to_gregorian(self): for f, g in year_starts: self.assertEqual(g, fr.to_gregorian(*f, method=4)) for f, g in continuous: self.assertEqual(g, fr.to_gregorian(*f, method='continuous')) def test_french_republican_schematic_continuous_from_gregorian(self): self.assertEqual((16, 1, 1), fr.from_gregorian(1807, 9, 24, method='continuous')) for f, g in year_starts: self.assertEqual(f, fr.from_gregorian(*g, method=4)) for f, g in continuous: self.assertEqual(f, fr.from_gregorian(*g, method=4)) def test_french_republican_schematic_continuous(self): self.assertEqual(gregorian.from_jd(self.jd), fr.to_gregorian(*fr.from_jd(self.jd, method=4), method=4)) self.assertEqual(self.x, fr.to_jd(*fr.from_jd(self.x, method=4), method=4)) assert self.j == fr.to_jd(*fr.from_jd(self.j, method='continuous'), method=4) def test_french_republican_famous_dates(self): self.assertEqual(gregorian.to_jd(1793, 9, 22), fr.to_jd(2, 1, 1)) # 9 Thermidor II self.assertEqual(gregorian.to_jd(1794, 7, 27), fr.to_jd(2, 11, 9)) # 18 Brumaire An VIII assert gregorian.to_jd(1799, 11, 9) == fr.to_jd(8, 2, 18) assert fr.to_jd(2, 9, 22) == gregorian.to_jd(1794, 6, 10) assert fr.to_jd(4, 1, 13) == gregorian.to_jd(1795, 10, 5) assert fr.to_gregorian(5, 12, 18) == (1797, 9, 4) assert fr.to_jd(6, 8, 22) == gregorian.to_jd(1798, 5, 11) assert (2, 9, 22) == fr.from_gregorian(1794, 6, 10) assert (4, 1, 13) == fr.from_gregorian(1795, 10, 5) assert (5, 12, 18) == fr.from_gregorian(1797, 9, 4) assert (6, 8, 22) == fr.from_gregorian(1798, 5, 11) # Coup of 30 Prairial VII self.assertEqual(fr.to_gregorian(7, 9, 30), (1799, 6, 18)) def test_premier_da_la_annee(self): # Autumnal equinoxes in 1793 and 1794 e0 = 2376204.5 e1 = 2376569.5 self.assertEqual(fr.premier_da_la_annee(e1 - 10), e0) self.assertEqual(fr.premier_da_la_annee(e1 + 100), e1) def test_french_republican_months(self): self.assertEqual(fr.MOIS[0], "Vendémiaire") self.assertEqual(fr.MOIS[1], "Brumaire") self.assertEqual(fr.MOIS[2], 'Frimaire') self.assertEqual(fr.MOIS[3], 'Nivôse') self.assertEqual(fr.MOIS[4], 'Pluviôse') self.assertEqual(fr.MOIS[5], 'Ventôse') self.assertEqual(fr.MOIS[6], 'Germinal') self.assertEqual(fr.MOIS[7], 'Floréal') self.assertEqual(fr.MOIS[8], 'Prairial') self.assertEqual(fr.MOIS[9], 'Messidor') self.assertEqual(fr.MOIS[10], 'Thermidor') self.assertEqual(fr.MOIS[12], 'Sansculottides') self.assertEqual(fr.MOIS[11], "Fructidor") def test_french_republican_schematic_error(self): self.assertRaises(ValueError, fr.from_jd, self.jd, method=400) self.assertRaises(ValueError, fr.from_jd, self.j, method=-1) def test_french_republican_names(self): self.assertEqual(fr.day_name(1, 1), "Raisin") self.assertEqual(fr.day_name(2, 1), "Pomme") self.assertEqual(fr.day_name(4, 18), "Pierre à chaux") self.assertEqual(fr.day_name(12, 15), "Truite") self.assertEqual(fr.day_name(13, 1), "La Fête de la Vertu") convertdate-2.3.2/tests/test_general.py000066400000000000000000000147221401655151000202300ustar00rootroot00000000000000# -*- coding: utf-8 -*- import time from datetime import datetime import pytz from convertdate import coptic, dublin, gregorian, hebrew, islamic, iso, julian, julianday, ordinal, persian, utils from . import CalTestCase class TestConvertdate(CalTestCase): def setUp(self): self.tm = time.localtime() self.gregoriandate = (self.tm[0], self.tm[1], self.tm[2]) self.jd = gregorian.to_jd(self.gregoriandate[0], self.gregoriandate[1], self.gregoriandate[2]) self.c_greg = (1492, 10, 21) self.c = gregorian.to_jd(*self.c_greg) self.x = gregorian.to_jd(2016, 2, 29) self.jdcs = range(2159677, 2488395, 2000) def test_utils(self): self.assertEqual(utils.amod(100, 4), 4) self.assertEqual(utils.ceil(1.2), 2) self.assertEqual(utils.jwday(self.jd), self.tm[6]) def test_julian_legal_date(self): try: julian.to_jd(1900, 2, 29) except ValueError: self.fail('Unexpected ValueError: "julian.to_jd(1900, 2, 29)"') self.assertRaises(ValueError, julian.to_jd, 2014, 2, 29) self.assertRaises(ValueError, julian.to_jd, 2014, 3, 32) self.assertRaises(ValueError, julian.to_jd, 2014, 4, 31) self.assertRaises(ValueError, julian.to_jd, 2014, 5, -1) def test_hebrew(self): self.assertEqual(self.jd, hebrew.to_jd(*hebrew.from_jd(self.jd))) self.reflexive(hebrew) # Anno Mundi am = hebrew.to_jd(1, hebrew.TISHRI, 1) self.assertEqual(julian.from_jd(am), (-3760, 10, 7)) def test_islamic(self): self.assertEqual(self.jd, islamic.to_jd(*islamic.from_jd(self.jd))) self.reflexive(islamic) new_years = [ (2012, 11, 15), (2015, 10, 15), (2019, 9, 1), (2020, 8, 20), (2021, 8, 10), (2022, 7, 30), ] for date in new_years: jd = islamic.to_jd_gregorianyear(date[0], 1, 1) with self.subTest(date[0]): self.assertEqual(date, gregorian.from_jd(jd)) self.assertEqual(islamic.from_jd(1948085.5), (0, 1, 1)) self.assertEqual(islamic.from_jd(1948084.5), (-1, 12, 30)) self.assertEqual(islamic.from_jd(1912648.5), (-100, 1, 1)) self.assertEqual(islamic.to_jd(-100, 1, 1), 1912648.5) def test_iso(self): self.assertEqual(iso.from_gregorian(2005, 1, 1), (2004, 53, 6)) self.assertEqual(iso.to_gregorian(2004, 53, 6), (2005, 1, 1)) self.assertEqual(self.jd, iso.to_jd(*iso.from_jd(self.jd))) self.reflexive(iso) def test_from_julian(self): self.assertEqual(self.jd, julian.to_jd(*julian.from_jd(self.jd))) self.assertEqual(julian.from_jd(self.c), (1492, 10, 12)) self.assertEqual(julian.from_jd(2400000.5), (1858, 11, 5)) self.assertEqual(julian.from_jd(2399830.5), (1858, 5, 19)) def test_julian_inverse(self): self.reflexive(julian) def test_to_julian(self): self.assertEqual(julian.to_jd(1858, 11, 5), 2400000.5) self.assertEqual(julian.to_jd(1492, 10, 12), self.c) def test_coptic(self): self.assertEqual(coptic.to_jd(1000, 1, 1), 2189914.5) self.assertEqual(coptic.to_jd(1666, 6, 1), 2433320.5) self.assertEqual(coptic.to_jd(1, 1, 1), 1825029.5) self.assertEqual(coptic.from_jd(2437970.5), (1679, 2, 23)) self.assertEqual(coptic.to_jd(1259, 13, 6), 2284878.5) self.assertEqual(coptic.from_jd(2284878.5), (1259, 13, 6)) self.reflexive(coptic) self.assertEqual(coptic.from_gregorian(2017, 1, 7), (1733, 4, 29)) self.assertEqual(coptic.to_gregorian(1727, 11, 11), (2011, 7, 18)) def test_dublin_dc(self): self.assertEqual(dublin.from_gregorian(1900, 1, 1), 0.5) self.assertEqual(dublin.to_gregorian(1), (1900, 1, 1)) self.assertEqual(dublin.to_jd(0), 2415020.0) self.assertEqual( dublin.to_jd(dublin.from_jd(self.c)), gregorian.to_jd(*dublin.to_gregorian(dublin.from_gregorian(*self.c_greg))), ) self.assertEqual(dublin.to_gregorian(dublin.from_jd(1737936)), gregorian.from_jd(1737936)) self.assertEqual(dublin.to_julian(dublin.from_jd(1737936)), julian.from_jd(1737936)) def test_julian_day(self): self.assertEqual(julianday.from_gregorian(*self.c_greg), self.c) self.assertEqual(julianday.to_datetime(self.c), datetime(1492, 10, 21, tzinfo=pytz.utc)) self.assertEqual(julianday.to_datetime(self.x), datetime(2016, 2, 29, tzinfo=pytz.utc)) self.assertEqual(julianday.to_datetime(self.c + 0.25), datetime(1492, 10, 21, 6, tzinfo=pytz.utc)) self.assertEqual(julianday.to_datetime(self.x + 0.525), datetime(2016, 2, 29, 12, 36, tzinfo=pytz.utc)) dt = datetime(2014, 11, 8, 3, 37, tzinfo=pytz.utc) self.assertEqual(julianday.from_datetime(dt), 2456969.65069) self.assertEqual(julianday.to_datetime(self.x + 0.525), datetime(2016, 2, 29, 12, 36, tzinfo=pytz.utc)) def test_month_length_julian(self): self.assertEqual(julian.month_length(1582, 10), 31) self.assertEqual(julian.month_length(1977, 2), 28) self.assertEqual(julian.month_length(1900, 2), 29) self.assertEqual(julian.month_length(1904, 2), 29) def test_month_length_islamic(self): self.assertEqual(islamic.month_length(1436, 1), 30) self.assertEqual(islamic.month_length(1436, 2), 29) self.assertEqual(islamic.month_length(1436, 12), 30) def test_monthcalendar_julian(self): self.assertEqual(julian.monthcalendar(1582, 10).pop(0).pop(1), 1) self.assertEqual(julian.monthcalendar(1582, 10).pop().pop(3), 31) def test_monthcalendar_islamic(self): self.assertEqual(islamic.monthcalendar(1436, 10).pop(0).pop(6), 1) self.assertEqual(islamic.monthcalendar(1436, 11).pop().pop(1), 30) def test_monthcalendar_hebrew(self): self.assertEqual(hebrew.monthcalendar(5775, 7).pop(0).pop(4), 1) self.assertEqual(hebrew.monthcalendar(5775, 7).pop().pop(0), 25) def test_returntype(self): self.assertSequenceType(coptic.from_gregorian(2020, 6, 4), int) self.assertSequenceType(hebrew.from_gregorian(2020, 6, 4), int) self.assertSequenceType(islamic.from_gregorian(2020, 6, 4), int) self.assertSequenceType(iso.from_gregorian(2020, 6, 4), int) self.assertSequenceType(julian.from_gregorian(2020, 6, 4), int) self.assertSequenceType(persian.from_gregorian(2020, 6, 4), int) convertdate-2.3.2/tests/test_gregorian.py000066400000000000000000000104371401655151000205670ustar00rootroot00000000000000# -*- coding: utf-8 -*- import time from convertdate import gregorian, julian from . import CalTestCase class TestGregorian(CalTestCase): def setUp(self): self.tm = time.localtime() self.gregoriandate = (self.tm[0], self.tm[1], self.tm[2]) self.jd = gregorian.to_jd(self.gregoriandate[0], self.gregoriandate[1], self.gregoriandate[2]) self.c_greg = (1492, 10, 21) self.c = gregorian.to_jd(*self.c_greg) self.jdcs = range(2159677, 2488395, 2000) def test_gregorian(self): assert gregorian.to_jd(*self.gregoriandate) == self.jd assert gregorian.to_jd2(*self.gregoriandate) == self.jd self.assertEqual(self.c, 2266295.5) assert gregorian.to_jd(2000, 1, 1) == 2451544.5 assert gregorian.to_jd2(2000, 1, 1) == 2451544.5 self.reflexive(gregorian) self.reflexive(gregorian, range(113957, 1574957, 365)) def test_gregorian_proleptic(self): self.assertEqual(gregorian.to_jd(72, 6, 27), 1747535.5) assert gregorian.to_jd2(72, 6, 27) == 1747535.5 for y in range(int(gregorian.EPOCH), int(gregorian.EPOCH) - 10000, -250): assert gregorian.to_jd(*gregorian.from_jd(y)) == y - 0.5 assert gregorian.from_jd(gregorian.to_jd(-1, 3, 1)) == (-1, 3, 1) assert gregorian.from_jd(gregorian.to_jd(-100, 7, 1)) == (-100, 7, 1) assert gregorian.from_jd(gregorian.to_jd(-500, 12, 31)) == (-500, 12, 31) assert gregorian.from_jd(gregorian.to_jd(-1000, 1, 1)) == (-1000, 1, 1) def test_gregorian_pre_epoch(self): j = julian.to_jd(-4716, 3, 1) g = gregorian.to_jd(-4716, 1, 23) self.assertEqual(g, j) self.assertEqual(g - 1, j - 1) self.assertEqual(g - 1, gregorian.to_jd(-4716, 1, 22)) self.assertEqual(gregorian.to_jd(-4716, 1, 22), j - 1) self.assertEqual(gregorian.to_jd(-4716, 1, 22), julian.to_jd(-4716, 2, 29)) def test_from_gregorian_20thc(self): self.assertEqual(gregorian.from_jd(2418934.0), (1910, 9, 19)) self.assertEqual(gregorian.from_jd(2433360.0), (1950, 3, 19)) self.assertEqual(gregorian.from_jd(2437970.0), (1962, 11, 1)) self.assertEqual(gregorian.from_jd(2447970.0), (1990, 3, 19)) self.assertEqual(gregorian.from_jd(2456967.5), (2014, 11, 6)) def test_to_gregorian(self): self.assertEqual(gregorian.to_jd(2014, 11, 5), 2456966.5) assert gregorian.to_jd(2012, 3, 1) == 1 + gregorian.to_jd(2012, 2, 29) assert gregorian.from_jd(gregorian.to_jd(2012, 2, 29) + 1) == (2012, 3, 1) assert gregorian.from_jd(gregorian.to_jd(2011, 2, 28) + 1) == (2011, 3, 1) assert gregorian.from_jd(gregorian.to_jd(2012, 3, 2) - 2) == (2012, 2, 29) assert gregorian.from_jd(gregorian.to_jd(2011, 3, 2) - 2) == (2011, 2, 28) def test_gregorian_1_ma(self): assert gregorian.to_jd(*self.c_greg) == 2266295.5 def test_gregorian_2_ma(self): assert gregorian.to_jd2(*self.c_greg) == 2266295.5 def test_gregorian_julian_dif_proleptic(self): self.assertEqual(julian.to_jd(1500, 5, 10), gregorian.to_jd(1500, 5, 20)) assert julian.to_jd(1300, 5, 10) == gregorian.to_jd(1300, 5, 18) assert julian.to_jd(1000, 5, 10) == gregorian.to_jd(1000, 5, 16) assert julian.to_jd(900, 5, 10) == gregorian.to_jd(900, 5, 15) assert julian.to_jd(300, 5, 10) == gregorian.to_jd(300, 5, 11) assert julian.to_jd(200, 5, 10) == gregorian.to_jd(200, 5, 10) assert julian.to_jd(100, 5, 10) == gregorian.to_jd(100, 5, 9) assert julian.to_jd(-1, 5, 10) == gregorian.to_jd(-1, 5, 8) def test_year_zero(self): assert gregorian.to_jd(1, 1, 1) == 1.0 + gregorian.to_jd(0, 12, 31) assert julian.to_jd(1, 1, 1) == 1.0 + julian.to_jd(0, 12, 31) assert julian.from_jd(julian.to_jd(1, 1, 1) - 1) == (0, 12, 31) self.assertEqual(gregorian.from_jd(gregorian.to_jd(1, 1, 1) - 1), (0, 12, 31)) def test_legal_date(self): self.assertRaises(ValueError, gregorian.to_jd, 1900, 2, 29) self.assertRaises(ValueError, gregorian.to_jd, 2014, 2, 29) self.assertRaises(ValueError, gregorian.to_jd, 2014, 3, 32) self.assertRaises(ValueError, gregorian.to_jd, 2014, 4, 31) self.assertRaises(ValueError, gregorian.to_jd, 2014, 5, -1) convertdate-2.3.2/tests/test_holidays.py000066400000000000000000000254761401655151000204370ustar00rootroot00000000000000# -*- coding: utf-8 -*- import unittest from datetime import datetime from convertdate import holidays, julian class TestHolidays(unittest.TestCase): def setUp(self): self.h = holidays.Holidays(2015) def test_nth_day_of_month(self): assert holidays.nth_day_of_month(4, 2, 4, 2014) == (2014, 4, 23) self.assertRaises(IndexError, holidays.nth_day_of_month, 5, 3, 4, 2014) self.assertRaises(IndexError, holidays.nth_day_of_month, 6, 2, 4, 2014) self.assertRaises(IndexError, holidays.nth_day_of_month, 1, 7, 4, 2014) assert holidays.nth_day_of_month(4, 3, 11, 2014) == (2014, 11, 27) assert holidays.nth_day_of_month(0, 3, 11, 2014) == (2014, 11, 27) def test_holidays(self): h = holidays.Holidays(2014) self.assertEqual(h.christmas, (2014, 12, 25)) assert h.thanksgiving == (2014, 11, 27) assert h.indigenous_peoples_day == (2014, 10, 13) assert h.independence_day == (2014, 7, 4) assert self.h.christmas == (2015, 12, 25) assert self.h.christmas_eve == (2015, 12, 24) assert self.h.new_years == (2015, 1, 1) assert self.h.new_years_eve == (2015, 12, 31) assert self.h.valentines_day == (2015, 2, 14) assert self.h.halloween == (2015, 10, 31) assert self.h.mothers_day == (2015, 5, 10) self.assertEqual(self.h.fathers_day, (2015, 6, 21)) def test_class(self): h = holidays.Holidays() assert h.year == datetime.now().year assert str(self.h) == 'Holidays(2015)' h.set_year(2010) assert h.year == 2010 def test_events(self): assert holidays.new_years(2013) == (2013, 1, 1) assert holidays.martin_luther_king_day(2015) == (2015, 1, 19) assert holidays.lincolns_birthday(2015) == (2015, 2, 12) assert holidays.valentines_day(2015) == (2015, 2, 14) assert holidays.washingtons_birthday(2015) == (2015, 2, 22) assert holidays.presidents_day(2015) == (2015, 2, 16) assert holidays.pulaski_day(2015) == (2015, 3, 2) assert self.h.pulaski_day == (2015, 3, 2) assert holidays.may_day(2015) == (2015, 5, 1) assert holidays.indigenous_peoples_day(2015, 'canada') == (2015, 10, 12) assert holidays.independence_day(2015) == (2015, 7, 4) assert holidays.independence_day(2015, True) == (2015, 7, 3) def test_thanksgiving(self): assert holidays.thanksgiving(2013) == (2013, 11, 28) assert holidays.thanksgiving(1939) == (1939, 11, 23) self.assertEqual(holidays.thanksgiving(1941), (1941, 11, 20)) assert self.h.thanksgiving == (2015, 11, 26) assert holidays.thanksgiving(2015, 'canada') == (2015, 10, 12) def test_easterWestern(self): easters = [ (1994, 4, 3), (1995, 4, 16), (1996, 4, 7), (1997, 3, 30), (1998, 4, 12), (1999, 4, 4), (2000, 4, 23), (2001, 4, 15), (2002, 3, 31), (2003, 4, 20), (2004, 4, 11), (2005, 3, 27), (2006, 4, 16), (2007, 4, 8), (2008, 3, 23), (2009, 4, 12), (2010, 4, 4), (2011, 4, 24), (2012, 4, 8), (2013, 3, 31), (2014, 4, 20), (2015, 4, 5), (2016, 3, 27), (2017, 4, 16), (2018, 4, 1), (2019, 4, 21), (2020, 4, 12), (2021, 4, 4), (2022, 4, 17), (2023, 4, 9), (2024, 3, 31), (2025, 4, 20), (2026, 4, 5), (2027, 3, 28), (2028, 4, 16), (2029, 4, 1), (2030, 4, 21), (2031, 4, 13), (2032, 3, 28), (2033, 4, 17), (2034, 4, 9), (2345, 4, 22), ] for y, m, d in easters: self.assertEqual(holidays.easter(y), (y, m, d)) def test_easterEastern(self): easters = [ (1999, 4, 11), (2000, 4, 30), (2001, 4, 15), (2002, 5, 5), (2003, 4, 27), (2004, 4, 11), (2005, 5, 1), (2006, 4, 23), (2007, 4, 8), (2008, 4, 27), (2009, 4, 19), (2010, 4, 4), (2011, 4, 24), (2012, 4, 15), (2013, 5, 5), (2014, 4, 20), (2015, 4, 12), (2016, 5, 1), (2017, 4, 16), (2018, 4, 8), (2019, 4, 28), (2020, 4, 19), (2021, 5, 2), (2022, 4, 24), (2023, 4, 16), (2024, 5, 5), (2025, 4, 20), (2026, 4, 12), (2027, 5, 2), (2028, 4, 16), (2029, 4, 8), (2030, 4, 28), (2031, 4, 13), (2032, 5, 2), (2033, 4, 24), (2034, 4, 9), (2035, 4, 29), (2036, 4, 20), (2037, 4, 5), (2038, 4, 25), (2039, 4, 17), (2056, 4, 9), (2156, 4, 11), ] for y, m, d in easters: self.assertEqual(holidays.easter(y, "orthodox"), (y, m, d)) self.assertEqual(holidays.easter(y, "eastern"), (y, m, d)) self.assertEqual(self.h.easter, (2015, 4, 5)) def testNonChalcedonian(self): # In these years, Orthodox Easter falls on 6 April (Julian), # but Non-Chalcedonian churches celebrate it a week later on 13 Aprail years = ( 570, 665, 760, 1007, 1102, 1197, 1292, 1539, 1634, 1729, 1824, 2071, 2166, 2261, 2356, ) for y in years: orthodox = julian.from_gregorian(*holidays.easter(y, "orthodox")) eastern = julian.from_gregorian(*holidays.easter(y, "eastern")) self.assertNotEqual(orthodox, eastern) self.assertEqual((y, 4, 6), orthodox) self.assertEqual((y, 4, 13), eastern) for y in years: self.assertEqual(holidays.easter(y + 1, "orthodox"), holidays.easter(y + 1, "eastern")) def test_jewish_holidays(self): # http://www.chabad.org/holidays/passover/pesach_cdo/aid/671901/jewish/When-is-Passover-in-2013-2014-2015-2016-and-2017.htm # the date here is the start of the holiday, so the eve=1 option is used passovers = [(2013, 3, 25), (2014, 4, 14), (2015, 4, 3), (2016, 4, 22), (2017, 4, 10)] for y, m, d in passovers: self.assertEqual(holidays.passover(y, eve=1), (y, m, d)) rosh_hashanahs = [ (2014, 9, 24), (2015, 9, 13), (2016, 10, 2), (2017, 9, 20), ] for y, m, d in rosh_hashanahs: self.assertEqual(holidays.rosh_hashanah(y, eve=1), (y, m, d)) self.assertEqual(holidays.hanukkah(2015, True), (2015, 12, 6)) self.assertEqual(holidays.hanukkah(2015), (2015, 12, 7)) self.assertEqual(holidays.yom_kippur(2015), (2015, 9, 23)) self.assertEqual(holidays.yom_kippur(2015, True), (2015, 9, 22)) sukkots = [ (2016, 10, 17), (2015, 9, 28), ] for y, m, d in sukkots: self.assertEqual(holidays.sukkot(y, eve=0), (y, m, d)) shavuots = [(2016, 6, 12), (2015, 5, 24)] for y, m, d in shavuots: self.assertEqual(holidays.shavuot(y, eve=0), (y, m, d)) purims = [(2017, 3, 12), (2016, 3, 24)] for y, m, d in purims: self.assertEqual(holidays.purim(y, eve=0), (y, m, d)) tisha_bavs = [ (2019, 8, 11), (2020, 7, 30), (2021, 7, 18), (2022, 8, 7), (2023, 7, 27), ] for y, m, d in tisha_bavs: self.assertEqual(holidays.tisha_bav(y, eve=0), (y, m, d)) assert self.h.hanukkah == (2015, 12, 7) assert self.h.rosh_hashanah == (2015, 9, 14) assert self.h.yom_kippur == (2015, 9, 23) assert self.h.passover == (2015, 4, 4) assert self.h.tisha_bav == (2015, 7, 26) assert self.h.shemini_azeret == (2015, 10, 5) assert self.h.lag_baomer == (2015, 5, 7) assert self.h.tu_beshvat == (2015, 2, 4) def test_mexican_holidays(self): self.assertEqual(holidays.natalicio_benito_juarez(2015, False), (2015, 3, 21)) self.assertEqual(holidays.natalicio_benito_juarez(2015), (2015, 3, 16)) assert self.h.dia_constitucion == (2015, 2, 2) assert self.h.natalicio_benito_juarez == (2015, 3, 16) assert self.h.dia_independencia == (2015, 9, 16) assert self.h.dia_revolucion == (2015, 11, 16) def test_usa_holidays(self): assert self.h.independence_day == (2015, 7, 3) assert self.h.flag_day == (2015, 6, 14) assert self.h.election_day == (2015, 11, 3) assert self.h.presidents_day == (2015, 2, 16) assert self.h.washingtons_birthday == (2015, 2, 22) assert self.h.lincolns_birthday == (2015, 2, 12) assert self.h.memorial_day == (2015, 5, 25) assert self.h.labor_day == (2015, 9, 7) assert self.h.indigenous_peoples_day == (2015, 10, 12) assert self.h.veterans_day == (2015, 11, 11) assert self.h.martin_luther_king_day == (2015, 1, 19) def test_usa_holidays_observed(self): self.assertSequenceEqual(holidays.independence_day(2015), (2015, 7, 4)) assert holidays.independence_day(2015, True) == (2015, 7, 3) assert holidays.washingtons_birthday(2015) == (2015, 2, 22) assert holidays.washingtons_birthday(2015, True) == (2015, 2, 16) assert holidays.washingtons_birthday(2020, True) == (2020, 2, 17) assert holidays.new_years(2022, True) == (2021, 12, 31) self.assertSequenceEqual(holidays.christmas(2021, True), (2021, 12, 24)) def test_deprecated_columbus_day(self): with self.assertRaises(DeprecationWarning): holidays.columbus_day(2020) def test_islamic_holidays(self): """Test the dates of certain Islamic holidays.""" holidays_2015 = { 'eid_aladha': (2015, 9, 24), 'ramadan': (2015, 6, 18), 'eid_alfitr': (2015, 7, 18), } with self.subTest(): for name, date in holidays_2015.items(): self.assertEqual(getattr(self.h, name), date, name) h21 = holidays.Holidays(2021) holidays_2021 = { 'eid_aladha': (2021, 7, 20), 'ramadan': (2021, 4, 13), 'eid_alfitr': (2021, 5, 13), } with self.subTest(): for name, date in holidays_2021.items(): self.assertEqual(getattr(h21, name), date, name) convertdate-2.3.2/tests/test_indian_civil.py000066400000000000000000000035051401655151000212400ustar00rootroot00000000000000# -*- coding: utf-8 -*- import time from convertdate import gregorian, indian_civil from . import CalTestCase class TestConvertdate(CalTestCase): def setUp(self): self.tm = time.localtime() self.gregoriandate = (self.tm[0], self.tm[1], self.tm[2]) self.jd = gregorian.to_jd(self.gregoriandate[0], self.gregoriandate[1], self.gregoriandate[2]) self.c_greg = (1492, 10, 21) self.c = gregorian.to_jd(*self.c_greg) self.x = gregorian.to_jd(2016, 2, 29) self.jdcs = range(2159677, 2488395, 2000) def test_reflexive(self): self.reflexive(indian_civil) def test_inverse(self): self.assertEqual(self.jd, indian_civil.to_jd(*indian_civil.from_jd(self.jd))) def test_returntype(self): '''Check that from_jd, from_gregorian return integers''' self.assertSequenceType(indian_civil.from_jd(self.jd), int) self.assertSequenceType(indian_civil.from_gregorian(*self.c_greg), int) self.assertSequenceType(indian_civil.from_gregorian(2020, 6, 4), int) def test_negative_jd(self): self.assertSequenceEqual(indian_civil.from_jd(1.5), (-4791, 9, 5)) self.assertSequenceEqual(indian_civil.from_jd(0.5), (-4791, 9, 4)) self.assertSequenceEqual(indian_civil.from_jd(-0.5), (-4791, 9, 3)) self.assertSequenceEqual(indian_civil.from_jd(-1.5), (-4791, 9, 2)) def test_month_length_indian_civil(self): self.assertEqual(indian_civil.month_length(1922, 1), 31) self.assertEqual(indian_civil.month_length(1923, 1), 30) def test_monthcalendar_indian_civil(self): self.assertEqual(indian_civil.monthcalendar(1936, 8).pop(0).pop(4), 1) self.assertEqual(indian_civil.monthcalendar(1927, 2).pop(0).pop(4), 1) self.assertEqual(indian_civil.monthcalendar(1922, 1).pop().pop(4), 31) convertdate-2.3.2/tests/test_julian.py000066400000000000000000000037471401655151000201020ustar00rootroot00000000000000from convertdate import julian import pytz from . import CalTestCase # 1492, 10, 12 C = 2266295.5 class TestJulian(CalTestCase): def test_julian_legal_date(self): try: julian.to_jd(1900, 2, 29) except ValueError: self.fail('Unexpected ValueError: "julian.to_jd(1900, 2, 29)"') self.assertRaises(ValueError, julian.to_jd, 2014, 2, 29) self.assertRaises(ValueError, julian.to_jd, 2014, 3, 32) self.assertRaises(ValueError, julian.to_jd, 2014, 4, 31) self.assertRaises(ValueError, julian.to_jd, 2014, 5, -1) def test_reflexive_julian(self): self.reflexive(julian) self.reflexive(julian, range(113957, 1574957, 365)) self.assertEqual(julian.from_jd(julian.to_jd(-4718, 3, 5)), (-4718, 3, 5)) def test_from_julian(self): jd = 2457447.5 self.assertEqual(jd, julian.to_jd(*julian.from_jd(jd))) self.assertEqual(julian.from_jd(C), (1492, 10, 12)) self.assertEqual(julian.from_jd(2400000.5), (1858, 11, 5)) self.assertEqual(julian.from_jd(2399830.5), (1858, 5, 19)) self.assertEqual(julian.from_jd(0), (-4712, 1, 1)) self.assertEqual(julian.from_jd(-1763), (-4717, 3, 5)) def test_julian_inverse(self): self.reflexive(julian) def test_to_julian(self): self.assertEqual(julian.to_jd(1858, 11, 5), 2400000.5) self.assertEqual(julian.to_jd(1492, 10, 12), C) def test_month_length_julian(self): self.assertEqual(julian.month_length(1582, 10), 31) self.assertEqual(julian.month_length(1977, 2), 28) self.assertEqual(julian.month_length(1900, 2), 29) self.assertEqual(julian.month_length(1904, 2), 29) def test_monthcalendar_julian(self): self.assertEqual(julian.monthcalendar(1582, 10).pop(0).pop(1), 1) self.assertEqual(julian.monthcalendar(1582, 10).pop().pop(3), 31) def test_returntype(self): self.assertSequenceType(julian.from_gregorian(2020, 6, 4), int) convertdate-2.3.2/tests/test_mayan.py000066400000000000000000000061441401655151000177170ustar00rootroot00000000000000# -*- coding: utf-8 -*- import time from convertdate import gregorian, mayan from . import CalTestCase class TestMayan(CalTestCase): def setUp(self): self.gdate = 2021, 2, 5 self.c_greg = (1492, 10, 21) self.c = gregorian.to_jd(*self.c_greg) self.jd = gregorian.to_jd(*self.gdate) self.jdcs = range(2159677, 2488395, 2000) def test_mayan_reflexive(self): assert self.jd == mayan.to_jd(*mayan.from_jd(self.jd)) self.reflexive(mayan) def test_mayan_count(self): assert mayan.to_jd(13, 0, 0, 0, 0) == 2456282.5 assert mayan.from_gregorian(2012, 12, 21) == (13, 0, 0, 0, 0) assert mayan.to_gregorian(13, 0, 0, 0, 0) == (2012, 12, 21) assert mayan.from_jd(self.c) == (11, 13, 12, 4, 13) def test_mayan_haab(self): # haab assert mayan.HAAB[2] == 'Zip' assert mayan.HAAB.index("Xul") == 5 assert mayan.to_haab(self.c) == (16, "Sotz'") assert mayan.to_haab(2456282.5) == (3, "K'ank'in") def test_mayan_tzolkin(self): # tzolkin assert mayan.TZOLKIN[0] == "Imix'" assert mayan.to_tzolkin(self.c) == (12, "B'en") assert mayan.to_tzolkin(2456282.5) == (4, 'Ajaw') assert mayan.to_tzolkin(2456850.5) == (13, 'Lamat') def test_mayan_convenience(self): self.assertEqual(mayan.lc_to_haab(0, 0, 0, 0, 0), (8, "Kumk'u")) assert mayan.lc_to_tzolkin(0, 0, 0, 0, 0) == (4, "Ajaw") assert mayan.lc_to_tzolkin(9, 16, 12, 5, 17) == (6, "Kab'an") assert mayan.lc_to_haab(9, 16, 12, 5, 17) == (10, "Mol") assert mayan.lc_to_haab_tzolkin(9, 16, 12, 5, 17) == "6 Kab'an 10 Mol" assert mayan.translate_haab("Wayeb'") == 'Nameless' def test_mayan_predictions(self): assert mayan.next_haab("Sotz'", self.c) == 2266280.5 for h in mayan.HAAB: assert mayan.to_haab(mayan.next_haab(h, self.c)) == (1, h) assert mayan.next_tzolkin_haab((13, "Ajaw"), (3, "Kumk'u"), 2456849.5) == 2463662.5 def test_mayan_monthcalendar(self): calendar = mayan.haab_monthcalendar(13, 0, 2, 11, 13) row = calendar[0] square = row[-1] assert isinstance(row, list) assert isinstance(square, tuple) assert row[7][0] == 1 assert mayan.to_jd(*calendar[-1][-1][-1]) == 19 + mayan.to_jd(13, 0, 2, 11, 13) self.assertEqual(square, (6, (13, "Etz'nab'"), (13, 0, 2, 11, 18))) def test_mayan_generators(self): lcg = mayan.longcount_generator(13, 0, 2, 11, 13) assert next(lcg) == (13, 0, 2, 11, 13) assert next(lcg) == (13, 0, 2, 11, 14) assert next(lcg) == (13, 0, 2, 11, 15) tzg = mayan.tzolkin_generator(9, "Ix") self.assertEqual(next(tzg), (9, "Ix")) assert next(tzg) == (10, "Men") assert next(tzg) == (11, "K'ib'") def test_start_epoch(self): self.assertSequenceEqual(mayan.from_jd(mayan.EPOCH + 1), (0, 0, 0, 0, 1)) self.assertSequenceEqual(mayan.from_jd(mayan.EPOCH), (0, 0, 0, 0, 0)) with self.assertRaises(ValueError): mayan.from_jd(mayan.EPOCH - 1) convertdate-2.3.2/tests/test_ordinal.py000066400000000000000000000052361401655151000202430ustar00rootroot00000000000000from calendar import isleap from convertdate import ordinal from . import CalTestCase class TestOrdinal(CalTestCase): def test_reflexive(self): self.reflexive(ordinal, range(2458849, 2458849 + 7289)) def test_to_jd(self): self.assertEqual(ordinal.to_jd(1900, 1), 2415020.5) def test_from_jd(self): self.assertEqual(ordinal.from_jd(2415020.5), (1900, 1)) def test_ordinal_to_gregorian(self): self.assertEqual(ordinal.to_gregorian(2013, 1), (2013, 1, 1)) self.assertEqual(ordinal.to_gregorian(2013, 105), (2013, 4, 15)) self.assertEqual(ordinal.to_gregorian(2013, 32), (2013, 2, 1)) self.assertEqual(ordinal.to_gregorian(2012, 1), (2012, 1, 1)) self.assertEqual(ordinal.to_gregorian(2012, 31), (2012, 1, 31)) self.assertEqual(ordinal.to_gregorian(2012, 32), (2012, 2, 1)) self.assertEqual(ordinal.to_gregorian(2012, 52), (2012, 2, 21)) self.assertEqual(ordinal.to_gregorian(2012, 59), (2012, 2, 28)) self.assertEqual(ordinal.to_gregorian(2012, 60), (2012, 2, 29)) self.assertEqual(ordinal.to_gregorian(2012, 61), (2012, 3, 1)) self.assertEqual(ordinal.from_gregorian(2013, 1, 1), (2013, 1)) self.assertEqual(ordinal.from_gregorian(2013, 2, 1), (2013, 32)) self.assertEqual(ordinal.from_gregorian(2013, 3, 1), (2013, 60)) self.assertEqual(ordinal.from_gregorian(2013, 4, 15), (2013, 105)) def test_jan_1(self): self.assertEqual(ordinal.from_gregorian(2000, 1, 1), (2000, 1)) self.assertEqual(ordinal.from_gregorian(2004, 1, 1), (2004, 1)) self.assertEqual(ordinal.from_gregorian(1, 1, 1), (1, 1)) def test_dec_31(self): self.assertEqual(ordinal.to_gregorian(2001, 364), (2001, 12, 30), 'December 30, 2001') self.assertEqual(ordinal.to_gregorian(2004, 365), (2004, 12, 30)) self.assertEqual(ordinal.to_gregorian(2001, 365), (2001, 12, 31)) self.assertEqual(ordinal.to_gregorian(2004, 366), (2004, 12, 31)) self.assertEqual(ordinal.from_gregorian(2001, 12, 30), (2001, 364)) self.assertEqual(ordinal.from_gregorian(2004, 12, 30), (2004, 365)) self.assertEqual(ordinal.from_gregorian(2001, 12, 31), (2001, 365)) self.assertEqual(ordinal.from_gregorian(2004, 12, 31), (2004, 366)) def test_leap(self): for year in range(1995, 2005): self.assertEqual(ordinal.from_gregorian(year, 2, 28), (year, 59)) leap = 0 if isleap(year): leap = 1 self.assertEqual(ordinal.from_gregorian(year, 2, 29), (year, 60)) self.assertEqual(ordinal.from_gregorian(year, 3, 1), (year, 60 + leap)) convertdate-2.3.2/tests/test_persian.py000066400000000000000000000074131401655151000202530ustar00rootroot00000000000000# -*- coding: utf-8 -*- from convertdate import gregorian, persian from . import CalTestCase # fmt: off JDS = ( 2130575, 2131306, 2132036, 2132767, 2133497, 2134228, 2134958, 2135689, 2136419, 2137150, 2137880, 2138611, 2139341, 2140072, 2140802, 2141533, 2142263, 2142994, 2143724, 2144455, 2145185, 2145916, 2146646, 2147377, 2148107, 2148838, 2149568, 2150299, 2151029, 2151759, 2152490, 2153220, 2153951, 2154681, 2155412, 2156142, 2156873, 2157603, 2158334, 2159064, 2159795, 2160525, 2161256, 2161986, 2162717, 2163447, 2164178, 2164908, 2165639, 2166369 ) # fmt: on class testPersian(CalTestCase): def setUp(self): self.gdate = 2021, 2, 5 self.jd = gregorian.to_jd(*self.gdate) self.jdcs = range(2159677, 2488395, 2000) def test_equinox_jd(self): data = [ (1000, 2086381), (1100, 2122905), (1199, 2159064), (1200, 2159430), (1201, 2159795), (1300, 2195954), (1400, 2232478), (1500, 2269002), (1600, 2305527), (1700, 2342051), (1800, 2378575), (1900, 2415099), (2000, 2451623), ] for gyear, jd in data: with self.subTest(y=gyear, jd=jd): self.assertEqual(persian.equinox_jd(gyear), jd) self.assertAlmostEqual(persian.equinox_jd(1620), 2312831, places=0) self.assertAlmostEqual(persian.equinox_jd(2021), 2459294, places=0) def test_inverse(self): self.assertEqual(self.jd, persian.to_jd(*persian.from_jd(self.jd))) def test_reflexive(self): self.reflexive(persian) def test_reverse_reflexive(self): date = 579, 9, 2 self.assertEqual(persian.from_jd(persian.to_jd(*date)), date, 'from_jd(to_jd(*x)) == x') def test_to_jd_579(self): date = 579, 9, 2 self.assertEqual(persian.to_jd(*date), 2159677.5) def test_from_jd_579(self): date = 579, 9, 2 self.assertEqual(persian.from_jd(2159677.5), date) def test_leap(self): self.assertEqual(persian.leap(-101), False) def test_leapconvert(self): jd = 2121444.5 self.assertSequenceEqual(persian.from_jd(jd), (475, 1, 1)) self.assertSequenceEqual(persian.from_jd(jd - 2), (474, 12, 28)) self.assertSequenceEqual(persian.from_jd(jd - 1), (474, 12, 29)) jd = 2121809.5 self.assertSequenceEqual(persian.from_jd(jd), (475, 12, 30)) self.assertSequenceEqual(persian.from_jd(jd + 1), (476, 1, 1)) def test_newyears(self): years = (1, 750, 625, 600, 580, 1000, 1400) jds = (1948320, 2221886, 2176231, 2167100, 2159795, 2313197, 2459294) for y, jd in zip(years, jds): jd = jd + 0.5 with self.subTest(y=y, jd=jd): self.assertEqual(persian.to_jd(y, 1, 1), jd) with self.subTest(jd=jd, y=y): self.assertEqual(persian.from_jd(jd), (y, 1, 1)) def test_examples(self): pairs = zip(range(500, 600, 2), JDS) for y, jd in pairs: jd = jd + 0.5 with self.subTest(y=y, jd=jd): self.assertEqual(persian.to_jd(y, 1, 1), jd) with self.subTest(jd=jd, y=y): self.assertEqual(persian.from_jd(jd), (y, 1, 1)) self.assertEqual(persian.to_jd(2021, 3, 21), 2686191.5) self.assertEqual(persian.to_jd(2021, 3, 20), 2686190.5) def test_month_length_persian(self): self.assertEqual(persian.month_length(1354, 12), 30) self.assertEqual(persian.month_length(1355, 12), 29) def test_monthcalendar_persian(self): self.assertEqual(persian.monthcalendar(1393, 8).pop(0).pop(4), 1) self.assertEqual(persian.monthcalendar(1393, 8).pop().pop(0), 25) convertdate-2.3.2/tests/test_positivist.py000066400000000000000000000102431401655151000210220ustar00rootroot00000000000000# -*- coding: utf-8 -*- import unittest from convertdate.data import positivist as data from convertdate.positivist import EPOCH, dayname, festival, from_gregorian, from_jd, legal_date, to_gregorian, to_jd class TestGregorian(unittest.TestCase): def setUp(self): pass def test_epoch(self): self.assertEqual(to_jd(1, 1, 1), EPOCH) self.assertEqual(to_jd(1, 1, 2), EPOCH + 1) self.assertEqual(to_jd(2, 1, 1), EPOCH + 365.0) self.assertEqual(from_jd(EPOCH), (1, 1, 1)) def test_to_gregorian(self): self.assertEqual(to_gregorian(228, 13, 25), (2016, 12, 26)) self.assertEqual(to_gregorian(228, 13, 25), (2016, 12, 26)) def test_legaldate(self): self.assertTrue(legal_date(1, 1, 1)) with self.assertRaises(ValueError): legal_date(0, 1, 1) with self.assertRaises(ValueError): legal_date(1, -1, 1) with self.assertRaises(ValueError): legal_date(1, 14, 3) with self.assertRaises(ValueError): legal_date(1, 16, 3) def test_from_jd(self): self.assertTrue(legal_date(*from_jd(2375479.5))) assert legal_date(*from_jd(2376479.5)) assert legal_date(*from_jd(2378479.5)) assert legal_date(*from_jd(2379479.5)) with self.assertRaises(ValueError): from_jd(EPOCH - 0.5) def test_reflexive_jd(self): self.assertEqual(from_jd(to_jd(1, 1, 1)), (1, 1, 1)) self.assertEqual(from_jd(to_jd(4, 1, 1)), (4, 1, 1)) self.assertEqual(from_jd(to_jd(4, 14, 1)), (4, 14, 1)) self.assertEqual(from_jd(to_jd(4, 14, 2)), (4, 14, 2)) self.assertEqual(from_jd(to_jd(10, 1, 1)), (10, 1, 1)) self.assertEqual(from_jd(to_jd(12, 1, 1)), (12, 1, 1)) self.assertEqual(from_jd(to_jd(13, 1, 1)), (13, 1, 1)) self.assertEqual(from_jd(to_jd(13, 1, 2)), (13, 1, 2)) self.assertEqual(from_jd(to_jd(13, 1, 3)), (13, 1, 3)) self.assertEqual(from_jd(to_jd(13, 1, 5)), (13, 1, 5)) self.assertEqual(from_jd(to_jd(13, 1, 7)), (13, 1, 7)) self.assertEqual(from_jd(to_jd(13, 1, 14)), (13, 1, 14)) self.assertEqual(from_jd(to_jd(13, 1, 28)), (13, 1, 28)) self.assertEqual(from_jd(to_jd(13, 2, 28)), (13, 2, 28)) self.assertEqual(from_jd(to_jd(13, 6, 1)), (13, 6, 1)) self.assertEqual(from_jd(to_jd(14, 1, 1)), (14, 1, 1)) self.assertEqual(from_jd(to_jd(16, 1, 1)), (16, 1, 1)) self.assertEqual(from_jd(to_jd(50, 1, 1)), (50, 1, 1)) self.assertEqual(from_jd(to_jd(99, 1, 1)), (99, 1, 1)) self.assertEqual(from_jd(to_jd(100, 1, 1)), (100, 1, 1)) self.assertEqual(from_jd(to_jd(100, 13, 25)), (100, 13, 25)) self.assertEqual(from_jd(to_jd(120, 13, 25)), (120, 13, 25)) self.assertEqual(from_jd(to_jd(50, 13, 25)), (50, 13, 25)) self.assertEqual(from_jd(to_jd(200, 1, 5)), (200, 1, 5)) self.assertEqual(from_jd(to_jd(250, 14, 1)), (250, 14, 1)) def test_reflexive_jd2(self): assert len(from_jd(2375479.5)) == 3 self.assertEqual(to_jd(*from_jd(2375479.5)), 2375479.5) self.assertEqual(to_jd(*from_jd(2376479.5)), 2376479.5) self.assertEqual(to_jd(*from_jd(2378479.5)), 2378479.5) self.assertEqual(to_jd(*from_jd(2379479.5)), 2379479.5) def test_reflexive_gregorian(self): self.assertEqual(from_gregorian(*to_gregorian(100, 13, 25)), (100, 13, 25)) self.assertEqual(from_gregorian(*to_gregorian(120, 13, 25)), (120, 13, 25)) self.assertEqual(from_gregorian(*to_gregorian(50, 13, 25)), (50, 13, 25)) self.assertEqual(from_gregorian(*to_gregorian(200, 1, 5)), (200, 1, 5)) self.assertEqual(from_gregorian(*to_gregorian(250, 14, 1)), (250, 14, 1)) def test_named_day(self): self.assertEqual(dayname(228, 13, 25), ('Bichat', "Félix Vicq-d'Azyr")) self.assertEqual(dayname(228, 1, 1), ('Moses', "Cadmus")) self.assertEqual(dayname(227, 1, 1), ('Moses', "Prometheus")) self.assertEqual(dayname(1, 1, 1), ('Moses', "Prometheus")) def test_festival(self): self.assertIsNone(festival(1, 2)) self.assertEqual(festival(1, 1), data.FESTIVALS.get((1, 1))) convertdate-2.3.2/tests/test_utils.py000066400000000000000000000015171401655151000177510ustar00rootroot00000000000000# -*- coding: utf-8 -*- import math import unittest from convertdate import utils class TestConvertdate(unittest.TestCase): def testCeil(self): self.assertEqual(utils.ceil(1.2), math.ceil(1.2)) self.assertEqual(utils.ceil(-1.2), math.ceil(-1.2)) def testTruncFloor(self): self.assertEqual(math.trunc(1.2), math.floor(1.2)) self.assertNotEqual(math.trunc(-1.2), math.floor(-1.2)) def test_jwday(self): self.assertEqual(utils.jwday(2459252.5), 6) self.assertEqual(utils.weekday_before(0, 2459252.5), 2459252.5 - 6) self.assertEqual(utils.jwday(2459252.5), 6) self.assertEqual(utils.weekday_before(0, 2459252.5), 2459252.5 - 6) self.assertEqual(utils.jwday(0.5), 1) self.assertEqual(utils.jwday(-0.5), 0) self.assertEqual(utils.jwday(-1.5), 6) convertdate-2.3.2/tox.ini000066400000000000000000000005541401655151000153510ustar00rootroot00000000000000# This file is part of convertdate. # http://github.com/fitnr/convertdate # Licensed under the MIT license: # http://opensource.org/licenses/MIT # Copyright (c) 2016, fitnr [tox] envlist = pypy, py36, py37, py38, py39, pylint [testenv] commands = python -m unittest [testenv:pylint] deps = pylint commands = pylint convertdate/ tests/