সূর্য সিদ্ধান্ত পঞ্জিকা সকল প্রবন্ধ

Julian Day, UT, TT ও ΔT: ঐতিহাসিক গণনায় কোন Time Scale কোথায় লাগে?

Julian Date ও Julian calendar-এর পার্থক্য, JD/JDN/MJD, UT1, UTC, TAI, TT, ΔT, Swiss Ephemeris input এবং ঐতিহাসিক পঞ্জিকা গণনার production-safe C# পদ্ধতি।

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

  1. Input civil date, location ও time-zone policy গ্রহণ করুন;
  2. Modern date হলে local time → UTC; historical date হলে declared local-mean/civil policy → UT approximation;
  3. UT1/UT JD তৈরি করুন;
  4. নির্বাচিত ΔT model দিয়ে TT JD তৈরি করুন;
  5. TT-তে Sun/Moon/planet position বা conjunction solve করুন;
  6. Event instant-কে UT1-এ ফিরিয়ে Earth rotation ও horizon calculation করুন;
  7. তারপর location-এর civil offset ও calendar mode প্রয়োগ করুন;
  8. শেষে sunrise/midnight/festival rule দিয়ে পঞ্জিকা-দিন নির্ধারণ করুন;
  9. 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 ব্যবহৃত হয়েছে। প্রকাশনার আগে সংখ্যাটির সঙ্গে নিচের প্রশ্নগুলোর উত্তর স্থায়ীভাবে লিখে রাখা উচিত:

  1. JD-টি TT, UT1 না অন্য scale-এ?
  2. এটি কোন engine/model থেকে পাওয়া?
  3. ব্যবহৃত ΔT কত এবং কোন model-এর?
  4. ৫৯৪ খ্রিস্টাব্দের local time কীভাবে তৈরি করা হয়েছে?
  5. Julian ও proleptic Gregorian label কী?
  6. বাংলা প্রথম দিন নির্ধারণে কোন 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

  1. প্রতিটি JD field-এর scale label আছে;
  2. Variable name-এ jdUt1/jdTt আলাদা;
  3. JD noon origin unit-tested;
  4. Midnight JD fraction .5 test করা;
  5. JDN conversion-এ floor(JD + 0.5) যাচাই;
  6. MJD offset 2400000.5 test করা;
  7. Julian Date ও Julian calendar আলাদা type/parameter;
  8. Gregorian flag explicit;
  9. Proleptic Gregorian mode explicit;
  10. 1582 reform gap display policy documented;
  11. 1752 regional reform hard-code না করা;
  12. ΔT seconds-to-days conversion test;
  13. UT1 → TT sign positive test;
  14. TT → UT1 sign negative test;
  15. Round-trip UT1 → TT → UT1 test;
  16. ΔT model/version result-এ stored;
  17. Historical uncertainty note stored;
  18. DUT1-এর sign convention documented;
  19. TT = TAI + 32.184 s test;
  20. Modern leap-second table version recorded;
  21. Pre-UTC date-কে UTC label না দেওয়া;
  22. swe_calc_ut-এ UT input;
  23. swe_calc-এ TT/ET input;
  24. ΔT double-applied নয়;
  25. swe_deltat_ex return unit verified;
  26. Rise/set input contract verified;
  27. Ephemeris flags consistent;
  28. Tidal-acceleration setting recorded;
  29. Root solver এক time scale-এ থাকে;
  30. Root result convert করার পরে scale updated;
  31. Local zone conversion event solve-এর পরে;
  32. DST historical rule date-aware;
  33. Ancient date-এ modern zone projection labeled;
  34. Sunrise comparison raw instant দিয়ে;
  35. Midnight comparison raw instant দিয়ে;
  36. Display rounding calendar decision-এর পরে;
  37. Dual J/G labels একই JD থেকে তৈরি;
  38. Early AD date DateTime range test;
  39. BCE date-এর জন্য astronomical year numbering documented;
  40. Year 0 conversion policy test;
  41. Locale-independent numeric serialization;
  42. XML/API-তে enough decimal precision;
  43. HTML-এ human-readable scale label;
  44. Engine/version regression snapshot;
  45. Alternative ΔT model sensitivity test;
  46. Threshold-near event manually reviewed;
  47. Known USNO JD example matched;
  48. Known Swiss Ephemeris example matched;
  49. Round-trip calendar → JD → calendar test;
  50. 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 পুনরুৎপাদনযোগ্য, পরীক্ষাযোগ্য এবং ব্যবহারকারীর কাছে ব্যাখ্যাযোগ্য থাকবে।

তথ্যসূত্র ও আরও পাঠ

  1. U.S. Naval Observatory—Julian Date Converter; JD-এর noon origin, UT1 basis ও fractional-day convention.
  2. U.S. Naval Observatory—Astronomical Almanac Glossary; JD, JDN, MJD ও time-scale qualification.
  3. USNO Earth Orientation—What are Earth Orientation Parameters?; UT1 ও Earth rotation.
  4. USNO Earth Orientation Values; ΔT, TAI−UTC ও UT1−UTC সম্পর্ক.
  5. NASA/GSFC—Delta T and Universal Time; dynamical time, UT ও historical ΔT.
  6. NASA/GSFC—Polynomial Expressions for Delta T; historical/future model intervals.
  7. Swiss Ephemeris Programmer’s Documentation; UT/ET function contracts ও ΔT handling.
  8. Astrodienst—Swiss Ephemeris documentation overview; general ও programmer documentation.

মন্তব্য, আলোচনা ও প্রশ্ন