জানুন কিভাবে JavaScript-এ সময় ফরম্যাট ও রূপান্তর করবেন যাতে অপ্রত্যাশিত ফলাফল না আসে: টাইমস্ট্যাম্প, ISO স্ট্রিং, টাইমজোন, DST, পার্সিং নিয়ম ও নির্ভরযোগ্য প্যাটার্ন।

JavaScript সময় বাগগুলো সচরাচর 'ঘড়িটা ভুল' হিসেবে দেখায় না। বরং তারা ছোট কিন্তু বিভ্রান্তিকর শিফট হিসেবে আসে: আপনার ল্যাপটপে একটি তারিখ ঠিক দেখায় কিন্তু সহকর্মীর মেশিনে ভুল, একটি API উত্তর যা ঠিক মনে হয় যতক্ষণ না সেটা অন্য টাইমজোনে রেন্ডার করা হয়, বা মৌসুমী সময় পরিবর্তনের সময় 'এক ঘন্টা' বা 'এক দিন' লাফ।
আপনি সাধারণত নিম্নলিখিত কোনটি (বা একাধিক) লক্ষ্য করবেন:
+02:00) আপনার প্রত্যাশার সাথে মিলছে না।বিরাট সমস্যা হল 'সময়' শব্দটি বিভিন্ন ধারণা বোঝাতে পারে:
JavaScript-এর বিল্ট-ইন Date এগুলোই কভার করার চেষ্টা করে, কিন্তু এটি মূলত একটি মুহূর্ত প্রতিনিধিত্ব করে এবং প্রদর্শনের সময় স্বয়ংক্রিয়ভাবে লোকাল নিয়মের দিকে ঠেলছে—এটাই অনিচ্ছাকৃত রূপান্তরকে সহজ করে।
এই গাইডটি বাস্তবমুখী: কিভাবে ব্রাউজার ও সার্ভার জুড়ে প্রেডিক্টেবল রূপান্তর করবেন, কোন ফরম্যাট নিরাপদ (যেমন ISO 8601) এবং সাধারণ ফাঁদগুলো কিভাবে শনাক্ত করবেন (সেকেন্ড বনাম মিলিসেকেন্ড, UTC বনাম লোকাল, পার্সিং পার্থক্য)। লক্ষ্য বেশি তত্ত্ব নয়—কম 'কেন এটা শিফট করছে' বিস্ময়।
JavaScript সময় বাগও সাধারণত এমন প্রতিনিধিত্বগুলো মিলিয়ে ফেলার কারণে শুরু হয় যা একে অপরের মতো দেখলেও বাস্তবে ভিন্ন।
1) এপক মিলিসেকেন্ড (সংখ্যা)
একটি সাদাসিধে সংখ্যা যেমন 1735689600000 সাধারণত '1970-01-01T00:00:00Z থেকে মিলিসেকেন্ড' হিসেবে থাকে। এটি একটি মুহূর্ত প্রতিনিধিত্ব করে এবং কোন ফরম্যাট বা টাইমজোন জোড়া থাকে না।
2) Date অবজেক্ট (একটি মুহূর্তের ওয়্র্যাপার)
Date একই ধরনের মুহূর্ত রাখে যতটা একটি টাইমস্ট্যাম্প রাখে। বিভ্রান্তিকর অংশ: যখন আপনি Date প্রিন্ট করেন, JavaScript পরিবেশের লোকাল নিয়ম অনুসারে ফরম্যাট করে যদি না আপনি অন্য কিছু চান।
3) ফরম্যাট করা স্ট্রিং (মানুষ-পাঠযোগ্য)
স্ট্রিংগুলো যেমন '2025-01-01', '01/01/2025 10:00', বা '2025-01-01T00:00:00Z' একটাই নয়। কিছু অনির্বচনীয় নয় (ISO 8601 Z সহ), কিছু লোকেল-নির্ভর, এবং কিছুতে টাইমজোন থাকে না।
একই মুহূর্ত টাইমজোন অনুযায়ী আলাদা দেখাতে পারে:
const instant = new Date("2025-01-01T00:00:00Z");
instant.toLocaleString("en-US", { timeZone: "UTC" });
// "1/1/2025, 12:00:00 AM"
instant.toLocaleString("en-US", { timeZone: "America/Los_Angeles" });
// "12/31/2024, 4:00:00 PM" (আগের দিন)
একটি একক অভ্যন্তরীণ প্রতিনিধিত্ব (সাধারণত এপক মিলিসেকেন্ড বা UTC ISO 8601) বেছে নিন এবং পুরো অ্যাপ ও API জুড়ে সেটিই অনুসরণ করুন। Date বা ফরম্যাট স্ট্রিং-এ কনভার্ট করুন কেবল প্রান্তে: ইনপুট পার্সিং ও UI প্রদর্শনে।
'টাইমস্ট্যাম্প' সাধারণত অর্থ করে এপক সময় (Unix time): 1970-01-01 00:00:00 UTC থেকে কটা সময় পার হয়েছে। কষ্টকর অংশ: বিভিন্ন সিস্টেম বিভিন্ন ইউনিটে গণনা করে।
JavaScript-এর Date মূল বিভ্রান্তি কারণ এটি মিলিসেকেন্ড ব্যবহার করে। অনেক API, ডিবি, ও লগ সিস্টেম সেকেন্ড ব্যবহার করে।
17040672001704067200000একই মুহূর্ত, কিন্তু মিলিসেকেন্ড সংস্করণে তিনটি অতিরিক্ত সংখ্যা।
স্পষ্ট গুণ/ভাগ ব্যবহার করুন যাতে ইউনিট বোঝা যায়:
// seconds -> Date
const seconds = 1704067200;
const d1 = new Date(seconds * 1000);
// milliseconds -> Date
const ms = 1704067200000;
const d2 = new Date(ms);
// Date -> seconds
const secondsOut = Math.floor(d2.getTime() / 1000);
// Date -> milliseconds
const msOut = d2.getTime();
Date()-এএটা দেখে সঠিক মনে হয়, কিন্তু যদি ts সেকেন্ডে থাকে তাহলে এটা ভুল:
const ts = 1704067200; // seconds
const d = new Date(ts); // WRONG: treated as milliseconds
ফলাফল হবে 1970 সালে একটি দিন, কারণ 1,704,067,200 মিলিসেকেন্ড কেবল এপকের প্রায় 19 দিনই হয়।
আপনি যদি নিশ্চিত না হন কোন ইউনিট আছে, হালকা গার্ডরেইল যোগ করুন:
function asDateFromUnknownEpoch(x) {
// crude heuristic: seconds are ~1e9-1e10, milliseconds are ~1e12-1e13
if (x < 1e11) return new Date(x * 1000); // assume seconds
return new Date(x); // assume milliseconds
}
const input = Number(valueFromApi);
console.log({ input, digits: String(Math.trunc(input)).length });
console.log('as ISO:', asDateFromUnknownEpoch(input).toISOString());
যদি 'digits' ~10 হয়, সম্ভবত সেকেন্ড; যদি ~13 হয়, সম্ভবত মিলিসেকেন্ড। ডিবাগিং-এ toISOString() প্রিন্ট করুন: এটি অস্পষ্ট নয় এবং ইউনিট ভুল সহজে ধরতে সাহায্য করে।
JavaScript-এর Date বিভ্রান্তিকর কারণ এটি সংরক্ষণ করে একটি একক মুহূর্ত কিন্তু সেটি উপস্থাপন করতে পারে বিভিন্ন টাইমজোনে।
অভ্যন্তরীণভাবে, Date মূলত 'Unix epoch থেকে মিলিসেকেন্ড'। এই সংখ্যা একটি UTC মুহূর্ত নির্দেশ করে। শিফট ঘটে যখন আপনি JavaScript-কে সেই মুহূর্তকে লোকাল সময়ে (কম্পিউটার/সার্ভারের সেটিংস অনুযায়ী) বা UTC-তে ফরম্যাট করতে বলেন।
অনেক Date API-র লোকাল এবং UTC ভ্যারিয়েন্ট থাকে। একই মুহূর্তের জন্য তারা আলাদা মান রিটার্ন করে:
const d = new Date('2025-01-01T00:30:00Z');
d.getHours(); // hour in *local* time zone
d.getUTCHours(); // hour in UTC
d.toString(); // local time string
d.toISOString(); // UTC (always ends with Z)
যদি আপনার মেশিন নিউ ইয়র্ক (UTC-5) এ থাকে, ঐ UTC সময় লোকালভাবে পূর্ববর্তী দিনে '19:30' হিসেবে দেখাতে পারে। সার্ভারে যদি UTC সেট থাকে, এটি '00:30' হিসেবে দেখাবে। একই মুহূর্ত, ভিন্ন প্রদর্শন।
লগ প্রায়ই Date#toString() ব্যবহার করে বা ইমপ্লিসিটলি Date ইন্টারপোলেট করে, যা পরিবেশের লোকাল টাইমজোন ব্যবহার করে। এর মানে একই কোড ল্যাপটপ, CI ও প্রোডাকশনে ভিন্ন টাইমস্ট্যাম্প প্রিন্ট করবে যদি টাইমজোন আলাদা।
স্টোর ও ট্রান্সমিট করুন UTC হিসেবে (উদাহরণ: এপক মিলিসেকেন্ড বা ISO 8601 toISOString()), এবং কেবল প্রদর্শনের সময় ব্যবহারকারীর লোকালে কনভার্ট করুন:
toISOString() বা এপক মিলিসেকেন্ড পাস করা বেশি ভালIntl.DateTimeFormat ব্যবহার করে ব্যবহারকারীর টাইমজোনে ফরম্যাট করুনযদি দ্রুত অ্যাপ বানাচ্ছেন, তাহলে আপনার জেনারেট করা API কন্ট্রাক্টে এটি শুরুর দিকে স্পষ্টভাবে ধারণা করে রাখুন: ফিল্ডের নাম পরিষ্কার রাখুন (createdAtMs, createdAtIso) এবং সার্ভার (Go + PostgreSQL) ও ক্লায়েন্ট (React) একই অর্থে ফিল্ডগুলো বোঝে।
ব্রাউজার, সার্ভার এবং ডেটাবেসের মধ্যে তারিখ/সময় পাঠাতে হলে ISO 8601 স্ট্রিং সাধারণত সবচেয়ে নিরাপদ ডিফল্ট। এগুলো স্পষ্ট, ব্যাপকভাবে সাপোর্টেড এবং টাইমজোন তথ্য বহন করে।
দুইটি ভালো বিনিময় ফরম্যাট:
2025-03-04T12:30:00Z2025-03-04T12:30:00+02:00'Z' মানে কি?
Z হলো 'Zulu time'—আরেক নাম UTC-র জন্য। তাই 2025-03-04T12:30:00Z হলো 'UTC-এ 12:30'।
কবে +02:00 মতো অফসেট গুরুত্বপূর্ণ?
যখন ইভেন্টটি লোকাল টাইম প্রসঙ্গে বন্ধনযুক্ত (অ্যাপয়েন্টমেন্ট, বুকিং, দোকানের খোলার সময়) তখন অফসেট জরুরি। 2025-03-04T12:30:00+02:00 UTC-র থেকে দুই ঘন্টা এগিয়ে থাকা একটি মুহূর্ত নির্দেশ করে এবং এটি 2025-03-04T12:30:00Z-এর সমান নয়।
'03/04/2025' এর মত স্ট্রিং ফাঁদ: এটা মার্চ 4 নাকি এপ্রিল 3? বিভিন্ন লোকেল ও পরিবেশ আলাদা ভাবে ব্যাখ্যা করে। 2025-03-04 (ISO তারিখ) বা পূর্ণ ISO datetime ব্যবহার করুন।
const iso = '2025-03-04T12:30:00Z';
const d = new Date(iso);
const back = d.toISOString();
console.log(iso); // 2025-03-04T12:30:00Z
console.log(back); // 2025-03-04T12:30:00.000Z
এই 'রাউন্ড-ট্রিপ' আচরণ API-গুলোর জন্য প্রত্যাশিত—সুস্পষ্ট, পূর্বানুমেয় এবং টাইমজোন-সচেতন।
Date.parse() ব্যবহার করা সুবিধাজনক লাগতে পারে: একটি স্ট্রিং দিন, একটি টাইমস্ট্যাম্প পান। সমস্যা হচ্ছে ISO 8601 ছাড়া অন্য যে কোনও ফরম্যাটের জন্য পার্সিং ব্রাউজারের হিউরিস্টিক্সে নির্ভর করে। সেই হিউরিস্টিক্স ইঞ্জিন ও সংস্করণ অনুসারে ভিন্ন হয়েছে, যার ফলে একই ইনপুট বিভিন্ন স্থানে ভিন্নভাবে পার্স হতে পারে (বা পার্স না-ও হতে পারে)।
Date.parse() পরিবর্তনশীল হতে পারেজাভাস্ক্রিপ্ট শুধুমাত্র ISO 8601 স্টাইল স্ট্রিং-এর জন্য পার্সিংকে নির্দিষ্ট করেছে (এবং তাও টাইমজোনের মতো বিবরণে কিছু টার্মস আছে)। 'বন্ধুবৎসল' ফরম্যাট যেমন '03/04/2025', 'March 4, 2025', বা '2025-3-4'—ব্রাউজারগুলি:
আপনি যদি নির্দিষ্ট স্ট্রিং শেপ অনুমান করতে না পারেন, তাহলে ফলাফল পূর্বানুমেয় হবে না।
YYYY-MM-DDএকটি সাধারণ ফাঁদ হলো সরল তারিখ ফর্ম 'YYYY-MM-DD' (উদাহরণ: '2025-01-15')। অনেক ডেভেলপার আশা করেন এটি লোকাল মিদনাইট হিসেবে ব্যাখ্যা হবে। বাস্তবে, কিছু পরিবেশ এই ফর্মকে UTC মিদনাইট হিসেবে ব্যাখ্যা করে।
এই পার্থক্য গুরুত্বপূর্ণ: UTC মিদনাইট লোকাল টাইমে কনভার্ট করলে নেতিবাচক অফসেট জোনে (উদাহরণ আমেরিকাস) এটি আগের দিন হয়ে যেতে পারে বা ঘন্টা শিফট হতে পারে। এটি 'কেন আমার তারিখ এক দিন পিছিয়ে?' বাগের সাধারণ কারণ।
সার্ভার/API ইনপুটের জন্য:
2025-01-15T13:45:00Z বা 2025-01-15T13:45:00+02:00YYYY-MM-DD) হিসেবে রাখুন এবং টাইমজোন সংজ্ঞায়িত না করলে Date-এ কনভার্ট করবেন না।ব্যবহারকারীর ইনপুটের জন্য:
Date.parse()-কে 'ফিগার করে নিতে' দেবেন না; নিচের কোনো প্যাটার্ন বেছে নিন:
new Date(year, monthIndex, day) ব্যবহার করে লোকাল ডেট তৈরি করুন)সময়-সংবেদনশীল ডাটা হলে 'আমার মেশিনে পার্স হচ্ছে' যথেষ্ট নয়—আপনার পার্সিং নিয়ম স্পষ্ট ও ধারাবাহিক হতে হবে।
যদি লক্ষ্য হলো 'ব্যবহারকারীদের প্রত্যাশা অনুযায়ী একটি তারিখ/সময় দেখানো', তাহলে JavaScript-এ সেরা টুল হলো Intl.DateTimeFormat। এটি ব্যবহারকারীর লোকেল নিয়ম অনুসারে (অর্ডার, সেপারেটর, মাসের নাম) আউটপুট দেয় এবং ম্যানুয়ালি স্ট্রিং জোড়ার ঝুঁকিকে কমায়।
ম্যানুয়াল ফরম্যাটিং প্রায়শই US-স্টাইল ধরে নেয়, লিডিং জিরো ভুলে যায়, বা 24/12-ঘন্টার বিভ্রান্তি সৃষ্টি করে। Intl.DateTimeFormat স্পষ্ট করে দেয় কোন টাইমজোনে প্রদর্শন করা হবে—বিশেষত গুরুত্বপূর্ণ যখন ডেটা UTC-তে স্টোর করা থাকে কিন্তু UI-তে লোকাল টাইম দেখানো দরকার।
'ভালোভাবে ফরম্যাট' করার জন্য dateStyle ও timeStyle সহজ এবং কার্যকর:
const d = new Date('2025-01-05T16:30:00Z');
// User's locale + user's local time zone
console.log(new Intl.DateTimeFormat(undefined, {
dateStyle: 'medium',
timeStyle: 'short'
}).format(d));
// Force a specific time zone (great for event times)
console.log(new Intl.DateTimeFormat('en-GB', {
dateStyle: 'full',
timeStyle: 'short',
timeZone: 'UTC'
}).format(d));
আপনি যদি নির্দিষ্ট hour cycle চান (যেমন সেটিং-এ 24/12 ঘন্টার স্যুইচ), তখন hour12 ব্যবহার করুন:
console.log(new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: '2-digit',
hour12: true
}).format(d));
প্রতিটি UI টাইপের জন্য (মেসেজ টাইম, লগ এন্ট্রি, ইভেন্ট স্টার্ট) একটি ফরম্যাট ফাংশন বেছে নিন এবং timeZone সিদ্ধান্তটি ইচ্ছাকৃত রাখুন:
এতে আপনি কনসিস্টেন্ট, লোকেল-ফ্রেন্ডলি আউটপুট পাবেন এবং ঝুঁকিপূর্ণ কাস্টম ফরম্যাট স্ট্রিং বজায় রাখতে হবে না।
Daylight Saving Time (DST) হল যখন একটি টাইমজোন নির্দিষ্ট তারিখে UTC অফসেট পরিবর্তন করে (সাধারণত এক ঘন্টা)। জটিল অংশ: DST কেবল অফসেট পরিবর্তন করে না—কিছু লোকাল টাইমসের অস্তিত্বই বদলে দেয়।
ক্লক যখন 'spring forward' করে, কিছু লোকাল টাইম ঘটেই না। উদাহরণ: অনেক এলাকায় ঘড়ি 01:59 থেকে 03:00 এ লাফ, তাই 02:30 লোকাল সময় হলো 'মিসিং'।
ক্লক যখন 'fall back' করে, কিছু লোকাল টাইম দুইবার ঘটে। উদাহরণ: 01:30 শিফটের আগে ও পরে দুইবার ঘটতে পারে, তাই একই ওয়াল-ক্লক টাইম দুটি ভিন্ন মুহূর্ত নির্দেশ করতে পারে।
DST বর্ডারের আশেপাশে এগুলো সমান নয়:
যদি আজ DST শুরু করে, 'আগামীকাল একই লোকাল সময় 9:00' হতে পারে কেবল 23 ঘন্টা দূরে; যদি DST শেষ করে, এটি হতে পারে 25 ঘন্টা দূরে।
// Scenario: schedule 'same local time tomorrow'
const d = new Date(2025, 2, 8, 9, 0); // Mar 8, 9:00 local
const plus24h = new Date(d.getTime() + 24 * 60 * 60 * 1000);
const nextDaySameLocal = new Date(d);
nextDaySameLocal.setDate(d.getDate() + 1);
// Around DST, plus24h and nextDaySameLocal can differ by 1 hour.
setHours চমক দিতে পারেআপনি যদি এমন কিছু করেন: date.setHours(2, 30, 0, 0) একটি 'spring forward' দিনে, JavaScript এটি একটি ভিন্ন বৈধ সময়ে নরমালাইজ করতে পারে (প্রায়ই 03:30), কারণ 02:30 লোকাল সময়ে বিদ্যমান নয়।
setDate) ব্যবহার করে করুন পরিবর্তে মিলিসেকেন্ড যোগ করার।সাধারণ বাগ হলো Date ব্যবহার করে এমন কিছু উপস্থাপন করা যা ক্যালেন্ডার মুহূর্ত নয়।
টাইমস্ট্যাম্প উত্তর দেয় 'এটা কবে ঘটল?' (উদাহরণ: '2025-12-23T10:00:00Z')। ডিউরেশন উত্তর দেয় 'কত সময়?' (যেমন '3 মিনিট 12 সেকেন্ড')। এগুলো আলাদা ধারণা, এবং মিশালে বিভ্রান্তি ও অপ্রত্যাশিত টাইমজোন/DST প্রভাব আসে।
Date ডিউরেশনের জন্য ভুল টুলDate সবসময় একটি পয়েন্ট অন টাইমলাইনে স্টোর করে এপকের আপেক্ষিক। যদি আপনি '90 সেকেন্ড' একটি Date হিসেবে রাখেন, আপনি প্রকৃতপক্ষে '1970-01-01 plus 90 seconds' স্টোর করছেন কোনো নির্দিষ্ট টাইমজোনে। ফরম্যাট করলে এটি হঠাৎ '01:01:30' দেখাতে পারে, এক ঘন্টা শিফট পেতে পারে, বা এমন একটি দিন দেখাতে পারে যা আপনার উদ্দেশ্য ছিল না।
ডিউরেশনের জন্য বেছে নিন সাদাসিধে সংখ্যা:
HH:mm:ss-এ রূপান্তরগননা টাইমার বা মিডিয়া দৈর্ঘ্যের জন্য একটি সহজ ফরম্যাটার:
function formatHMS(totalSeconds) {
const s = Math.max(0, Math.floor(totalSeconds));
const hh = String(Math.floor(s / 3600)).padStart(2, "0");
const mm = String(Math.floor((s % 3600) / 60)).padStart(2, "0");
const ss = String(s % 60).padStart(2, "0");
return `${hh}:${mm}:${ss}`;
}
formatHMS(75); // "00:01:15" (countdown timer)
formatHMS(5423); // "01:30:23" (media duration)
যদি মিনিট থেকে কনভার্ট করেন, আগে গুণ করুন (minutes * 60) এবং রেন্ডার করা পর্যন্ত মানটি সংখ্যায় রাখুন।
JavaScript-এ সময় তুলনা করার সময় সবচেয়ে নিরাপদ হলো সংখ্যার বিরুদ্ধে সংখ্যা তুলনা করা, না ফরম্যাট করা টেক্সটের। একটি Date অবজেক্ট মূলত একটি এপক মিলিসেকেন্ড সংখ্যার র্যাপার, তাই তুলনা করলে ইচ্ছাকৃতভাবে 'নাম্বার বনাম নাম্বার' হওয়া উচিত।
ভরসাযোগ্যভাবে তুলনা করতে getTime() (বা Date.valueOf()) ব্যবহার করুন যা একই সংখ্যা রিটার্ন করে:
const a = new Date('2025-01-10T12:00:00Z');
const b = new Date('2025-01-10T12:00:01Z');
if (a.getTime() < b.getTime()) {
// a is earlier
}
// Also works:
if (+a < +b) {
// unary + calls valueOf()
}
ফরম্যাট করা স্ট্রিং যেমন '1/10/2025, 12:00 PM' তুলনা করা এড়ান—সেগুলো লোকেল-নির্ভর এবং সঠিকভাবে সোর্ট করবে না। একমাত্র ব্যতিক্রম হলো একই ফরম্যাটে থাকা ISO 8601 স্ট্রিং (উদাহরণ: সবই '...Z')—সেগুলো লেক্সিকোগ্রাফিকালি সোর্টেবল।
টাইম দিয়ে সোর্ট করা সহজ যদি আপনি এপক মিলিসেকেন্ড দিয়ে সোর্ট করেন:
items.sort((x, y) => new Date(x.createdAt).getTime() - new Date(y.createdAt).getTime());
রেঞ্জের মধ্যে ফিল্টার করাও একই ধারণা:
const start = new Date('2025-01-01T00:00:00Z').getTime();
const end = new Date('2025-02-01T00:00:00Z').getTime();
const inRange = items.filter(i => {
const t = new Date(i.createdAt).getTime();
return t >= start && t < end;
});
'দিনের শুরু' নির্ভর করে আপনি লোকাল সময় বোঝাতে চান নাকি UTC:
// Local start/end of day
const d = new Date(2025, 0, 10); // Jan 10 in local time
const localStart = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0, 0);
const localEnd = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59, 999);
// UTC start/end of day
const utcStart = new Date(Date.UTC(2025, 0, 10, 0, 0, 0, 0));
const utcEnd = new Date(Date.UTC(2025, 0, 10, 23, 59, 59, 999));
একটি সংজ্ঞা আগে বেছে নিন এবং আপনার তুলনা ও রেঞ্জ লজিকে সেটি ধারাবাহিকভাবে অনুসরণ করুন।
টাইম বাগগুলো র্যান্ডম মনে হয় যতক্ষণ না আপনি নির্দিষ্ট করেন 'আপনার কাছে কি আছে' (টাইমস্ট্যাম্প? স্ট্রিং? Date?) এবং 'কোথায় শিফট আসছে' (পার্সিং, টাইমজোন কনভার্শন, ফরম্যাটিং)।
প্রথমে একই মান তিনভাবে লগ করুন। এটি দ্রুত জানিয়ে দেয় সমস্যা সেকেন্ড বনাম মিলিসেকেন্ড, লোকাল বনাম UTC, বা স্ট্রিং পার্সিং কিনা।
console.log('raw input:', input);
const d = new Date(input);
console.log('toISOString (UTC):', d.toISOString());
console.log('toString (local):', d.toString());
console.log('timezone offset (min):', d.getTimezoneOffset());
খেয়াল রাখার বিষয়:
toISOString() অত্যন্ত ভুল (উদাহরণ: বছর 1970 বা অনেক দূরের ভবিষ্যৎ), সন্দেহ করুন সেকেন্ড বনাম মিলিসেকেন্ডtoISOString() ঠিক দেখায় কিন্তু toString() শিফট করে, আপনি লোকাল টাইমজোন প্রদর্শন সমস্যার সম্মুখীনgetTimezoneOffset() তারিখ অনুযায়ী পরিবর্তিত হয়, আপনি DST অতিক্রম করছেনঅনেক 'আমার মেশিনে কাজ করছে' রিপোর্ট কেবল বিভিন্ন পরিবেশ ডিফল্টের কারণ।
console.log(Intl.DateTimeFormat().resolvedOptions());
console.log('TZ:', process.env.TZ);
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);
যদি আপনার সার্ভার UTC-এ চলে কিন্তু আপনার ল্যাপটপ লোকাল জোনে থাকে, ফরম্যাট করা আউটপুট আলাদা হবে যদি না আপনি স্পষ্টভাবে timeZone নির্দিষ্ট করেন।
DST বর্ডার ও 'এজ' টাইমগুলোর চারপাশে ইউনিট টেস্ট তৈরি করুন:
23:30 → 00:30 ক্রসোভারযদি দ্রুত iteration করছেন, এই টেস্টগুলো আপনার স্ক্যাফোল্ডিং-এ রাখুন। উদাহরণস্বরূপ, React + Go অ্যাপ জেনারেট করলে একটি ছোট 'টাইম কন্ট্রাক্ট' টেস্টসুট আগে থেকেই যোগ করুন (API পে-লোড উদাহরণ + পার্স/ফরম্যাট অ্যাসার্শন) যাতে রিগ্রেশন প্রোডাকশনে পৌঁছার আগে ধরা পড়ে।
locale এবং (প্রয়োজনে) timeZone নির্দিষ্ট করেJavaScript-এ নির্ভরযোগ্য সময় হ্যান্ডলিং বেশিরভাগই একটি 'source of truth' বেছে নেওয়া এবং স্টোরেজ থেকে প্রদর্শন পর্যন্ত ধারাবাহিক থাকা।
UTC তে স্টোর ও ক্যালকুলেট করুন। ব্যবহারকারীর লোকাল সময়কে কেবল উপস্থাপনা বিবরণ হিসেবে বিবেচনা করুন।
সিস্টেমগুলোর মধ্যে তারিখ ট্রান্সমিট করুন ISO 8601 স্ট্রিং হিসেবে স্পষ্ট অফসেট সহ (পছন্দসইভাবে Z)। যদি আপনাকে সংখ্যাস্বরূপ এপক পাঠাতে হয়, ইউনিট ডকুমেন্ট করুন এবং ধারাবাহিক রাখুন (JS-এ মিলিসেকেন্ড কমন)।
মানুষের জন্য ফরম্যাটিং-এ Intl.DateTimeFormat (বা toLocaleString) ব্যবহার করুন, এবং যখন নির্ধারিত আউটপুট দরকার তখন স্পষ্ট timeZone পাঠান (উদাহরণ: সবসময় UTC দেখানো বা নির্দিষ্ট ব্যবসায়িক অঞ্চল)।
Z সহ ISO 8601 পছন্দ করুন (যেমন '2025-12-23T10:15:00Z')। যদি এপক ব্যবহার করেন, ফিল্ডের নাম যেমন createdAtMs ব্যবহার করে ইউনিট স্পষ্ট করুন।যদি আপনি recurring events, জটিল টাইমজোন নিয়ম, DST-সেইফ আরিথমেটিক ('আগামীকাল একই লোকাল টাইম'), অথবা অসঙ্গত ইনপুট থেকে অনেক পার্সিং দরকার—তখন একটি ডেডিকেটেড ডেট-টাইম লাইব্রেরি বিবেচনা করুন। মূল ভ্যালু হলো পরিষ্কার API এবং কম এজ-কেস বাগ।
আরও জানতে চাইলে /blog দেখুন। টুলিং বা সাপোর্ট অপশন মূল্যায়ন করছেন? দেখুন /pricing।