Julian Date একটি day-counting system; এটি নিজে কোনো একক time scale নয়। একই instant-কে JD(UT1), JD(TT) বা JD(TDB) হিসেবে লেখা যায়। আবার সেই instant-কে Julian calendar, Gregorian calendar অথবা proleptic Gregorian calendar-এ আলাদা civil label দেওয়া যায়। এই তিনটি স্তর—day count, time scale ও calendar label—একত্রে মিশিয়ে ফেলাই historical software-এর বহু ভুলের মূল কারণ।
Time scale কেন জরুরি?
গ্রহের orbital equation চালানোর জন্য একটি uniform সময়মান দরকার। কিন্তু পৃথিবীর বাস্তব ঘূর্ণন পুরোপুরি uniform নয়। অন্যদিকে ব্যবহারকারী ঘটনা দেখেন স্থানীয় সূর্যোদয়, মধ্যরাত্রি এবং civil clock-এর সঙ্গে তুলনা করে। ফলে calculation-এর অন্তত দুটি পৃথক সময়ের ভূমিকা থাকে:
- Uniform dynamical time: সূর্য, চন্দ্র ও গ্রহের ephemeris position নির্ণয়;
- Earth-rotation time: পৃথিবীর orientation, local meridian, sidereal time, sunrise/sunset এবং horizon event;
- Civil time: ব্যবহারকারীর clock, time zone, DST ও প্রকাশিত তারিখ;
- Calendar label: একই instant-কে Julian বা Gregorian তারিখে লেখা।
এই স্তরগুলো ভুলভাবে বদল করলে longitude calculation সামান্য সরে যেতে পারে; আর কোনো event যদি সূর্যোদয়, মধ্যরাত্রি বা রাশি-সীমানার কাছে থাকে, সেই সামান্য ব্যবধানই পঞ্জিকার দিন বদলে দিতে পারে।
JD, JDN ও MJD—এক জিনিস নয়
| নাম | অর্থ | Day boundary | উদাহরণ/সূত্র |
|---|---|---|---|
| Julian Date—JD | দিন ও দিনের fraction-এর ধারাবাহিক সংখ্যা | মূল convention-এ noon | 2000-01-01 12:00 TT = JD 2451545.0 |
| Julian Day Number—JDN | Julian day-এর integer label | Noon-to-noon day | Civil date grouping-এ প্রায়ই floor(JD + 0.5) |
| Modified Julian Date—MJD | JD-এর ছোট offset form | Midnight boundary | MJD = JD − 2400000.5 |
JD-এর fractional part দেখে civil clock অনুমান করার সময় noon origin মনে রাখতে হবে। JD-এর fraction .0 মানে noon; মধ্যরাত্রিতে fraction সাধারণত .5। তাই (int)jd নিয়ে Gregorian day বানানো নিরাপদ নয়।
JD day শুরু: noon
Civil-day index: floor(JD + 0.5)
MJD: JD − 2400000.5
UTC, UT1, TAI ও TT
| সময়মান | ভিত্তি | পঞ্জিকা সফটওয়্যারে ব্যবহার |
|---|---|---|
| UT1 | পৃথিবীর পর্যবেক্ষিত rotation | Earth orientation, sidereal time ও local horizon |
| UTC | Atomic seconds + leap seconds | আধুনিক civil timestamp ও time-zone conversion |
| TAI | Continuous international atomic time | TT-এর ভিত্তি; civil display নয় |
| TT | Uniform terrestrial dynamical scale | Planetary/lunar ephemeris argument |
| TDB | Barycentric coordinate time | কিছু high-precision solar-system ephemeris |
| Local civil time | UTC + zone rules | ব্যবহারকারীর তারিখ, clock ও DST |
UTC এবং UT1 কাছাকাছি হলেও এক নয়। Leap second-এর মাধ্যমে আধুনিক UTC-কে UT1-এর কাছাকাছি রাখা হয়। অন্যদিকে TT একটি uniform scale; এর সংজ্ঞায়:
TT = TAI + 32.184 seconds
১৯৭২-এর পর কোনো আধুনিক instant-এ TAI−UTC জানা থাকলে TT−UTC নির্ণয় করা যায়। কিন্তু প্রাচীন যুগে UTC ছিল না; তাই ৫৯৪ খ্রিস্টাব্দের ঘটনাকে “UTC” বলা বৈজ্ঞানিকভাবে বিভ্রান্তিকর। সেখানে UT1 বা historical UT estimate ব্যবহার করে তার সঙ্গে ΔT model যুক্ত করা উচিত।
ΔT কী?
ΔT হলো Terrestrial Time এবং Earth-rotation time-এর পার্থক্য:
ΔT = TT − UT1
JD(TT) = JD(UT1) + ΔT ÷ 86400
JD(UT1) = JD(TT) − ΔT ÷ 86400
আধুনিক যুগে আরেকটি দরকারি quantity হলো DUT1 = UT1 − UTC। তখন:
ΔT = 32.184 s + (TAI − UTC) − DUT1
ΔT seconds-কে JD-তে যোগ করার আগে অবশ্যই 86400 দিয়ে ভাগ করতে হবে। Seconds সরাসরি JD-র সঙ্গে যোগ করা মারাত্মক unit error।
ΔT clock correction নয়
ΔT কোনো time-zone offset নয় এবং এটি local clock-এর সঙ্গে সরাসরি যোগ করার বিষয়ও নয়। এটি dynamical ephemeris time ও পৃথিবীর rotation-based time-এর মধ্যে সেতু। Time-zone conversion একটি পরবর্তী, পৃথক ধাপ।
Astronomical instant থেকে পঞ্জিকা-দিন: সঠিক pipeline
- Input civil date, location ও time-zone policy গ্রহণ করুন;
- Modern date হলে local time → UTC; historical date হলে declared local-mean/civil policy → UT approximation;
- UT1/UT JD তৈরি করুন;
- নির্বাচিত ΔT model দিয়ে TT JD তৈরি করুন;
- TT-তে Sun/Moon/planet position বা conjunction solve করুন;
- Event instant-কে UT1-এ ফিরিয়ে Earth rotation ও horizon calculation করুন;
- তারপর location-এর civil offset ও calendar mode প্রয়োগ করুন;
- শেষে sunrise/midnight/festival rule দিয়ে পঞ্জিকা-দিন নির্ধারণ করুন;
- Display rounding একেবারে শেষে করুন।
একটি event solver যদি TT-তে root খুঁজে পায়, তার result-কে local time দেখানোর আগে UT1/UTC conversion করতে হবে। আবার swe_calc_ut-এর মতো API যদি UT input নিয়েই internally ΔT প্রয়োগ করে, সেখানে নিজে ΔT যোগ করলে correction দ্বিগুণ হয়ে যাবে।
ঐতিহাসিক ΔT কেন অনিশ্চিত?
Modern atomic clock-এর আগে পৃথিবীর rotation সরাসরি একই precision-এ record করা হয়নি। Ancient ও medieval যুগের ΔT estimate মূলত eclipse, occultation এবং অন্যান্য historical observation থেকে পুনর্গঠিত। Record যত পুরোনো, uncertainty সাধারণত তত বড়।
ফলে ঐতিহাসিক computation-এ “04:21:01 PM” print করা software-এর numerical resolution দেখাতে পারে, কিন্তু তা historical physical certainty-এর সমান নয়। একটি responsible report-এ তাই রাখা উচিত:
- ΔT model-এর নাম ও version;
- প্রয়োগ করা ΔT value—seconds-এ;
- Time scale label—UT1, TT বা UTC;
- Calendar label—Julian/Gregorian/proleptic Gregorian;
- Estimated uncertainty বা অন্তত qualitative confidence;
- Ephemeris engine/version ও tidal-acceleration setting;
- স্থানীয় সময়ের policy—historical local mean time না modern zone projection।
Calendar conversion ও time-scale conversion আলাদা
১৫৮২ সালের Gregorian reform calendar label পরিবর্তন করেছে; এটি TT বা UT1-এর সংজ্ঞা বদলায়নি। তাই computation-এ দুটি independent choice রাখতে হবে:
| Choice | উদাহরণ | কী বদলায় |
|---|---|---|
| Time scale | TT ↔ UT1 | একই event-এর numerical time coordinate |
| Calendar system | Julian ↔ Gregorian | একই instant-এর year-month-day label |
| Time zone | UT1/UTC → Dhaka/Kolkata/New York | Local clock ও কখনও local civil date |
| Panjika rule | Sunrise-to-sunrise | Event কোন পঞ্জিকা-দিনে প্রয়োগ হবে |
Historical export-এ dual Julian/Gregorian date দেখানো যেতে পারে, কিন্তু underlying event JD একটিই থাকবে। অর্থাৎ দুটি তারিখ দুটি event নয়; একই instant-এর দুটি calendar representation।
Swiss Ephemeris-এ কোন input দেবেন?
Swiss Ephemeris interface-এ function family অনুযায়ী time-scale contract আলাদা। Wrapper-এর documentation যাচাই করা আবশ্যক, তবে সাধারণ নীতি হলো:
| Function family | Expected input | সতর্কতা |
|---|---|---|
swe_calc_ut |
Julian day in UT | Library internally ΔT ব্যবহার করে |
swe_calc |
Julian day in ET/TT | UT JD সরাসরি পাঠাবেন না |
swe_deltat_ex |
UT Julian day | Return unit সাধারণত day; wrapper যাচাই করুন |
swe_julday |
Calendar fields + decimal hour | Julian/Gregorian flag explicit করুন |
| Rise/set/transit functions | সাধারণত UT-based JD | Location, altitude ও refraction profile-ও লাগে |
ভুল double conversion-এর উদাহরণ
// Wrong if CalcUt already converts UT to ephemeris time internally.
double jdTt = jdUt + deltaTSeconds / 86400.0;
CalcUt(jdTt, body, flags);
সঠিক contract
// UT-input API
CalcUt(jdUt, body, flags);
// TT/ET-input API
double jdTt = jdUt + deltaTSeconds / 86400.0;
CalcEt(jdTt, body, flags);
একই report-এ দুই interface mix করলে raw values-এর সঙ্গে scale label রাখুন। Variable name শুধু jd না রেখে jdUt1, jdTt বা jdUtc লিখলে বহু bug compile-time-এর আগেই review-এ ধরা পড়ে।
C#-এ scale-safe data model
public enum AstronomicalTimeScale
{
Ut1,
Utc,
Tai,
Tt,
Tdb
}
public sealed class JulianInstant
{
public double Value { get; private set; }
public AstronomicalTimeScale Scale { get; private set; }
public JulianInstant(double value, AstronomicalTimeScale scale)
{
if (Double.IsNaN(value) || Double.IsInfinity(value))
throw new ArgumentOutOfRangeException("value");
Value = value;
Scale = scale;
}
}
এতে UT JD ভুল করে TT-input function-এ পাঠানো পুরোপুরি বন্ধ হয় না, কিন্তু method signature-এ scale check করা সহজ হয়:
static JulianInstant Ut1ToTt(
JulianInstant ut1,
double deltaTSeconds)
{
if (ut1.Scale != AstronomicalTimeScale.Ut1)
throw new ArgumentException("UT1 input is required.");
return new JulianInstant(
ut1.Value + deltaTSeconds / 86400.0,
AstronomicalTimeScale.Tt);
}
static JulianInstant TtToUt1(
JulianInstant tt,
double deltaTSeconds)
{
if (tt.Scale != AstronomicalTimeScale.Tt)
throw new ArgumentException("TT input is required.");
return new JulianInstant(
tt.Value - deltaTSeconds / 86400.0,
AstronomicalTimeScale.Ut1);
}
Model metadata-ও result-এর অংশ
public sealed class HistoricalTimeContext
{
public string DeltaTModel { get; set; }
public string DeltaTModelVersion { get; set; }
public double DeltaTSeconds { get; set; }
public string CalendarMode { get; set; }
public string LocalTimePolicy { get; set; }
public string EphemerisVersion { get; set; }
}
HTML, XML ও API export-এ অন্তত machine-readable metadata রাখুন। শুধু formatted string রাখলে ভবিষ্যতে model বদলানোর পর পুরোনো ফল পুনরুৎপাদন করা যাবে না।
JD split করলে precision ভালো থাকে
প্রায় ২৪ লক্ষের কাছাকাছি বড় JD-এর সঙ্গে ক্ষুদ্র fraction বারবার যোগ-বিয়োগ করলে floating-point resolution কমে। High-precision solver-এ একটি reference epoch এবং ছোট offset আলাদা রাখা যেতে পারে:
public struct SplitJulianDate
{
public double Epoch;
public double Offset;
public double Total
{
get { return Epoch + Offset; }
}
}
SplitJulianDate value = new SplitJulianDate();
value.Epoch = 2451545.0;
value.Offset = eventJd - value.Epoch;
এটি ভুল time scale ঠিক করে না; শুধু numerical representation উন্নত করে। Scale label এখনও আবশ্যক।
বাংলা সন ১ ও JD 1938094.4629
এই প্রকল্পে গবেষণা-নির্বাচিত মেষ সংক্রান্তির ভিত্তি হিসেবে JD 1938094.4629 ব্যবহৃত হয়েছে। প্রকাশনার আগে সংখ্যাটির সঙ্গে নিচের প্রশ্নগুলোর উত্তর স্থায়ীভাবে লিখে রাখা উচিত:
- JD-টি TT, UT1 না অন্য scale-এ?
- এটি কোন engine/model থেকে পাওয়া?
- ব্যবহৃত ΔT কত এবং কোন model-এর?
- ৫৯৪ খ্রিস্টাব্দের local time কীভাবে তৈরি করা হয়েছে?
- Julian ও proleptic Gregorian label কী?
- বাংলা প্রথম দিন নির্ধারণে কোন sunrise/midnight rule প্রয়োগ হয়েছে?
এই metadata ছাড়া ভবিষ্যৎ গবেষক একই decimal number পেলেও একই civil date বা clock time নাও পেতে পারেন। বিশেষ করে modern IANA time-zone rules-কে ৫৯৪ খ্রিস্টাব্দে পিছিয়ে নেওয়া ঐতিহাসিক বাস্তবতার দাবি নয়; এটি একটি declared computational projection মাত্র।
প্রস্তাবিত output format
{
"event": "Mesha Sankranti",
"jd": 1938094.4629,
"timeScale": "TT",
"deltaTSeconds": null,
"deltaTModel": "PROJECT-CONSTANT / replace with actual model",
"calendarLabels": {
"julian": "...",
"prolepticGregorian": "..."
},
"localTimePolicy": "Declared project policy",
"calculationVersion": "..."
}
উপরের deltaTSeconds: null বোঝায় যে example-এ value ইচ্ছাকৃতভাবে দেওয়া হয়নি। Published data-তে নির্বাচিত model-এর actual output লিখতে হবে; অজানা value-কে শূন্য ধরে নেওয়া যাবে না।
Validation checklist
- প্রতিটি JD field-এর scale label আছে;
- Variable name-এ
jdUt1/jdTtআলাদা; - JD noon origin unit-tested;
- Midnight JD fraction
.5test করা; - JDN conversion-এ
floor(JD + 0.5)যাচাই; - MJD offset 2400000.5 test করা;
- Julian Date ও Julian calendar আলাদা type/parameter;
- Gregorian flag explicit;
- Proleptic Gregorian mode explicit;
- 1582 reform gap display policy documented;
- 1752 regional reform hard-code না করা;
- ΔT seconds-to-days conversion test;
- UT1 → TT sign positive test;
- TT → UT1 sign negative test;
- Round-trip UT1 → TT → UT1 test;
- ΔT model/version result-এ stored;
- Historical uncertainty note stored;
- DUT1-এর sign convention documented;
- TT = TAI + 32.184 s test;
- Modern leap-second table version recorded;
- Pre-UTC date-কে UTC label না দেওয়া;
swe_calc_ut-এ UT input;swe_calc-এ TT/ET input;- ΔT double-applied নয়;
swe_deltat_exreturn unit verified;- Rise/set input contract verified;
- Ephemeris flags consistent;
- Tidal-acceleration setting recorded;
- Root solver এক time scale-এ থাকে;
- Root result convert করার পরে scale updated;
- Local zone conversion event solve-এর পরে;
- DST historical rule date-aware;
- Ancient date-এ modern zone projection labeled;
- Sunrise comparison raw instant দিয়ে;
- Midnight comparison raw instant দিয়ে;
- Display rounding calendar decision-এর পরে;
- Dual J/G labels একই JD থেকে তৈরি;
- Early AD date
DateTimerange test; - BCE date-এর জন্য astronomical year numbering documented;
- Year 0 conversion policy test;
- Locale-independent numeric serialization;
- XML/API-তে enough decimal precision;
- HTML-এ human-readable scale label;
- Engine/version regression snapshot;
- Alternative ΔT model sensitivity test;
- Threshold-near event manually reviewed;
- Known USNO JD example matched;
- Known Swiss Ephemeris example matched;
- Round-trip calendar → JD → calendar test;
- Production log-এ full time context retained।
সাধারণ ভুল ও সমাধান
| ভুল | ফল | সমাধান |
|---|---|---|
সব variable-এর নাম jd |
UT/TT অদলবদল | Scale-bearing type ও explicit names |
| JD fraction-কে midnight-origin ধরা | ১২ ঘণ্টার error | Noon origin মনে রাখা |
| ΔT seconds সরাসরি JD-তে যোগ | হাজার দিনের error | 86400 দিয়ে ভাগ |
swe_calc_ut-এর আগে ΔT যোগ |
ΔT double correction | API contract অনুযায়ী input |
| ৫৯৪ সালের time-কে UTC বলা | Anachronistic label | Historical UT1/UT estimate লিখুন |
| Julian calendar = Julian Date ধরা | Calendar conversion ভুল | Day count ও calendar পৃথক |
| Ancient output-এ seconds দেখিয়ে exact দাবি | False precision | ΔT uncertainty প্রকাশ |
| Modern zone rules অতীতে silently প্রয়োগ | Misleading local time | Local-time policy label |
উপসংহার
Julian Date কেবল একটি continuous day count। তার সঙ্গে কোন time scale যুক্ত—UT1, UTC, TT বা TDB—তা আলাদাভাবে জানাতে হয়। Planetary ephemeris সাধারণত uniform dynamical time-এ চলে; Earth rotation ও local horizon calculation-এর জন্য UT1 দরকার; আর ব্যবহারকারীর civil display-এর জন্য UTC/time-zone layer লাগে।
ΔT এই দুই astronomical সময়মানের সেতু, time-zone offset নয়। Historical epoch-এ ΔT একটি model-dependent estimate; তাই result-এর সঙ্গে model, version ও uncertainty প্রকাশ করা বৈজ্ঞানিক সততার অংশ। Julian/Gregorian calendar conversion আবার time-scale conversion থেকে সম্পূর্ণ আলাদা একটি layer।
একটি production-quality পঞ্জিকা engine তাই raw JD-এর পাশাপাশি scale, calendar, zone policy, ΔT model এবং applied rule trace সংরক্ষণ করবে। এতে বাংলা সন ১ থেকে আধুনিক দিন পর্যন্ত calculation পুনরুৎপাদনযোগ্য, পরীক্ষাযোগ্য এবং ব্যবহারকারীর কাছে ব্যাখ্যাযোগ্য থাকবে।
তথ্যসূত্র ও আরও পাঠ
- U.S. Naval Observatory—Julian Date Converter; JD-এর noon origin, UT1 basis ও fractional-day convention.
- U.S. Naval Observatory—Astronomical Almanac Glossary; JD, JDN, MJD ও time-scale qualification.
- USNO Earth Orientation—What are Earth Orientation Parameters?; UT1 ও Earth rotation.
- USNO Earth Orientation Values; ΔT, TAI−UTC ও UT1−UTC সম্পর্ক.
- NASA/GSFC—Delta T and Universal Time; dynamical time, UT ও historical ΔT.
- NASA/GSFC—Polynomial Expressions for Delta T; historical/future model intervals.
- Swiss Ephemeris Programmer’s Documentation; UT/ET function contracts ও ΔT handling.
- Astrodienst—Swiss Ephemeris documentation overview; general ও programmer documentation.
মন্তব্য, আলোচনা ও প্রশ্ন