“অধিমাস প্রতি তিন বছর পর আসে”—সাধারণ ব্যাখ্যা হিসেবে কথাটি কাছাকাছি, কিন্তু calculation rule হিসেবে ভুল। পঞ্জিকা engine-কে average year নয়, exact New Moon এবং exact নিরয়ণ সৌর-সংক্রান্তির instant তুলনা করতে হয়। তবেই মাসের identity, অধিমাসের নাম, পরবর্তী নিজ মাস এবং ক্ষয়মাসের বিরল sequence নির্ভরযোগ্যভাবে পাওয়া যায়।
দুটি জ্যোতির্বৈজ্ঞানিক ঘড়ি
ভারতীয় lunisolar calendar একই সঙ্গে দুইটি cycle অনুসরণ করে:
| Cycle | আনুমানিক দৈর্ঘ্য | Calendar-এ ভূমিকা |
|---|---|---|
| Synodic lunar month | ২৯.৫৩ দিন | অমাবস্যা থেকে পরের অমাবস্যা; তিথি ও পক্ষের পূর্ণ cycle |
| ১২টি lunar month | ৩৫৪.৩৭ দিন | একটি সাধারণ চান্দ্র বছর |
| Sidereal solar year | ৩৬৫.২৬ দিনের কাছাকাছি | সূর্যের ১২ নিরয়ণ রাশি অতিক্রম |
অতএব বারো চান্দ্রমাস ও সৌর বছরের ব্যবধান বছরে প্রায় ১০.৯ দিন। এই ব্যবধান জমতে জমতে আনুমানিক ৩২.৫ মাসে একটি পূর্ণ lunation-এর কাছাকাছি হয়। কিন্তু “৩২.৫ মাস” কেবল গড় ব্যাখ্যা—কোন মাস অধিমাস হবে তা এর সাহায্যে নির্ধারণ করা যায় না।
অধিমাস কেন স্থির cycle নয়?
চন্দ্রের একটি synodic cycle সব সময় ঠিক একই দৈর্ঘ্যের নয়। একইভাবে সূর্যও প্রতিটি নিরয়ণ রাশিতে সমান সংখ্যক দিন থাকে না—পৃথিবীর কক্ষপথের প্রকৃতি এবং ব্যবহৃত astronomical model-এর কারণে apparent solar speed পরিবর্তিত হয়। ফলে কোনো New Moon interval-এ:
- একটি সংক্রান্তি না-ও ঘটতে পারে;
- সাধারণত একটি সংক্রান্তি ঘটে;
- বিরলভাবে দুটি সংক্রান্তি ঘটতে পারে।
এই event geometry-ই মাসের ধরন নির্ধারণ করে। Average duration বোঝার জন্য উপকারী, classification-এর জন্য নয়।
Operational rule: একটি lunation-এ ০, ১ বা ২ সংক্রান্তি
পরপর দুইটি astronomical New Moon instant ধরা যাক Ni এবং Ni+1। তাহলে একটি অমান্ত lunation:
ingressCount = ওই interval-এর ভিতরে নিরয়ণ সূর্যের ৩০° রাশি-boundary crossing-এর সংখ্যা
| সংক্রান্তির সংখ্যা | Classification | অর্থ |
|---|---|---|
| ০ | অধিমাস | একটি সম্পূর্ণ lunation-এ সূর্য নতুন নিরয়ণ রাশিতে প্রবেশ করেনি |
| ১ | সাধারণ মাস | একটি lunation-এ স্বাভাবিকভাবে একটি রাশি-সংক্রান্তি ঘটেছে |
| ২ | ক্ষয়মাস context | একটি lunation-এর মধ্যেই সূর্য দুইটি রাশি-boundary অতিক্রম করেছে; একটি expected month-name sequence থেকে লুপ্ত হয় |
“ক্ষয়মাস context” বলা নিরাপদ, কারণ একটি row-কে শুধু month = skipped বললেই পুরো sequence বোঝা যায় না। আগের ও পরের lunation, দুইটি ingress target এবং chosen tradition/profile একসঙ্গে দেখে published name নির্ধারণ করতে হয়।
Boundary-তে event পড়লে কার মাস?
Computer calculation-এ সবচেয়ে বিপজ্জনক ambiguity হলো একটি সংক্রান্তি New Moon instant-এর একেবারে সমান বা numerical tolerance-এর মধ্যে পড়া। তাই interval-কে half-open রাখুন:
start <= ingressInstant && ingressInstant < end
অর্থাৎ শুরুতে ঠিক পড়া ingress বর্তমান lunation-এর; শেষ boundary-তে ঠিক পড়া ingress পরের lunation-এর। একই event দুই মাসে count হবে না। Root solver-এর floating-point result তুলতে raw DateTime round না করে Julian Day বা উচ্চ-precision instant canonical রাখুন।
সাধারণ মাসের নাম কোথা থেকে আসে?
একটি regular অমান্ত মাসে যে একমাত্র নিরয়ণ solar ingress ঘটে, তার target rāśi-এর সঙ্গে চান্দ্রমাসের নাম map করা হয়। বহুল ব্যবহৃত correspondence:
| সূর্যের প্রবেশ | চান্দ্রমাস | সূর্যের প্রবেশ | চান্দ্রমাস |
|---|---|---|---|
| মেষ | চৈত্র | তুলা | আশ্বিন |
| বৃষ | বৈশাখ | বৃশ্চিক | কার্তিক |
| মিথুন | জ্যৈষ্ঠ | ধনু | মার্গশীর্ষ/অগ্রহায়ণ |
| কর্কট | আষাঢ় | মকর | পৌষ |
| সিংহ | শ্রাবণ | কুম্ভ | মাঘ |
| কন্যা | ভাদ্রপদ | মীন | ফাল্গুন |
এখানে numeric identity ও localized spelling পৃথক রাখুন। MonthNumber = 6 হতে পারে canonical field; বাংলা resource “ভাদ্রপদ” বা regional display “ভাদ্র” দেখাতে পারে।
অধিমাসের নাম এবং পরের নিজ/শুদ্ধ মাস
Zero-ingress lunation-এর নিজের ভিতরে naming ingress নেই। তাই engine পরের relevant ingress দেখে base month-name নির্ধারণ করে। যে মাসের regular occurrence সামনে আসছে, zero-ingress মাসও সেই নাম পায় এবং prefix হয় অধিক। পরের regular occurrence-কে আলাদা করতে নিজ বা শুদ্ধ বলা হয়।
Lunation B: ১ ingress, তুলায় প্রবেশ → নিজ/শুদ্ধ আশ্বিন
এটি illustration; production result actual event data থেকে আসবে। Database-এ দুই মাসের base number একই হলেও identity এক নয়:
baseMonthKey = "ashvina"
monthKind = "adhika" // প্রথম lunation
baseMonthKey = "ashvina"
monthKind = "nija" // পরের regular lunation
শুধু display text “আশ্বিন” সংরক্ষণ করলে festival lookup, URL, cache এবং historical export-এ দুই মাস এক হয়ে যাবে। Stable lunation ID ও explicit monthKind বাধ্যতামূলক করুন।
ক্ষয়মাস: একটি নাম sequence থেকে লুপ্ত হওয়া
একটি lunation-এর মধ্যে দুইটি solar ingress ঘটলে চন্দ্রের এক New Moon থেকে পরের New Moon পৌঁছানোর আগেই সূর্য দুইটি রাশিতে প্রবেশ করে। ফলে স্বাভাবিক one-ingress-per-month correspondence ভেঙে যায় এবং একটি expected চান্দ্রমাসের নাম পৃথক lunation হিসেবে প্রকাশিত হয় না—এটাই ক্ষয়মাসের context।
এটি অধিমাসের তুলনায় অনেক বিরল। Algorithm-এ নিম্নলিখিত তথ্য ধরে রাখুন:
- একই lunation-এর প্রথম ও দ্বিতীয় ingress;
- দুই ingress-এর target rāśi;
- আগের ও পরের lunation-এর classification;
- কোন name প্রকাশিত এবং কোন expected name suppressed;
- নির্বাচিত textual/traditional naming profile।
monthNumber + 2 করে কোনো নাম বাদ দেওয়া যথেষ্ট নয়। Published name এবং suppressed identity নির্ধারণে full neighboring sequence ব্যবহার করুন। ঐতিহাসিক calendrical আলোচনায় ক্ষয়মাসের আশেপাশে অধিমাসের বিশেষ বিন্যাসের উল্লেখ আছে; software তবু সেই pattern hard-code না করে actual ০/১/২ ingress sequence detect করবে।
এক মাসে শূন্য বা দুই সংক্রান্তি কীভাবে সম্ভব?
একটি lunation গড়ে ২৯.৫৩ দিন। অন্যদিকে সূর্যের একটি ৩০° নিরয়ণ রাশি অতিক্রমের সময় গড়ে প্রায় ৩০.৪ দিন হলেও সব রাশিতে সমান নয়। দুটি moving interval-এর boundary কখনও এমনভাবে পড়ে যে:
| Illustrative interval | ভিতরের ingress | ফল |
|---|---|---|
| New Moon ১ → New Moon ২ | কোনো ৩০° crossing নেই | অধিমাস |
| New Moon ২ → New Moon ৩ | একটি crossing | সাধারণ/নিজ মাস |
| New Moon X → New Moon Y | দুটি crossing | ক্ষয়মাস context |
উদাহরণের “New Moon ১” কোনো নির্দিষ্ট ঐতিহাসিক তারিখ নয়। বাস্তব গণনায় longitudes থেকে roots solve করতে হবে।
Astronomical classification global, civil label local
Geocentric New Moon এবং নিরয়ণ solar ingress-এর absolute instant একটি chosen astronomical profile-এ location-independent। তাই একই profile ব্যবহার করলে ঢাকা, কলকাতা বা নিউ ইয়র্কে মূল Adhika/Regular/Kshaya classification একই থাকবে। তবে স্থানীয় time zone-এ event-এর civil date ও weekday আলাদা হতে পারে।
উদাহরণস্বরূপ, একটি ingress UTC রাত ২০:৩০-এ হলে ঢাকায় পরদিনের civil date, কিন্তু নিউ ইয়র্কে আগের দিনের date হতে পারে। তাই API-তে দুই layer রাখুন:
- Canonical event: Julian Day বা UTC instant;
- Localized display: requested time zone-এর date, time ও weekday।
তিথিক্ষয় এবং ক্ষয়মাস এক বিষয় নয়
| বিষয় | তিথিক্ষয় | ক্ষয়মাস |
|---|---|---|
| মূল ঘটনা | একটি তিথি পরপর দুই sunrise-এর কোনোটিতে বর্তমান নয় | এক lunation-এ দুই solar ingress |
| Location dependency | Sunrise ও location-এর কারণে local result বদলাতে পারে | Chosen geocentric event profile-এ মূল classification global |
| Unit | তিথি/day label | চান্দ্রমাস identity |
| Detection | Sunrise sampling + tithi intervals | New Moon interval + ingress count |
একই বাংলা শব্দ “ক্ষয়” দেখে দুই algorithm মিশিয়ে ফেললে serious error হবে। Code-এ KshayaTithi এবং KshayaMonthContext পৃথক type রাখুন।
অমান্ত ও পূর্ণিমান্ত display-এ কী হবে?
Adhika/Kshaya detection-এর সবচেয়ে পরিষ্কার computational ভিত্তি consecutive New Moon lunation—অর্থাৎ অমান্ত core। পূর্ণিমান্ত display একই astronomical cycle-কে Full Moon boundary-তে ভাগ করে। Regular মাসে কৃষ্ণপক্ষের নাম next-month mapping দিয়ে পাওয়া গেলেও Adhika/Kshaya sequence-এ blind +1 নিরাপদ নয়।
সঠিক architecture:
- New Moon থেকে New Moon canonical lunation তৈরি করুন;
- প্রতিটি lunation-এর ingress list ও month identity নির্ধারণ করুন;
- প্রতিটি pakṣa interval-কে সেই canonical lunation identity-এর সঙ্গে link করুন;
- Amanta/Purnimanta renderer chosen convention অনুযায়ী halves group করবে;
- Adhika/Nija/Kshaya metadata হারাবে না।
এতে একই দিনের তিথি ও astronomical facts অপরিবর্তিত রেখে regional month label দেখানো যায়।
অধিমাসে উৎসব: calculation ও ধর্মীয় policy আলাদা রাখুন
“অধিমাসে সব উৎসব হয় না”—এমন universal rule software-এ hard-code করা উচিত নয়। নিত্য তিথিভিত্তিক observance, মাসনির্দিষ্ট বার্ষিক উৎসব, regional practice এবং নির্দিষ্ট sampradāya-র rule এক নয়। কিছু বার্ষিক উৎসব অধিক occurrence-এর বদলে নিজ/শুদ্ধ মাসে পালিত হয়; অন্য observance উভয় cycle-এ প্রযোজ্য হতে পারে।
Festival definition-এ explicit policy field রাখুন:
public enum FestivalMonthPolicy
{
ObserveInAdhika,
ObserveInNija,
ObserveInBoth,
AuthoritySpecific,
NotApplicable
}
প্রতিটি rule-এর সঙ্গে authority, edition এবং effective version রাখুন। কোনো উৎসব suppress করলে report-এ কারণ দেখান—যেমন SUPPRESSED_IN_ADHIKA_BY_PROFILE। Calculation engine মাসের identity দেবে; festival engine নির্দিষ্ট authority profile প্রয়োগ করবে।
নির্ভরযোগ্য calculation pipeline
- Profile freeze: solar/lunar model, ayanāṃśa, ephemeris version, ΔT policy ও precision নির্ধারণ;
- New Moon roots: geocentric Sun–Moon elongation ০° হওয়ার consecutive instants solve;
- Solar ingress roots: unwrapped nirayana solar longitude ০°, ৩০°, ৬০° … boundary crossing solve;
- Lunation windows: consecutive New Moon দিয়ে
[start, end)interval; - Ingress association: প্রতিটি ingress ঠিক একটি lunation-এ assign;
- Classification: count ০/১/২;
- Naming: regular mapping, Adhika look-ahead, Kshaya neighborhood analysis;
- Festival policy: month identity-এর পরে authority-specific rule;
- Localization: সবশেষে time zone, language এবং civil calendar label।
Solar longitude wrap—যেমন 359.999° থেকে 0.001°—আগে unwrap না করলে solver ভুল direction বা duplicate ingress দিতে পারে। একইভাবে 0° elongation-এর কাছাকাছি signed angle normalize করতে হবে।
C# 5-compatible data model
public enum LunarMonthKind
{
Adhika,
Regular,
Nija,
KshayaContext,
Undetermined
}
public sealed class SolarIngress
{
public int FromRashi { get; set; } // 1..12
public int ToRashi { get; set; } // 1..12
public double JulianDayUt { get; set; }
public DateTimeOffset InstantUtc { get; set; }
}
public sealed class LunationSpan
{
public long LunationId { get; set; }
public double StartJulianDayUt { get; set; }
public double EndJulianDayUt { get; set; }
public DateTimeOffset NewMoonStartUtc { get; set; }
public DateTimeOffset NewMoonEndUtc { get; set; }
public IList<SolarIngress> Ingresses { get; set; }
}
public sealed class LunarMonthDecision
{
public LunarMonthKind Kind { get; set; }
public int? MonthNumber { get; set; }
public string MonthKey { get; set; }
public int? SuppressedMonthNumber { get; set; }
public string RuleCode { get; set; }
public IList<SolarIngress> Evidence { get; set; }
}
DateTimeOffset display ও interoperability-এর জন্য; boundary classification-এ full-precision Julian Day ব্যবহার করলে tick rounding-এর ঝুঁকি কমে।
C# classifier: count first, name later
static IList<SolarIngress> IngressesInside(
LunationSpan span,
IEnumerable<SolarIngress> all)
{
return all
.Where(x => x.JulianDayUt >= span.StartJulianDayUt &&
x.JulianDayUt < span.EndJulianDayUt)
.OrderBy(x => x.JulianDayUt)
.ToList();
}
static LunarMonthDecision Classify(
LunationSpan span,
IEnumerable<SolarIngress> all)
{
IList<SolarIngress> hits = IngressesInside(span, all);
if (hits.Count == 0)
{
return new LunarMonthDecision
{
Kind = LunarMonthKind.Adhika,
RuleCode = "ADHIKA_ZERO_INGRESS",
Evidence = hits
};
}
if (hits.Count == 1)
{
return new LunarMonthDecision
{
Kind = LunarMonthKind.Regular,
MonthNumber = MonthFromTargetRashi(hits[0].ToRashi),
RuleCode = "REGULAR_ONE_INGRESS",
Evidence = hits
};
}
if (hits.Count == 2)
{
return new LunarMonthDecision
{
Kind = LunarMonthKind.KshayaContext,
RuleCode = "KSHAYA_CONTEXT_TWO_INGRESSES",
Evidence = hits
};
}
return new LunarMonthDecision
{
Kind = LunarMonthKind.Undetermined,
RuleCode = "UNEXPECTED_INGRESS_COUNT_" + hits.Count,
Evidence = hits
};
}
একটি lunation-এ তিন বা তার বেশি ingress astronomical expectation-এর বাইরে; silently continue না করে diagnostic failure করুন। এতে duplicate-root বা interval-assignment bug ধরা পড়বে।
Adhika naming: পরের ingress-এর দিকে look-ahead
static int MonthFromTargetRashi(int rashi)
{
if (rashi < 1 || rashi > 12)
throw new ArgumentOutOfRangeException("rashi");
// Mesha -> Chaitra, Vrishabha -> Vaisakha ... Mina -> Phalguna
return rashi;
}
static void NameAdhikaMonth(
IList<LunationSpan> spans,
IList<LunarMonthDecision> decisions,
int index)
{
LunarMonthDecision current = decisions[index];
if (current.Kind != LunarMonthKind.Adhika)
return;
for (int j = index + 1; j < spans.Count; j++)
{
SolarIngress next = spans[j].Ingresses
.OrderBy(x => x.JulianDayUt)
.FirstOrDefault();
if (next == null)
continue;
current.MonthNumber = MonthFromTargetRashi(next.ToRashi);
current.RuleCode = "ADHIKA_NAMED_FROM_NEXT_INGRESS";
return;
}
throw new InvalidOperationException(
"অধিমাসের নাম নির্ণয়ের জন্য পরবর্তী সংক্রান্তি পাওয়া যায়নি।");
}
তারপর পরের regular decision-এর base month যদি একই হয়, display layer সেটিকে Nija বা Shuddha হিসেবে mark করতে পারে। তবে মূল evidence Regular classification এবং preceding Adhika link—দুটিই সংরক্ষণ করুন।
Kshaya naming আলাদা resolver-এ রাখুন। দুই ingress-এর target, previous/next decision এবং tradition profile input নিন; result-এ SuppressedMonthNumber ও full trace ফেরত দিন।
API ও XML-এ কী প্রকাশ করবেন?
শুধু “অধিক কার্তিক” string দিলে consumer audit বা alternate language render করতে পারবে না। Structured output:
{
"lunationId": 24731,
"newMoonStartJdUt": 2460000.123456,
"newMoonEndJdUt": 2460029.654321,
"month": {
"number": 7,
"key": "kartika",
"nameBn": "কার্তিক",
"kind": "adhika",
"rule": "ADHIKA_NAMED_FROM_NEXT_INGRESS"
},
"ingressCount": 0,
"ingresses": [],
"astronomyProfile": "surya-siddhanta-v3",
"ayanamsaProfile": "project-nirayana-v2",
"civilDisplayZone": "Asia/Dhaka"
}
XML:
<lunar-month lunation-id="24731"
number="7"
key="kartika"
kind="adhika"
ingress-count="0"
rule="ADHIKA_NAMED_FROM_NEXT_INGRESS">
<boundary type="new-moon-start" jd-ut="2460000.123456" />
<boundary type="new-moon-end" jd-ut="2460029.654321" />
<profiles astronomy="surya-siddhanta-v3"
ayanamsa="project-nirayana-v2" />
</lunar-month>
Kshaya context-এ দুইটি <ingress>, published month, suppressed month এবং resolver profile দিন। Amanta/Purnimanta label আলাদা child object রাখুন।
ঐতিহাসিক পঞ্জিকা ও Julian/Gregorian display
প্রাচীন বা মধ্যযুগীয় বছর গণনায় internal chronology হিসেবে continuous Julian Day ব্যবহার করা সুবিধাজনক। Julian/Gregorian civil calendar conversion কেবল display layer; ১৫৮২ সালের calendar reform অধিমাসের astronomical classification পরিবর্তন করে না। একই instant-কে দুই civil calendar-এ আলাদা date label দেওয়া হয়।
তবে historical result model-dependent হতে পারে:
- সূর্য ও চন্দ্রের mean/true motion কোন siddhānta/ephemeris থেকে এসেছে;
- ayanāṃśa বা sidereal reference কী;
- ancient ΔT estimate কী;
- printed tradition-এর correction table ব্যবহার হয়েছে কি না;
- textual source অমান্ত না পূর্ণিমান্ত।
তাই “এই বছর অধিমাস ছিল” ফলের সঙ্গে method/version প্রকাশ করুন। অন্য পঞ্জিকার সঙ্গে mismatch হলে প্রথমে model ও reference frame তুলুন, civil date label নয়।
Validation checklist
- Consecutive New Moon roots chronological;
- প্রতিটি lunation
[start, end); - Shared boundary event duplicate নয়;
- Ingress exactly at start current interval-এ;
- Ingress exactly at end next interval-এ;
- Solar longitude 360° wrap unwrapped;
- New Moon elongation wrap normalized;
- ০ ingress → Adhika;
- ১ ingress → Regular;
- ২ ingress → KshayaContext;
- ৩+ ingress diagnostic error;
- Regular ingress target → correct lunar month;
- Mīna → Phālguna mapping;
- Meṣa → Caitra mapping;
- Adhika name next ingress থেকে;
- Adhika/Nija pair একই base identity, আলাদা kind;
- Kshaya resolver দুই ingress সংরক্ষণ করে;
- Suppressed month audit field আছে;
- Neighboring lunations Kshaya test-এ অন্তর্ভুক্ত;
- Amanta display canonical lunation-এর সঙ্গে মেলে;
- Purnimanta display blind
+1নয়; - FestivalMonthPolicy প্রতিটি মাসনির্দিষ্ট rule-এ আছে;
- Suppressed festival reason trace-এ আছে;
- UTC/JD classification time zone বদলালে বদলায় না;
- ঢাকা/কলকাতা/নিউ ইয়র্ক civil label পৃথক হতে পারে;
- Tithi-kshaya test month-kshaya থেকে পৃথক;
- Surya Siddhanta ও Drik profile mix হয় না;
- Ayanāṃśa/profile metadata export হয়;
- Ancient year DateTime range overflow ছাড়া JD-তে চলে;
- ১৫৮২ cutover classification অপরিবর্তিত;
- Known printed Panchanga Adhika/Nija pair regression;
- Known rare Kshaya sequence regression;
- API এবং XML একই identity দেয়;
- Localized spelling numeric key বদলায় না;
- Cache key-তে astronomy, ayanāṃśa ও naming profile version আছে।
উপসংহার
অধিমাস কোনো arbitrary extra month নয়; সৌর ও চান্দ্র cycle-এর precise সম্পর্ক থেকে জন্ম নেওয়া একটি astronomical classification। পরপর দুই New Moon-এর মধ্যে নিরয়ণ সংক্রান্তি না থাকলে অধিমাস, একটি থাকলে সাধারণ মাস, আর দুটি থাকলে ক্ষয়মাসের context তৈরি হয়। মাসের নাম event sequence থেকে আসে—average year বা fixed leap table থেকে নয়।
সঠিক software design-এ New Moon এবং ingress instant canonical থাকবে, interval হবে [start, end), classification ও naming আলাদা ধাপে হবে, এবং Adhika/Nija identity পৃথক থাকবে। Kshaya month-এ neighboring lunations ও দুই ingress-এর complete evidence সংরক্ষণ করতে হবে।
উৎসবনীতি, অমান্ত/পূর্ণিমান্ত presentation, ভাষা, time zone এবং Julian/Gregorian civil label calculation core-এর পরে প্রয়োগ করুন। এতে একই engine গবেষণা, দৈনিক পঞ্জিকা, historical export, API এবং printed calendar—সব জায়গায় ব্যাখ্যাযোগ্য ও পুনরুৎপাদনযোগ্য ফল দেবে।
তথ্যসূত্র ও আরও পাঠ
- Robert Sewell ও Śaṅkara Bālkṛṣṇa Dīkṣita—The Indian Calendar; intercalated (adhika) ও suppressed (kshaya) month terminology এবং traditional calendrical framework.
- Vinod K. Mishra—The Calendars of India; Indian lunisolar calendar, adhika এবং rare missing-month sequence-এর overview.
- Nachum Dershowitz ও Edward M. Reingold—Indian Calendrical Calculations; true Hindu calendar-এ zodiac transitions, leap month এবং expunged month calculation.
- Why Adhik Maas Happens; zero-ingress Adhika, naming এবং two-ingress Kshaya-এর explanatory account.
- Positional Astronomy Centre—Rashtriya Panchang; contemporary Indian astronomical almanac context ও official publication reference.
- সূর্য সিদ্ধান্ত পঞ্জিকা project specification; versioned sidereal profiles, historical Julian Day pipeline এবং festival-rule separation.
মন্তব্য, আলোচনা ও প্রশ্ন