পঞ্জিকার সময়কে বোঝার সহজ উপায় হলো astronomical instant, local clock এবং traditional elapsed time—এই তিনটি আলাদা স্তর হিসেবে রাখা। গণনার সত্য হলো UTC বা Julian Day instant। সেটিকে selected timezone-এ রূপান্তর করলে ঘড়ির সময় পাওয়া যায়; একই instant থেকে local sunrise বাদ দিলে দণ্ড-পল-বিপল পাওয়া যায়। কোনো display string আরেক display string থেকে তৈরি হবে না।
এক ঘটনার দুই সময়রূপ
ধরা যাক কোনো তিথি শেষ হয়েছে একটি নির্দিষ্ট instant-এ। User-facing report-এ তা দুইভাবে দেখানো যায়:
Sunrise-relative: দং ৪০/৪৬/১৬.৬২
| রূপ | কি জানায় | কি প্রয়োজন |
|---|---|---|
| Local clock | স্থানের দেয়ালঘড়িতে ঘটনাটি কখন | UTC instant + timezone |
| দণ্ড-পল-বিপল | সেই দিনের local sunrise থেকে কত traditional time অতিবাহিত | Event instant − sunrise instant |
| ISO timestamp | Date, time ও UTC offset-সহ machine value | DateTimeOffset |
| Julian Day UT | Timezone-স্বাধীন research value | Astronomical solver |
ঘড়ির সময় দেখে সরাসরি দণ্ড অনুমান করলে ভুল হতে পারে, কারণ sunrise প্রতিদিন বদলায়। আবার শুধু দণ্ড থেকে civil date বোঝা যায় না। তাই publication-এ দুটো রাখা পাঠকের জন্য সুবিধাজনক, আর API-তে authoritative instant-টিও রাখতে হবে।
দণ্ড, পল ও বিপলের সম্পর্ক
জ্যোতির্বৈজ্ঞানিক time division-এ ৬০ ক্ষুদ্র এককে পরবর্তী বৃহৎ একক তৈরি হয়। Project-এর printed Panjika convention:
| একক | সম্পর্ক | আধুনিক মান |
|---|---|---|
| ১ দিবস | ৬০ দণ্ড/ঘটিকা | ২৪ ঘণ্টা |
| ১ দণ্ড | ৬০ পল | ২৪ মিনিট = ১,৪৪০ সেকেন্ড |
| ১ পল | ৬০ বিপল | ২৪ সেকেন্ড |
| ১ বিপল | ১/৬০ পল | ০.৪ সেকেন্ড |
| ০.০১ বিপল | প্রকাশনার দুই decimal | ০.০০৪ সেকেন্ড |
এখানে “দিবস = ২৪ ঘণ্টা” unit conversion-এর মান। এটি স্থানীয় দুটি actual sunrise-এর মধ্যবর্তী duration সবদিন ঠিক ২৪ ঘণ্টা—এ দাবি নয়। Astronomical sunrise interval ঋতু, longitude এবং DST transition-এর কারণে modern clock-এ সামান্য কম-বেশি হতে পারে।
নাড়ী, ঘটিকা, দণ্ড, বিনাড়ী, পল—নাম কেন এত?
অঞ্চল, ভাষা ও গ্রন্থভেদে একই বা কাছাকাছি এককের একাধিক নাম দেখা যায়। সূর্য সিদ্ধান্তের ইংরেজি অনুবাদে nāḍī ও vināḍī; বাংলা মুদ্রিত পঞ্জিকায় বেশি পরিচিত দণ্ড, পল ও বিপল। এই project-এ mapping স্পষ্টভাবে ঘোষণা করা হবে:
| Project term | সমার্থক/সম্পর্কিত নাম | UI abbreviation |
|---|---|---|
| দণ্ড | ঘটিকা, নাড়ী, ঘটি | দং |
| পল | বিনাড়ী, বিঘটিকা | পল বা slash-এর দ্বিতীয় সংখ্যা |
| বিপল | পলের ষাট ভাগের এক ভাগ | বিপল বা slash-এর তৃতীয় সংখ্যা |
| আধুনিক ঘণ্টা | Clock hour | ঘ |
গণনার origin কেন local sunrise?
Traditional civil Panjika day local sunrise থেকে পরবর্তী sunrise পর্যন্ত। ফলে সেই দিনের তিথি, নক্ষত্র, করণ ও যোগের ending time-কে sunrise-relative traditional units-এ প্রকাশ করলে day assignment-এর সঙ্গে স্বাভাবিক সামঞ্জস্য থাকে:
traditional units = elapsed ÷ fixed unit lengths
UTC instant subtract করার কারণ হলো local wall clock-এ offset পরিবর্তন হতে পারে। দুটি DateTimeOffset-কে UTC-তে নিয়ে difference করলে elapsed physical time সঠিক থাকে।
সব event-এর origin sunrise নয়। অরুণোদয়-ভিত্তিক ব্রত rule-এ evaluation moment sunrise-এর ৯৬ মিনিট আগে; কিন্তু event-এর printed দণ্ড চাইলে নির্বাচিত Panjika day-এর sunrise origin-ই রাখুন এবং negative traditional value না দেখিয়ে rule-moment আলাদাভাবে label করুন। অন্য কোনো origin ব্যবহার করলে field-এ origin ঘোষণা করা বাধ্যতামূলক।
Clock instant থেকে দণ্ড-পল-বিপল
প্রথমে sunrise থেকে event পর্যন্ত মোট elapsed seconds:
দণ্ড = floor(S / 1440)
পল = floor((S mod 1440) / 24)
বিপল = (S mod 24) / 0.4
Equivalent direct formula:
- Total danda =
S / 1440; - Total pala =
S / 24; - Total bipala =
S / 0.4; - Formatted result-এ প্রতি বৃহৎ এককের remainder নিন।
Event civil midnight পার হলেও elapsed positive-ই থাকবে। event.TimeOfDay - sunrise.TimeOfDay ব্যবহার করলে next-day ২:০০ AM-কে negative মনে হবে; পূর্ণ instant subtract করতে হবে।
পূর্ণ উদাহরণ: “রাত্র ১০:১৪:৫০ দং ৪০/৪৬/১৬.৬২”
ধরা যাক local sunrise ছিল ৫:৫৬:১৯.৩৫২ AM এবং event ঘটেছে একই civil date-এর ১০:১৪:৫০ PM-এ।
| ধাপ | হিসাব | ফল |
|---|---|---|
| Elapsed time | ২২:১৪:৫০.০০০ − ০৫:৫৬:১৯.৩৫২ | ১৬:১৮:৩০.৬৪৮ |
| দণ্ড | ১৬ ঘণ্টা ÷ ২৪ মিনিট | ৪০ দণ্ড; remainder ১৮:৩০.৬৪৮ |
| পল | ১৮:৩০.৬৪৮ ÷ ২৪ সেকেন্ড | ৪৬ পল; remainder ৬.৬৪৮ সেকেন্ড |
| বিপল | ৬.৬৪৮ ÷ ০.৪ | ১৬.৬২ বিপল |
= ৪০ দণ্ড ৪৬ পল ১৬.৬২ বিপল
= দং ৪০/৪৬/১৬.৬২
এটি mathematical consistency example। Production result-এ sunrise এবং event দুটিই একই engine profile, location, date ও timezone থেকে নিতে হবে। Screenshot-এর rounded clock time থেকে উচ্চ precision দণ্ড পুনর্নির্মাণ করলে কয়েক বিপল পার্থক্য হতে পারে।
দণ্ড-পল-বিপল থেকে modern clock time
Reverse conversion:
= (দণ্ড × 1440) + (পল × 24) + (বিপল × 0.4)
event instant = sunrise instant + elapsed seconds
উপরের উদাহরণে:
(40 × 1440) + (46 × 24) + (16.62 × 0.4)
= 57600 + 1104 + 6.648
= 58710.648 seconds
= 16:18:30.648 after sunrise
Sunrise instant ৫:৫৬:১৯.৩৫২ AM-এর সঙ্গে যোগ করলে ১০:১৪:৫০ PM। Reverse conversion-এর input-এ location, civil date, sunrise definition এবং timezone না থাকলে clock time নির্ণয় করা যায় না। একই ৪০/৪৬/১৬.৬২ কলকাতা ও নিউ ইয়র্কে একই elapsed duration বোঝায়, কিন্তু local clock ending time ভিন্ন হতে পারে।
Midnight, “নিশা” এবং ২৪-এর বেশি ঘণ্টা
Panjika day midnight-এ শেষ হয় না। Event next civil date-এর midnight-এর পরে কিন্তু next sunrise-এর আগে হলে project clock label “নিশা” ব্যবহার করে। Traditional count current sunrise থেকেই চলতে থাকে।
আগের sunrise ৫:৫৬:১৯.৩৫২ AM এবং event next civil date-এর ২:৫৯:১২ AM হলে:
traditional = দং ৫২/৩৭/১১.৬২
display = নিশা ঘ ২:৫৯:১২
কিছু সরকারি বা মুদ্রিত ephemeris extended-hour notation ব্যবহার করে: next-day ১:০০ AM = ২৫h, ২:০০ AM = ২৬h। এটি civil date বদলালেও চলমান Panchanga day বোঝাতে সহায়ক। Project Bengali UI “নিশা” দেখাতে পারে, কিন্তু API-তে full ISO date-time ও offset রাখবে।
| একই instant-এর প্রকাশ | উদাহরণ |
|---|---|
| Normal next-day clock | ৯ অক্টোবর ২০২৬, ২:৫৯:১২ AM |
| Panjika extended hour | ৮ অক্টোবরের ২৬:৫৯:১২ |
| Project Bengali label | নিশা ঘ ২:৫৯:১২ |
| Traditional elapsed | দং ৫২/৩৭/১১.৬২ |
Timezone ও DST: wall-clock subtraction করবেন না
Dhaka বা Kolkata-তে আধুনিক সময়ে সাধারণত fixed offset ব্যবহৃত হলেও New York-এ Daylight Saving Time পরিবর্তিত হয়। Spring-forward রাতে ১:৫৯:৫৯-এর পরে ঘড়ি সরাসরি ৩:০০ দেখাতে পারে; fall-back রাতে একটি clock hour দুইবার আসে।
ভুল পদ্ধতি:
TimeSpan elapsed = eventLocal.DateTime - sunriseLocal.DateTime;
এখানে offset হারিয়ে যেতে পারে। সঠিক:
TimeSpan elapsed = eventLocal.ToUniversalTime()
- sunriseLocal.ToUniversalTime();
এভাবে elapsed physical seconds সঠিক থাকে। Display করার সময় event instant-কে selected TimeZoneInfo-তে convert করুন। Cache key-তে শুধু city name নয়—coordinates, timezone ID, date এবং calculation profile রাখুন।
Fixed ২৪-minute দণ্ড বনাম actual day-এর ১/৬০ ভাগ
দুটি আলাদা model গুলিয়ে ফেলা সহজ:
| Model | সংজ্ঞা | ব্যবহার |
|---|---|---|
| Fixed traditional unit | ১ দণ্ড = ২৪ মিনিট | Printed Panjika, conversion, research comparison |
| Dynamic daylight division | Sunrise–sunset interval-এর fraction | দিনমান, hora/muhurta ধরনের আলাদা calculation |
| Dynamic full-day fraction | Actual sunrise–next sunrise ÷ ৬০ | Custom visualization; “fixed দণ্ড” নামে প্রকাশ নয় |
Project-এর দং ৪০/৪৬/১৬.৬২ fixed model। Actual sunrise interval-কে ৬০ ভাগ করলে প্রতিদিন এবং প্রত্যেক location-এ unit length বদলে যাবে; New York DST day-এ পরিবর্তন আরও বড় হবে। এমন experimental field দরকার হলে নাম দিন dayWindowFraction, এবং traditional danda field থেকে আলাদা রাখুন।
দিনমান বা রাত্রিমানকে আলাদাভাবে ৩০ ভাগ করা ritual calculation অন্য বিষয়। সেখানে sunrise–sunset অথবা sunset–next sunrise interval proportionalভাবে ভাগ করা হতে পারে। সেই dynamic muhūrta/prahara গণনাকে fixed ২৪-minute danda conversion-এর সঙ্গে মেশাবেন না।
Rounding, carry এবং প্রকাশনার precision
Floating-point value আলাদা আলাদা করে round করলে ৫৯ পল ৬০.০০ বিপল-এর মতো invalid result হতে পারে। সেরা পদ্ধতি হলো smallest displayed unit-এ প্রথমে total value round করে তারপর integer division:
- দুই decimal বিপল দেখালে ০.০১ বিপল = ০.০০৪ second;
- Total elapsed seconds-কে centi-bipala-তে round করুন;
- সেখান থেকে দণ্ড, পল, বিপল ভাগ করুন;
- Carry স্বয়ংক্রিয়ভাবে পরের unit-এ যাবে।
উদাহরণ: ৫৯.৯৯৬ বিপল rounding-এর পরে ৬০.০০ হলে তা ০ বিপল এবং পল +১ হবে। একইভাবে ৫৯ পল carry হয়ে দণ্ড +১।
দুই decimal বিপল ৪ millisecond resolution নির্দেশ করে—কিন্তু astronomical model বা historical clock এত নির্ভুল ছিল এমন দাবি নয়। এটি publication format। API-তে precision ও rounding metadata রাখলে false precision বোঝার ঝুঁকি কমে।
C# 5/.NET Framework-compatible implementation
public sealed class TraditionalTimeValue
{
public int Danda { get; set; }
public int Pala { get; set; }
public decimal Bipala { get; set; }
public double ElapsedSeconds { get; set; }
public string Origin { get; set; }
}
public static TraditionalTimeValue ToTraditionalTime(
DateTimeOffset sunrise,
DateTimeOffset eventTime)
{
double seconds = (eventTime.ToUniversalTime()
- sunrise.ToUniversalTime()).TotalSeconds;
if (seconds < 0.0)
throw new ArgumentOutOfRangeException(
"eventTime", "Event is before the selected sunrise.");
// 0.01 bipala = 0.004 second.
long totalCentiBipala = checked((long)Math.Round(
seconds / 0.004,
MidpointRounding.AwayFromZero));
const long perPala = 6000; // 60 × 100
const long perDanda = 360000; // 60 × 60 × 100
int danda = (int)(totalCentiBipala / perDanda);
long afterDanda = totalCentiBipala % perDanda;
int pala = (int)(afterDanda / perPala);
long centiBipala = afterDanda % perPala;
return new TraditionalTimeValue
{
Danda = danda,
Pala = pala,
Bipala = centiBipala / 100m,
ElapsedSeconds = seconds,
Origin = "local-sunrise"
};
}
Formatter:
public static string FormatTraditionalTime(
TraditionalTimeValue value,
Func<string, string> bengaliDigits)
{
string raw = String.Format(
CultureInfo.InvariantCulture,
"{0}/{1:00}/{2:00.00}",
value.Danda,
value.Pala,
value.Bipala);
return "দং " + bengaliDigits(raw);
}
Reverse conversion:
public static DateTimeOffset FromTraditionalTime(
DateTimeOffset sunrise,
int danda,
int pala,
decimal bipala,
TimeZoneInfo zone)
{
if (danda < 0 || pala < 0 || pala >= 60
|| bipala < 0m || bipala >= 60m)
throw new ArgumentOutOfRangeException(
"Traditional time components are outside their ranges.");
decimal seconds = (danda * 1440m)
+ (pala * 24m)
+ (bipala * 0.4m);
DateTimeOffset utc = sunrise.ToUniversalTime()
.AddSeconds((double)seconds);
return TimeZoneInfo.ConvertTime(utc, zone);
}
একটি Panjika day সাধারণত ৬০ দণ্ডের কাছাকাছি হলেও reverse function-এ danda ৬০-এর বেশি নিষিদ্ধ করা হয়নি—research input বা extended interval থাকতে পারে। Daily output validator আলাদাভাবে event next sunrise-এর আগে কি না পরীক্ষা করবে।
Daily API ও XML-এ কীভাবে রাখবেন?
শুধু formatted text দিলে client পুনরায় parse করতে বাধ্য হয়। Structured value এবং ready-to-display Bengali string দুটোই রাখুন:
{
"event": "tithi-end",
"instantUtc": "2026-10-08T16:44:50Z",
"localTime": "2026-10-08T22:14:50+05:30",
"clockLabel": "রাত্র ঘ ১০:১৪:৫০",
"traditionalTime": {
"origin": "local-sunrise",
"danda": 40,
"pala": 46,
"bipala": 16.62,
"display": "দং ৪০/৪৬/১৬.৬২",
"unitModel": "fixed-24-minute-danda",
"rounding": "nearest-0.01-bipala"
}
}
উপরের UTC/local timestamp illustration-টি নির্দিষ্ট longitude calculation-এর দাবি নয়; production serializer authoritative event instant ব্যবহার করবে। XML-এ:
<event type="tithi-end"
instant_utc="2026-10-08T16:44:50Z"
local_time="2026-10-08T22:14:50+05:30">
<clock>রাত্র ঘ ১০:১৪:৫০</clock>
<traditional origin="local-sunrise"
model="fixed-24-minute-danda"
danda="40"
pala="46"
bipala="16.62">
দং ৪০/৪৬/১৬.৬২
</traditional>
</event>
Yearly Printed Panjika XML-এর CDATA text-এ একই display রাখা যায়; পাশাপাশি structured child রাখলে future Assamese বা English renderer raw number থেকেই নিজের language output বানাতে পারবে।
ঐতিহাসিক তারিখ ও স্থানীয় সময়ের সতর্কতা
পুরোনো পঞ্জিকার দণ্ড-পলকে modern zone clock-এ রূপান্তর করতে কেবল unit conversion যথেষ্ট নয়। জানতে হবে:
- কোন স্থানের sunrise origin;
- স্থানীয় mean time, standard time নাকি অন্য convention;
- Printed sunrise apparent/center এবং refraction policy;
- Julian না proleptic Gregorian civil date label;
- ঘড়ির সময়ে historical offset কীভাবে ধরা হয়েছে;
- দণ্ড value rounded নাকি exact intermediate result।
১৮১৮ সালের কোনো পঞ্জিকায় দণ্ড দেওয়া থাকলে আজকের Asia/Kolkata +05:30 সরাসরি বসানো ঐতিহাসিকভাবে সঠিক নাও হতে পারে। গবেষণা output-এ “calculation convention” ও “display convention” আলাদা করে লিখুন। Dual Julian/Gregorian date policy-এর মতো time convention-ও reproducibility metadata-এর অংশ।
Validation checklist
- ১ দণ্ড = ১,৪৪০ seconds;
- ১ পল = ২৪ seconds;
- ১ বিপল = ০.৪ second;
- ৬০ বিপল carry হয়ে ১ পল;
- ৬০ পল carry হয়ে ১ দণ্ড;
- ৬০ দণ্ড = ২৪ ঘণ্টা fixed conversion;
- Event at sunrise = দং ০/০০/০০.০০;
- Event ২৪ মিনিট পরে = দং ১/০০/০০.০০;
- Event ২৪ সেকেন্ড পরে = দং ০/০১/০০.০০;
- Event ০.৪ সেকেন্ড পরে = দং ০/০০/০১.০০;
- দং ৪০/৪৬/১৬.৬২ reverse result = ১৬:১৮:৩০.৬৪৮ elapsed;
- Forward এবং reverse round-trip accepted tolerance-এ;
- ৫৯.৯৯৬ বিপল rounding carry;
- ৫৯ পল + carry → next দণ্ড;
- Negative elapsed daily event reject;
- Post-midnight event positive elapsed থাকে;
- Post-midnight clock label “নিশা”;
- Full ISO date local clock-এর সঙ্গে থাকে;
- Spring-forward day UTC subtraction সঠিক;
- Fall-back duplicated hour offset-সহ disambiguated;
- Kolkata, Dhaka ও New York-এ fixed unit length একই;
- Actual sunrise interval দিয়ে unit length পরিবর্তিত হয় না;
- Dynamic day fraction আলাদা field;
- Traditional origin metadata present;
- API numeric value ও display string মিল;
- HTML, print ও XML একই converter ব্যবহার করে;
- Bengali digit conversion decimal separator নষ্ট করে না;
- Historical output-এ time convention declared।
উপসংহার
Clock time এবং দণ্ড-পল-বিপল পরস্পরবিরোধী নয়; একই astronomical instant-এর দুই presentation। Modern clock selected timezone-এ civil date ও offset দেখায়। Traditional form local sunrise থেকে elapsed fixed units দেখায়—১ দণ্ড ২৪ মিনিট, ১ পল ২৪ সেকেন্ড এবং ১ বিপল ০.৪ সেকেন্ড।
সঠিক architecture-এ event প্রথমে UTC বা Julian Day instant হিসেবে সংরক্ষিত হয়। সেখান থেকে local clock এবং sunrise-relative traditional time আলাদাভাবে তৈরি হয়। Clock string থেকে দণ্ড বা দণ্ড string থেকে timezone অনুমান করা হয় না। ফলে midnight, “নিশা”, DST এবং বহু-location output একই নিয়মে চলে।
Project-এর Daily Details, printed calendar, API ও XML একই converter ব্যবহার করলে “রাত্র ঘ ১০:১৪:৫০” এবং “দং ৪০/৪৬/১৬.৬২” সর্বত্র একই event-কে নির্দেশ করবে। Structured numeric fields ভবিষ্যৎ ভাষা ও গবেষণা export-কে সহজ করবে; display label শুধু presentation layer-এর কাজ থাকবে।
তথ্যসূত্র ও আরও পাঠ
- Sūrya Siddhānta, Chapter 1—Burgess translation; ৬ prāṇa = ১ vināḍī, ৬০ vināḍī = ১ nāḍī, ৬০ nāḍī = ১ day-এর সংজ্ঞা ও ২৪-second/২৪-minute equivalence.
- Robert Sewell ও Śaṅkara Bālakṛṣṇa Dīkṣita—The Indian Calendar, 1896; Indian time divisions ও sunrise-based civil day.
- Muriel Marion Underhill—The Hindu Religious Year, 1921; ghaṭikā, pala, vipala এবং sunrise-to-sunrise civil day.
- Positional Astronomy Centre, Kolkata—Rashtriya Panchang explanation; midnight-এর পর next sunrise পর্যন্ত ২৫h, ২৬h ইত্যাদি extended-hour notation.
- S. R. Sarma—“The Units of Time in Ancient and Medieval India”, History of Science in South Asia.
- সূর্য সিদ্ধান্ত পঞ্জিকা project; sunrise-window, “নিশা”, Daily API, Printed Panjika এবং XML formatting conventions.
মন্তব্য, আলোচনা ও প্রশ্ন