LocalDate-এর মতো java.time অবজেক্ট নিয়ে কাজ করার সময় প্রায়ই জটিল তারিখ সমন্বয় করতে হয়, যেমন "মাসের দ্বিতীয় মঙ্গলবার" খুঁজে বের করা।
এটি নিজ হাতে হিসাব না করে আপনি TemporalAdjusters ব্যবহার করতে পারেন।
java.time.temporal.TemporalAdjusters (শেষে 's' আছে, খেয়াল করুন) ইউটিলিটি ক্লাসটি অনেক কমন তারিখ সমন্বয়ের জন্য স্ট্যাটিক মেথড দেয়।
এই সমন্বয়গুলো আপনি একটি টেম্পোরাল অবজেক্টের (যেমন LocalDate) ওপর .with() মেথড দিয়ে প্রয়োগ করেন।
with(TemporalAdjuster) ব্যবহার করলে একটি নতুন ইনস্ট্যান্স রিটার্ন হয়, বিদ্যমান ইনস্ট্যান্সটি আপডেট হয় না, কারণ java.time অবজেক্টগুলো ইমিউটেবল।
import java.time.LocalDate;
import java.time.Month;
import java.time.DayOfWeek;
import java.time.temporal.TemporalAdjusters;
LocalDate date = LocalDate.of(2024, Month.AUGUST, 15); // 2024-08-15 (a Thursday)
// Use a predefined adjuster: find the last day of the month
LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
// => 2024-08-31
সময়সূচির হিসাবে কাজে লাগে এমন কয়েকটি গুরুত্বপূর্ণ অ্যাডজাস্টার এখানে দেখুন:
সপ্তাহের কোনো একটি বারের n-তম পুনরাবৃত্তি খুঁজতে dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek) ব্যবহার করুন।
// Find the second Tuesday of August 2024
LocalDate secondTuesday = date.with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY));
// => 2024-08-13
firstInMonth(DayOfWeek dayOfWeek) অথবা lastInMonth(DayOfWeek dayOfWeek) ব্যবহার করুন।
// Find the last Monday of August 2024
LocalDate lastMonday = date.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY));
// => 2024-08-26
next(), previous(), nextOrSame() আর previousOrSame()-এর মতো অ্যাডজাস্টার চলতি তারিখের সাপেক্ষে সপ্তাহের একটি নির্দিষ্ট বারের পরের বা আগের পুনরাবৃত্তি খুঁজে দেয়।
next()/previous(): চলতি তারিখটি মিলে গেলেও সেটি বাদ দেয়।nextOrSame()/previousOrSame(): চলতি তারিখটি মিলে গেলে সেটিকেও ধরে নেয়।LocalDate thursday = LocalDate.of(2024, Month.AUGUST, 15); // A Thursday
// Find the next Thursday (exclusive)
LocalDate nextThursday = thursday.with(TemporalAdjusters.next(DayOfWeek.THURSDAY));
// => 2024-08-22
// Find the next Thursday (inclusive) - returns the same date
LocalDate nextOrSameThursday = thursday.with(TemporalAdjusters.nextOrSame(DayOfWeek.THURSDAY));
// => 2024-08-15
// Find the previous Monday (exclusive)
LocalDate previousMonday = thursday.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
// => 2024-08-12
TemporalAdjuster একটি ফাংশনাল ইন্টারফেস, তাই আপনি ল্যাম্বডা দিয়ে নিজের অ্যাডজাস্টার লিখতে পারেন, যা সমন্বয় করার জন্য টেম্পোরালটি নেয় আর সমন্বয় করা টেম্পোরালটি রিটার্ন করে।
এটি আগে থেকে দেওয়া অ্যাডজাস্টারগুলোর মতোই .with() দিয়ে প্রয়োগ করা হয়, আর ভেতরে ওগুলোও ব্যবহার করতে পারে।
import java.time.temporal.TemporalAdjuster;
// An adjuster that moves a weekend date to the following Monday
TemporalAdjuster skipWeekend = temporal -> {
DayOfWeek day = DayOfWeek.from(temporal);
if (day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY) {
return temporal.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
}
return temporal;
};
LocalDate saturday = LocalDate.of(2024, Month.AUGUST, 17);
LocalDate monday = saturday.with(skipWeekend);
// => 2024-08-19
TemporalAdjusters ক্লাসের এই অ্যাডজাস্টারগুলো ব্যবহার করলে তারিখ নিয়ে কাজ অনেক সহজ হয়ে যায়।
নিউ ইয়র্কের যে বিউটি সেলুনটিতে আপনি Booking Up For Beauty অনুশীলনীতে সাহায্য করেছিলেন, তার ব্যবসা ভালোই চলছে, আর এর অনেক গ্রাহক এখন নিয়মিত হয়ে গেছেন। প্রতিটি ভিজিট আলাদা করে বুক না করে, নিয়মিত গ্রাহকদের জন্য থাকে একটি স্থায়ী ব্যবস্থা: "প্রতি দ্বিতীয় মঙ্গলবার", "মাসের শেষ শুক্রবার" ইত্যাদি। মালিক আপনাকে একটি সহায়ক মেথড বানাতে বলেছেন, যা এই ব্যবস্থাগুলোর পিছনের তারিখগুলো এবং সাথে সেলুনের নিজস্ব মাসিক রুটিনের তারিখও বের করে দেবে।
SalonCalendar.standingAppointment() মেথডটি ইমপ্লিমেন্ট করুন, যা একটি বছর, একটি মাস, একটি পুনরাবৃত্তি-সংখ্যা (প্রথমটির জন্য 1, দ্বিতীয়টির জন্য 2, এভাবে) এবং সপ্তাহের একটি বার নেয়। এটি ওই মাসের মধ্যে সপ্তাহের ওই বারের ওই পুনরাবৃত্তিটি যে তারিখে পড়ে, সেই তারিখ রিটার্ন করে:
SalonCalendar calendar = new SalonCalendar();
calendar.standingAppointment(2024, Month.AUGUST, 2, DayOfWeek.TUESDAY);
// => LocalDate.of(2024, 8, 13)
কিছু নিয়মিত গ্রাহক মাসের ভেতরে তাঁদের বারের শেষ পুনরাবৃত্তিটি পছন্দ করেন। SalonCalendar.lastAppointment() মেথডটি ইমপ্লিমেন্ট করুন, যা একটি বছর, একটি মাস ও সপ্তাহের একটি বার নেয় এবং ওই মাসের মধ্যে সপ্তাহের ওই বারের শেষ পুনরাবৃত্তিটি যে তারিখে পড়ে, সেই তারিখ রিটার্ন করে:
SalonCalendar calendar = new SalonCalendar();
calendar.lastAppointment(2024, Month.AUGUST, DayOfWeek.FRIDAY);
// => LocalDate.of(2024, 8, 30)
রিসেপশনে একজন ক্লায়েন্ট জিজ্ঞেস করেন "পরের শনিবার"। তিনি যেদিন জিজ্ঞেস করছেন সেদিনই যদি শনিবার হয়, তাহলে তিনি সেই দিনটাই বোঝাচ্ছেন। SalonCalendar.nextAvailable() মেথডটি ইমপ্লিমেন্ট করুন, যা একটি তারিখ ও সপ্তাহের একটি বার নেয়, আর দেওয়া তারিখটি বা তার পরের যে প্রথম তারিখটি ওই বারে পড়ে, সেটি রিটার্ন করে:
SalonCalendar calendar = new SalonCalendar();
calendar.nextAvailable(LocalDate.of(2024, 8, 15), DayOfWeek.SATURDAY);
// => LocalDate.of(2024, 8, 17)
calendar.nextAvailable(LocalDate.of(2024, 8, 17), DayOfWeek.SATURDAY);
// => LocalDate.of(2024, 8, 17)
সেলুন প্রতি মাসের শেষ দিনে তার হিসাবের খাতা বন্ধ করে। তবে সপ্তাহান্তে সেলুন বন্ধ থাকে, তাই মাসের শেষ দিনটি যদি শনিবার বা রবিবারে পড়ে, তাহলে তার আগের শুক্রবারেই খাতা বন্ধ করা হয়। SalonCalendar.bookkeepingDay() মেথডটি ইমপ্লিমেন্ট করুন, যা একটি বছর ও একটি মাস নেয় এবং ওই মাসের হিসাবরক্ষণের দিনটি রিটার্ন করে:
SalonCalendar calendar = new SalonCalendar();
calendar.bookkeepingDay(2024, Month.SEPTEMBER);
// => LocalDate.of(2024, 9, 30)
calendar.bookkeepingDay(2024, Month.AUGUST);
// => LocalDate.of(2024, 8, 30)
কর্মীদের প্রতি মাসের ১৫ তারিখে বেতন দেওয়া হয়, একই সপ্তাহান্তের নিয়মে: ১৫ তারিখটি যদি শনিবার বা রবিবারে পড়ে, তাহলে বেতন দেওয়া হয় তার আগের শুক্রবারে। নিয়মটি আরেকবার না লিখে এটিকে পুনরায় ব্যবহারযোগ্য অ্যাডজাস্টারে পরিণত করুন।
SalonCalendar.precedingWorkday() মেথডটি ইমপ্লিমেন্ট করুন, যা একটি TemporalAdjuster রিটার্ন করে; এটি কোনো কর্মদিবস অপরিবর্তিত রাখে আর শনিবার বা রবিবারকে পিছিয়ে আগের শুক্রবারে নিয়ে যায়। এরপর ওই অ্যাডজাস্টার ব্যবহার করে SalonCalendar.payday() মেথডটি ইমপ্লিমেন্ট করুন, যা একটি বছর ও একটি মাস নেয়:
SalonCalendar calendar = new SalonCalendar();
LocalDate.of(2024, 6, 15).with(calendar.precedingWorkday());
// => LocalDate.of(2024, 6, 14)
calendar.payday(2024, Month.JUNE);
// => LocalDate.of(2024, 6, 14)
calendar.payday(2024, Month.AUGUST);
// => LocalDate.of(2024, 8, 15)
চাইলে আপনি ফিরে গিয়ে bookkeepingDay()-তেও অ্যাডজাস্টারটি ব্যবহার করতে পারেন।
Exercism-এ সাইন আপ করুন, Java ট্র্যাকের 27টি কনসেপ্ট159টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।