JavaScript-এ একটি বিল্ট-ইন অবজেক্ট Date আছে, যা তারিখ ও সময় সংরক্ষণ করে এবং সেগুলো পরিচালনার জন্য মেথড দেয়।
এটি Java-এর java.util.Date ক্লাসের ওপর ভিত্তি করে তৈরি হয়েছিল; ২০১০-এর দশকের গোড়ার দিকে এটিকে প্রতিস্থাপন করা হয়েছিল, তবে ব্যাকওয়ার্ড কম্প্যাটিবিলিটির জন্য JavaScript-এর Date এখনও টিকে রয়েছে।
সাধারণভাবে Date নিয়ে কাজ করা কতটা কঠিন, আর টাইমজোন হ্যান্ডলিং কতটা দুর্বল বা একেবারে অনুপস্থিত, তার কারণে moment.js, day.js, date-fns আর luxon-এর মতো অনেক লাইব্রেরি গড়ে উঠেছে।
এগুলোর কোনোটিই Exercism-এ পাওয়া যায় না।
আপনার নিজের প্রজেক্টে moment.js-এর মতো ডেপ্রিকেটেড বা আর মেইনটেইন করা হয় না এমন প্যাকেজ ব্যবহার করবেন না; বরং luxon-এর মতো আরও আধুনিক বিকল্প, কিংবা এখনও ব্যাপকভাবে পাওয়া যায় না এমন Temporal-এর ওপর নির্ভর করুন।
এই অনুশীলনীটিতে মূলত Date নিয়ে আলোচনা করা হয়েছে, যা JavaScript-এর শেষ দিন পর্যন্ত প্রাসঙ্গিক থাকবে।
একটি Date অবজেক্ট হলো Date ক্লাসের একটি ইনস্ট্যান্স।
কনস্ট্রাক্টর ফাংশনে কোনো আর্গুমেন্ট না দিয়েও এটি তৈরি করা যায়।
এতে বর্তমান তারিখ ও সময় নির্দেশ করে এমন একটি Date অবজেক্ট পাওয়া যায়:
const now = new Date();
// => Thu Apr 14 2022 11:46:08 GMT+0530 (India Standard Time)
// Shows current day, date and time (in your time zone).
যদি কোনো সংখ্যা পাস করা হয়, তাহলে সেটিকে একটি timestamp হিসেবে ধরা হয়।
একটি টাইমস্ট্যাম্প হলো একটি ইন্টিজার সংখ্যা, যা ১৯৭০ সালের ১ জানুয়ারি UTC+0 থেকে যত মিলিসেকেন্ড পেরিয়ে গেছে, সেই সংখ্যা বোঝায়।
const epoch = new Date(0);
// Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)
const another = new Date(1749508766627);
// Tue Jun 10 2025 00:39:26 GMT+0200 (Central European Summer Time)
কেউ হয়তো আশা করতে পারেন new Date(0) "সবচেয়ে আগের" তারিখের অবজেক্ট তৈরি করবে, কিন্তু JavaScript তারিখটিকে আপনার স্থানীয় টাইমজোনে রূপান্তর করে; তাই কেবল GMT / UTC+0 টাইমজোনের আশপাশে থাকা মানুষরাই আসলে ইউনিক্স এপক মানটি পান।
আপনি তারিখ নির্দেশ করে এমন একটি স্ট্রিং মান Date কনস্ট্রাক্টরে পাস করতে পারেন।
সব ইমপ্লিমেন্টেশনে একইভাবে কাজ করে এমন একমাত্র ফরম্যাট হলো আন্তর্জাতিকভাবে স্বীকৃত ও প্রমিত তথাকথিত ISO 8601 টাইমস্ট্যাম্প স্ট্রিং-এর সরলীকৃত রূপ।
UTC-এ সময়ের একটি মুহূর্ত দেখতে এমন হয়:
YYYY-MM-DDTHH:mm:ss.mssZ
YYYYMMDDTHHmmss.mssZ
যেখানে নিচের প্রতিস্থাপনগুলো ঘটে:
| কী | বিবরণ | ডিফল্ট |
|---|---|---|
| YYYY | ক্যালেন্ডার বছর, ৪ সংখ্যায় প্রকাশিত | |
| MM | ক্যালেন্ডার মাস, ২ সংখ্যায় প্রকাশিত | 01 |
| DD | ক্যালেন্ডার দিন, ২ সংখ্যায় প্রকাশিত | 01 |
| T | আক্ষরিক T অক্ষর, যা তারিখকে সময় থেকে আলাদা করে | |
| HH | ২৪-ঘণ্টার ঘড়িতে ঘণ্টা, ২ সংখ্যায় | 00 |
| mm | মিনিট, ২ সংখ্যায় | 00 |
| ss | সেকেন্ড, ২ সংখ্যায় | 00 |
| mss | মিলিসেকেন্ড, ৩ সংখ্যায় | 000 |
| Z | আক্ষরিক Z অক্ষর, অথবা একটি অফসেট +/-HH:mm
|
আক্ষরিক Z অক্ষরটি UTC বোঝায় (কোনো টাইমজোন নেই, ডে লাইট সেভিংসও নেই)।
যেহেতু বেশিরভাগ কম্পোনেন্টেরই ডিফল্ট মান আছে, তাই শেষের দিকের অংশগুলো বাদ দিয়েও লেখা বৈধ:
YYYY-MM-DD
ডিফল্ট হিসেবে সময় ধরা হয় 00:00:00.000।
যদি টাইমস্ট্যাম্পটি Z দিয়ে শেষ না হয়, আর +HH:mm বা -HH:mm (অর্থাৎ টাইমজোন অফসেট) দিয়েও শেষ না হয়, তাহলে ঐতিহাসিক কারণবশত নিচের নিয়মটি প্রযোজ্য হয়:
যখন টাইমজোন অফসেট অনুপস্থিত থাকে, তখন শুধু তারিখের ফরমগুলো UTC সময় হিসেবে ব্যাখ্যা করা হয় আর তারিখ-সময়ের ফরমগুলো স্থানীয় সময় হিসেবে ব্যাখ্যা করা হয়। UTC সময় হিসেবে ব্যাখ্যা করার কারণ হলো স্পেসিফিকেশনে থাকা একটি ঐতিহাসিক এরর, যা ISO 8601-এর সঙ্গে সঙ্গতিপূর্ণ ছিল না, কিন্তু ওয়েব কম্প্যাটিবিলিটির জন্য বদলানো যায়নি। দেখুন ভাঙা পার্সার – ওয়েব বাস্তবতার একটি সমস্যা।
Date.parse যেসব অন্য ফরম্যাট গ্রহণ করে, সেগুলো কাজ করতে পারে, আবার নাও পারে।
JavaScript-এ Date নিয়ে কাজ করার সময় একটি string থেকে Date-এ রূপান্তর করতে সবসময় একটি ISO 8601 টাইমস্ট্যাম্প ব্যবহার করুন।
শুধু তারিখের ফরম অনুমোদিত, তবে সব ISO 8601 ফরম্যাট সমর্থিত নয়। MDN-এর সরলীকৃত রূপের ব্যাখ্যা পৃষ্ঠাটি দেখুন।
আগে থেকে থাকা একটি Date অবজেক্টও কনস্ট্রাক্টরের আর্গুমেন্ট হিসেবে ব্যবহার করা যায়।
এতে একই তারিখ ও সময় নিয়ে বিদ্যমান Date অবজেক্টের একটি কপি তৈরি হয়।
const t1 = new Date();
const t2 = new Date(t1);
// Values of t1 and t2 will be the same.
তিনটি সংখ্যা পাস করলে শুধু তারিখ বোঝানো Date তৈরি করা যায়। ছয়টি সংখ্যা পাস করলে তারিখ ও সময় বোঝানো Date তৈরি করা যায়।
const date1 = new Date(95, 11, 17);
// Creates Date for Dec 17 1995 00:00 if your local timezone is equivalent to UTC.
const date2 = new Date(2013, 12, 5, 13, 24, 0);
// Creates Date for Jan 5 2014 13:24 if your local timezone is equivalent to UTC.
দ্বিতীয় মানটি হলো month, যা জানুয়ারিতে 0 থেকে শুরু হয়ে ডিসেম্বরে 11 পর্যন্ত যায়।
Date.parse()আপনি হয়তো Date.parse নামের একটি তারিখ পার্সিং ফাংশনের উল্লেখ বা রেফারেন্স দেখতে পারেন।
যেহেতু এই ফাংশনের জন্য মাত্র কয়েকটি ইনভেরিয়েন্ট (সত্য) আছে, আর বাকি ইমপ্লিমেন্টেশন নির্দিষ্ট করা নেই (তাই স্ট্যান্ডার্ডও নয়), এটি ব্যবহার করা উচিত নয়।
Date-এর কম্পোনেন্টগুলো অ্যাক্সেস করাডেট অবজেক্টে এমন অনেক মেথড আছে যেগুলো তারিখের কম্পোনেন্টগুলো রিটার্ন করে:
getFullYear(); // Get the year (4 digits)
getMonth(); // Get the month, from 0 to 11.
getDate(); // Get the day of month, from 1 to 31.
getHours(); // Get the hour in a 24 clock, from 0 to 23
getMinutes(); // Get the minutes, from 0 to 59
getSeconds(); // Get the seconds, from 0 to 59
getMilliseconds(); // Get the milliseconds, from 0 and 999
getDay(); // Get the day of week, from 0 (Sunday) to 6 (Saturday).
এগুলোর প্রতিটিরই মান হালনাগাদ করার জন্য একটি সংশ্লিষ্ট set ভ্যারিয়েন্ট আছে (যেমন setFullYear)।
সীমা ছাড়ানো যেকোনো মান পরের কম্পোনেন্টে গিয়ে রোল ওভার হয়:
const date = new Date('2025-02-28T12:42:00Z');
// => Fri Feb 28 2025 13:42:00 GMT+0100 (Central European Standard Time)
date.setDate(29);
// there was no February 29th in 2025.
date.getDate();
// => 1
date.toString();
// => Sat Mar 01 2025 13:42:00 GMT+0100 (Central European Standard Time)
যেসব মেথড স্থানীয় টাইমজোন উপেক্ষা করে, সেগুলোর সবার জন্যই UTC ভ্যারিয়েন্ট আছে।
ডেট অবজেক্টে getTime() নামের একটি মেথড আছে, যা ইউনিক্স টাইমস্ট্যাম্প মিলিসেকেন্ডে রিটার্ন করে, অর্থাৎ ১৯৭০ সালের ১ জানুয়ারির গোড়ায় UTC-তে মধ্যরাত থেকে যত মিলিসেকেন্ড পেরিয়ে গেছে তার সংখ্যা।
এছাড়া একটি ডেট অবজেক্ট থেকে ISO 8601 টাইমস্ট্যাম্প স্ট্রিংয়ে রূপান্তর করার জন্য toISOString() মেথডটি আছে।
বড় (>) ও বড় বা সমান (>=), আর ছোট (<) ও ছোট বা সমান (<=) অপারেটর দুটি তারিখের মধ্যে বা একটি তারিখ ও একটি সংখ্যার মধ্যে সরাসরি ব্যবহার করা যায়।
এটি কাজ করে কারণ JavaScript তারিখটিকে একটি প্রিমিটিভে রূপান্তর করার চেষ্টা করে।
দুটি তারিখের মধ্যে বা একটি তারিখ ও একটি সংখ্যার মধ্যে তুলনা করার সময় JavaScript [Symbol.toPrimitive]("number") কল করে, যা ভেতরে ভেতরে date.valueOf() কল করে।
পরেরটি date.getTime() কল করার সমান।
আপনি যদি এই আচরণের ওপর নির্ভর করতে না চান, তাহলে আগে getTime() দিয়ে সংখ্যায় রূপান্তর করে নিন।
তারিখকে সমতা চিহ্ন (== এবং ===) দিয়ে তুলনা করা যায় না, তবে .getTime()-এর ফলাফলকে দিয়ে তা করা যায়।
এই অনুশীলনীতে আপনি অ্যাপয়েন্টমেন্ট পরিচালনার জন্য কিছু ফাংশন নিয়ে কাজ করবেন। সিস্টেমটি সবকিছু ISO 8601 ফরম্যাটের স্ট্রিং-এ সংরক্ষণ করে, কিন্তু মানুষ ক্যালেন্ডার এভাবে ব্যবহার করে না। বিভিন্ন ফরম্যাটের মধ্যে রূপান্তরের জন্য নানা ফাংশন প্রয়োজন।
এখন থেকে n দিন পরে বর্তমান সময়ে একটি অ্যাপয়েন্টমেন্ট তৈরি করুন।
ফাংশনটি n দিন নেয় এবং এখন থেকে n দিন পরের অ্যাপয়েন্টমেন্টের সময় রিটার্ন করে।
createAppointment(4, now);
// Given now is Sun Oct 05 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)
// => Sun Oct 09 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)
যদি দ্বিতীয় প্যারামিটার now ব্যবহার না করা হয়, তবে তার বদলে বর্তমান সময় ব্যবহার করা উচিত।
বিভিন্ন টুল কেবল আন্তর্জাতিকভাবে মানসম্মত ISO 8601 ফরম্যাটেই কাজ করে।
একটি তারিখ নিয়ে সেই ফরম্যাটে একটি স্ট্রিং রিটার্ন করার জন্য getAppointmentTimestamp ফাংশনটি লিখুন।
const appointment = new Date(Date.UTC(2010, 6, 16, 12, 42, 0, 0));
getAppointmentTimestamp(appointment);
// => '2010-07-16T12:42:00.000Z'
টাইমস্ট্যাম্প পড়া কঠিন; অ্যাপয়েন্টমেন্টের বিবরণ পাওয়ার একটি ফাংশন এতে সাহায্য করবে।
getAppointmentDetails ফাংশনটি ISO 8601 ফরম্যাটের একটি টাইমস্ট্যাম্প নেয় এবং বছর, মাস, তারিখ, ঘণ্টা আর মিনিট রিটার্ন করে।
getAppointmentDetails('2022-04-24T08:15:00.000');
// => { year: 2022, month: 3, date: 24, hour: 8, minute: 15 }
ফাংশনটি প্রথম আর্গুমেন্ট হিসেবে অ্যাপয়েন্টমেন্টের সময় এবং দ্বিতীয় আর্গুমেন্ট হিসেবে কিছু অপশনের অবজেক্ট পাবে। অবজেক্টের অপশন অনুযায়ী আপনাকে অ্যাপয়েন্টমেন্টটি আপডেট করতে হবে এবং নতুন অ্যাপয়েন্টমেন্টের তারিখ রিটার্ন করতে হবে। অপশন অবজেক্টে একাধিক অপশন থাকতে পারে।
updateAppointment('2022-02-09T09:20:00.000', { month: 6 });
// => { year: 2022, month: 6, date: 9, hour: 10, minute: 20 }
ফাংশনটি আর্গুমেন্ট হিসেবে দুটি অ্যাপয়েন্টমেন্ট (টাইমস্ট্যাম্প) পাবে। আপনাকে ওই দুই সময়ের পার্থক্য সেকেন্ডে রিটার্ন করতে হবে।
আধা সেকেন্ডের প্রায় কোনো অর্থই নেই, তাই রিটার্ন করার আগে সংখ্যাটি রাউন্ড করে নিন।
timeBetween('2022-12-12T09:20:00.000', '2022-12-18T08:30:00.000');
// => 515400
সবশেষে, অ্যাপয়েন্টমেন্ট তৈরি হওয়ার সময় সিস্টেমকে যাচাই করতে হয় এটি বৈধ কি না। অর্থাৎ, অ্যাপয়েন্টমেন্টটি অবশ্যই ভবিষ্যতে হতে হবে, অতীতে নয়।
isValid ফাংশনটি লিখুন, যা দুটি আর্গুমেন্ট নেয়: একটি অ্যাপয়েন্টমেন্ট টাইমস্ট্যাম্প (স্ট্রিং), আর বর্তমান সময় একটি টাইমস্ট্যাম্প (স্ট্রিং) হিসেবে। বর্তমান সময়ের সাপেক্ষে অ্যাপয়েন্টমেন্টটি ভবিষ্যতে থাকলে এটি true রিটার্ন করে।
isValid('2022-02-11T23:00:00.000', '2022-02-08T23:00:00.000');
// => true
Exercism-এ সাইন আপ করুন, JavaScript ট্র্যাকের 37টি কনসেপ্ট159টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।