thai_lunar 0.1.0 copy "thai_lunar: ^0.1.0" to clipboard
thai_lunar: ^0.1.0 copied to clipboard

Pure-Dart Thai lunar calendar: Gregorian conversion, athikamat/athikavar year types, and Buddhist holiday full moons (Makha, Visakha, Asalha).

thai_lunar #

pub version license: MIT

A pure-Dart, dependency-free Thai lunar calendar (จันทรคติ / chantarakati, Suriyayatra) engine.

It converts between Gregorian and Thai lunar dates, classifies lunar year types (อธิกมาส athikamat / อธิกวาร athikavar), and computes the Buddhist holidays that fall on full moons — Makha Bucha, Visakha Bucha, Asalha Bucha — plus wan phra (Buddhist sabbath) days by the conventional civil lunar reckoning (waxing 8 & 15, waning 8, and the last day of the lunar month).

All arithmetic is integer — these are integer algorithms; floating point drifts.

Features #

  • Gregorian → Thai lunar conversion (gregorianToThaiLunar) and the exact inverse (thaiLunarToGregorian) — round-trips losslessly for every day.
  • Lunar year classification: normal / athikavar (extra day) / athikamat (extra month) via lunarYearType, isAthikamat, isAthikavar.
  • Movable Buddhist holiday full moons via fullMoonOf (Makha Bucha date, Visakha Bucha date, Asalha Bucha date), with the athikamat month shift and the doubled-month-8 (secondEighth) handled for you.
  • Wan phra (Buddhist sabbath) detection: top-level isWanPhra(DateTime) and the computed ThaiLunarDate.isWanPhra getter.
  • เสาร์ห้า (Sao Ha) finder — the rare auspicious Saturday on the 5th of lunar month 5 — via isSaoHa, saoHaType, saoHaDatesIn and nextSaoHa.
  • A rich, value-equal ThaiLunarDate (== / hashCode / copyWith, Comparable so a List sorts chronologically) exposing beYear, ceYear, csYear, month, phase, day, isFullMoon, weekday, isSecondEighth and isYearEndWrap.
  • BE / CE era-aware API (ThaiEra) with beToCe / ceToBe helpers.
  • Zero dependencies, pure Dart.

Install #

dependencies:
  thai_lunar: ^0.1.0

Usage #

import 'package:thai_lunar/thai_lunar.dart';

// Gregorian -> Thai lunar
final lunar = gregorianToThaiLunar(DateTime.utc(2000, 1, 1));
print(lunar);                 // แรม 9 ค่ำ เดือน 1 พ.ศ. 2542
print(lunar.beYear);          // 2542  (Buddhist Era; the lunar year had not
print(lunar.ceYear);          // 1999  yet rolled over on 1 Jan)
print(lunar.csYear);          // 1361  (Chula Sakarat)
print(lunar.weekday);         // 6     (Saturday; 1=Mon..7=Sun)
print(lunar.isFullMoon);      // false
print(lunar.isWanPhra);       // false (computed from phase/day/month-length)

// Year classification (BE by default; pass era: ThaiEra.ce for CE years)
lunarYearType(2026, era: ThaiEra.ce);   // ThaiLunarYearType.extraMonth
isAthikamat(2026, era: ThaiEra.ce);     // true  (leap month: doubled month 8)
isAthikavar(2025, era: ThaiEra.ce);     // true  (leap day in month 7)

// Holidays — full moon of a lunar month, landing in the given calendar year.
// In an athikamat year the conventional months shift (Makha 3->4, Visakha
// 6->7, Asalha -> the SECOND month 8).
fullMoonOf(2026, 4, era: ThaiEra.ce);                 // Makha   2026-03-03
fullMoonOf(2026, 7, era: ThaiEra.ce);                 // Visakha 2026-05-31
final asalha = fullMoonOf(2026, 8, era: ThaiEra.ce, secondEighth: true); // 2026-07-29
final khaoPhansa = asalha.add(const Duration(days: 1));                  // 2026-07-30

// Wan phra (Buddhist sabbath)
isWanPhra(DateTime.utc(2026, 5, 31));   // true (Visakha full moon)

// Era helpers
beToCe(2569);   // 2026
ceToBe(2026);   // 2569

เสาร์ห้า (Sao Ha) #

เสาร์ห้า is a Saturday that coincides with the 5th day of lunar month 5 (เดือน 5) — either the waxing 5th (ขึ้น 5 ค่ำ) or the waning 5th (แรม 5 ค่ำ). It is the strongest auspicious day in Thai belief for consecrating amulets and วัตถุมงคล (sacred objects). It is rare: it does not occur every year, arriving roughly once every 2–3 years. Two grades:

  • เสาร์ห้าใหญ่ (SaoHaType.major) — Saturday + ขึ้น 5 ค่ำ เดือน 5 (waxing). The rarer, "greater" grade.
  • เสาร์ห้าน้อย (SaoHaType.minor) — Saturday + แรม 5 ค่ำ เดือน 5 (waning).
// Classify a single day.
isSaoHa(DateTime.utc(2024, 4, 13));     // true
saoHaType(DateTime.utc(2024, 4, 13));   // SaoHaType.major  (ขึ้น 5 ค่ำ เดือน 5)
saoHaType(DateTime.utc(2011, 4, 23));   // SaoHaType.minor  (แรม 5 ค่ำ เดือน 5)
saoHaType(DateTime.utc(2024, 1, 6));    // null  (an ordinary Saturday)

// All เสาร์ห้า in a Gregorian year (usually none).
saoHaDatesIn(2024);   // [2024-04-13]  (major)
saoHaDatesIn(2022);   // []            (none that year)

// The next one on/after a date (searches forward ~30 years; null if none).
nextSaoHa(DateTime.utc(2021, 1, 1));    // 2024-04-13

Validated range #

The engine is validated against the official Thai calendar for roughly 1900–2050 CE (the range over which the conversion and holiday APIs are tested and supported). The underlying arithmetic is a Suriyayatra reconstruction that runs beyond those bounds, but before the early-20th-century standardisation of the Thai calendar it diverges from the official record, so fullMoonOf and thaiLunarToGregorian throw ArgumentError for input outside this range. Year-type classifiers (lunarYearType etc.) do not throw and may be used beyond the range with this caveat in mind.

Notes & caveats #

  • Calendar-day contract. gregorianToThaiLunar uses only the DateTime's own year / month / day; the time of day and the time zone are ignored, so you get the Thai lunar date for that wall-clock calendar day. To convert "the UTC day" instead, pass date.toUtc().
  • fullMoonOf returns the occurrence of that lunar month's full moon whose Gregorian date falls within the requested calendar year. A lunar year straddles the Gregorian boundary, so an early month (1..4) belongs to the lunar year that began the previous Gregorian year — this is handled for you.
  • Months 5 and 6 each occur twice in a Gregorian year — once at the head of a lunar year and once again as the previous lunar year wraps round at its end. The year-end occurrence is flagged via ThaiLunarDate.isYearEndWrap and carries the BE year of the lunar year it closes (= CS year + 1181), matching the convention a Thai reader expects for those tail days. Because of this flag thaiLunarToGregorian(gregorianToThaiLunar(d)) == d is exact for every day, including the wrap days.
  • thai_holidays — Thai public holiday dates (uses lunar holidays like these).
  • The same publisher also maintains the Thai-numerals toolkit thainum and a Thai PromptPay helper thai_promptpay.

Attribution #

This package is a faithful port of pythaidate by Mark Hollow (MIT, © 2023). The underlying algorithm derives from J.C. Eade, The Calendrical Systems of Mainland South-East Asia (Brill, 1995). See NOTICE.md.

License #

MIT — see LICENSE.

0
likes
160
points
79
downloads

Documentation

API reference

Publisher

verified publisher10v3n4m.cc

Weekly Downloads

Pure-Dart Thai lunar calendar: Gregorian conversion, athikamat/athikavar year types, and Buddhist holiday full moons (Makha, Visakha, Asalha).

Repository (GitHub)
View/report issues

Topics

#thai #calendar #lunar #buddhist #date

License

MIT (license)

More

Packages that depend on thai_lunar