Skip to main content

Date classes for Thai calendar systems.

Project description

pythaidate: A Python Library for Thai Calendar Systems

Thailand has used several calendar systems during its history with several still in use today. This library provides datetime.date-like classes for working with the Thai lunisolar calendar of the Chulasakarat Era (จุลศักราช) and the lunar Pakkhakhananaa calendar (ปฏิทินปักขคณนา).

Installation

$ python3 -m pip install pythaidate

Examples

CsDate: Chulasakarat Date

CsDate objects can be created from a year, month, day triple, like a datetime.date object. They represent the Thai lunisolar calendar with the epoch of 22nd March 638 AD. Months should be specified in Sukothai number format (eg. 5 is the first month). The example here specifies month 1 which, according to Sukothai numbering, is the 9th month in the year (although the 10th month in a year with intercalary month). Intercalary months (อธิกมาส) are specified as 88.

>>> from pythaidate import CsDate
>>> cs = CsDate(1361, 1, 24)
>>> cs.year, cs.month, cs.day
(1361, 1, 24)

The days property gives the zero-indexed count of days since new years day.

>>> cs.days
260

The horakhun (หรคุฌ) property gives the days since the epoch and julianday gives the Julian Day Number, useful for converting between calendar formats.

>>> cs.horakhun
497378
>>> cs.julianday
2451545

Other properties show the internal calculation values:

  • kammabucala: (กัมมัขผล) the excess of solar days over whole solar days
  • masaken: (มาสเกฌฑ์) The number of lunar months since the epoch
  • uccapon: (อุจจพล) The measure of the position of the Moon's apogee (furthest distance from the Earth). It increases by one unit a day to a maximum of 3232.
  • avoman: (อวมาน) The excess of lunar days over solar days in units of 1/692 of a lunar day modulus 692, increasing by 11 units each solar day. It is used to determine when to add intercalary days in the calendar
  • tithi: (ดิถี) a lunar day, equal to 1/30th of a synodic month

The year and day count since new years day can also be used to create a CsDate object with the fromyd class method:

>>> cs = CsDate.fromyd(1361, 260)
>>> cs.julianday
2451545

Similarly, a CsDate object can be created from the Julian Day Number:

>>> cs = CsDate.fromjulianday(2451545)
>>> cs.year, cs.month, cs.day
(1361, 1, 24)

A CsDate can be displayed as text with .csformat() or by converting the object to a string:

>>> cs.csformat()
'วันเสาร์ เดือน ๑ แรม ๙ ค่ำ ปีเถาะ จ.ศ.๑๓๖๑'
>>> str(cs)
'วันเสาร์ เดือน ๑ แรม ๙ ค่ำ ปีเถาะ จ.ศ.๑๓๖๑'

CsDate objects have 3 properties for intercalations and a day count:

  • solar_leap_year: for the solar leap year (อธิกสุรทิน)
  • leap_day: for the lunar intercalary day (อธิกวาร)
  • leap_month: for the lunar intercalary month (อธิกมาส)
  • days_in_year: returns the number of days in the year. This will be one of:
    • 354: no intercalations (ปกติมาส ปกติวาร)
    • 355: intercalary month, no intercalary day (ปกติมาส อธิกวาร)
    • 384: no intercalary month, intercalary day (อธิกมาส ปกติวาร)

In the Thai lunisolar calendar system a year can only have either zero or one intercalations. There can't be both an intercalary day (อธิกวาร) and month (อธิกมาส) in the same year.

>>> cs.solar_leap_year
False
>>> cs.leap_day
False
>>> cs.leap_month
True
>>> cs.days_in_year
384

PakDate: Pakkhakhananaa Date

Create a PakDate object from a pakcode. The 1- prefix is the cycle number (1-indexed), followed by the ปักขคณนา, สัมพยุหะ, พยุหะ, สมุหะ, วรรค and day of moon phase. The Pakkhakhananaa cycle repeats every 289,577 days.

>>> from pythaidate import PakDate
>>> p = PakDate(pakcode="1-6:11:5:2:2:10")
>>> p.horakhun
96398
>>> p.julianday
2451545

Note that the horakhun value from Pakkhakhananaa lunar and (Chulasakarat era) lunisolar calendars are not compatible as they represent day count since the epoch of each calendar. For comparisons use julianday instead.

The Pakkhakhananaa code and abbreviations are available:

>>> p.pakcode
'1-6:11:5:2:2:10'
>>> print(p.pakabbr)
๖๑๕ข๒
 ๑

Pakkhakhananaa can be created from a datetime.date object:

>>> from datetime import date
>>> from pythaidate import PakDate
>>> p = PakDate(date=date(2000, 1, 1))
>>> p.julianday
2451545

...and from Julian Day Number:

>>> from pythaidate import PakDate
>>> p = PakDate(jd=2451545)
>>> p.julianday
2451545
>>> p.pakcode
'1-6:11:5:2:2:10'

pakboard() will display an ASCII Pakkhakhananaa board (กระดานปักขคณนา) and (best viewed with a fixed-width font):

>>> p.pakboard()
           ๑  ๒  ๓  ๔  ๕  ๖  ๗  ๘  ๙ ๑๐ ๑๑ ๑๒ ๑๓ ๑๔ ๑๕ ๑๖ ๑๗ ๑๘
ปักขคณนา    ม  ม  ม  ม  ม  ม  ม  ม  ม  ม  ม  ม  ม  ม  ม  ม  ม  จ
มหาสัมพยุหะ  จ  จ  จ  จ  จ  จ  จ  จ  จ  จ  ม
จุลสัมพยุหะ   จ  จ  จ  จ  จ  จ  จ  จ  จ  ม
มหาพยุหะ    ม  ม  ม  ม  ม  ม  จ
จุลพยุหะ     ม  ม  ม  ม  ม  จ
มหาสมุหะ    จ  จ  จ  ม
จุลสมุหะ     จ  จ  ม
มหาวรรค    ม  ม  ม  ม  จ
จุลวรรค     ม  ม  ม  จ
มหาปักข์     ๑  ๒  ๓  ๔  ๕  ๖  ๗  ๘  ๙ ๑๐ ๑๑ ๑๒ ๑๓ ๑๔ ๑๕
จุลปักข์      ๑  ๒  ๓  ๔  ๕  ๖  ๗  ๘  ๙ ๑๐ ๑๑ ๑๒ ๑๓ ๑๔
           รอบที่ ๑   หรคุณปักขคณนา ๙๖๓๙๘   ปักขเกณฑ์ ๖๕๒๙ 

Julian Day Number (JDN) helpers

  • to_julianday(year, month, day): Returns JDN from a year, month, day triple
  • from_julianday(jd): Returns a year, month, day triple from a JDN
  • today(): returns JDN for today
  • date_to_julianday(d): converts datetime.date object or other object with a julianday property to JDN
  • julianday_to_date(jd): converts JDN to a datetime.date object

Monkey patching datetime.date

The Julian Day Number is a useful way to convert between calendar systems. The CsDate and PakDate classes both have a .julianday property but Python's datetime.date doesn't. By default pythaidate will monkey patch datetime.date to add a .julianday property to add this useful feature. pythaidate (or a class from it) must be imported before importing datetime.date.

To disable this, set the PYTHAIDATE_NO_MONKEYPATCH environment variable to any non-empty value. Behaviour of pythaidate won't be affected if disabled as the conversion functions look for both date objects and julianday properties.

>>> from pythaidate import Chulasakarat
>>> from datetime import date
>>> hasattr(date, "julianday")
True
>>> from datetime import date
>>> from pythaidate import Chulasakarat
>>> hasattr(date, "julianday")
False

Limitations

General

  • Tested and supported on Python 3.8 - 3.12.

Chulasakarat Era Lunisolar Calendar

  • The determination of which years are intercalary has been a somewhat subjective process and changed over the centuries, along with regional variations too. This library produces 7 intercalary months per 19 year period and 11 intercalary days per 57 years. This maintains the overall "pace" of the calendar but there may be slight short-term deviations from other calendars. But don't worry, those other calendars are just as wrong too - there's no definitive reference calendar.
  • Currently only supports Sukothai-style month numbering (eg. first month of the year is month 5)
  • strftime and strptime are not implemented

Selected References

Thai

English

  • Eade, J.C. (2018). The Calendrical Systems of Mainland South-East Asia. Netherlands: Brill.
  • Gislén L., Eade, J.C. (2019). The Calendars of Southeast Asia 2: Burma, Thailand, Laos and Cambodia. Journal of Astronomical History and Heritage, 22(3).

French

  • Faraut, F. G. (1910). Astronomie cambodgienne. Vietnam: Imprimerie F.-H. Schneider.

  • Billard, R. L'Astronomie Indienne. Investigation des Textes Sanskrits et des Donnees Numeriques. Paris: Ecole francaise d'extreme-orient. (1971).

Other Resources

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pythaidate-0.1.6.tar.gz (756.4 kB view details)

Uploaded Source

Built Distribution

pythaidate-0.1.6-py3-none-any.whl (19.2 kB view details)

Uploaded Python 3

File details

Details for the file pythaidate-0.1.6.tar.gz.

File metadata

  • Download URL: pythaidate-0.1.6.tar.gz
  • Upload date:
  • Size: 756.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.9.16

File hashes

Hashes for pythaidate-0.1.6.tar.gz
Algorithm Hash digest
SHA256 542ccacc2d1c243037ebf63e9c45976c7e60db7f896e1a1195c5827ef6657b4f
MD5 72cc44041804222f5a9c0ea720d3e111
BLAKE2b-256 ae487b8bf84be0480669cc22d5c3d99dcc7796aeadde8cdd9e3cc9e19c167083

See more details on using hashes here.

File details

Details for the file pythaidate-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: pythaidate-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 19.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.9.16

File hashes

Hashes for pythaidate-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 6d27990823602bd250206a86fba6aaac771d3db12db024be56e26247e220ed48
MD5 971911a80a2f5ecf6626916e97936927
BLAKE2b-256 9170b41b6d814a86e546fbaee4c362c8a5f0c2945866458985c573827595c0a0

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page