مقایسه تاریخ در جاوا — راهنمای جامع
در این راهنما به بررسی شیوه مقایسه تاریخ در جاوا با استفاده از Date/Time API در جاوا 8 میپردازیم در ادامه روشهای مختلف بررسی برابر بودن دو تاریخ و شیوه مقایسه تاریخها را معرفی میکنیم.
مقایسه تاریخ
روش مقدماتی برای بیان تاریخ در جاوا به صورت LocalDate است. در ادامه وهلههای شیء LocalDate را که نماینده 10 آگوست 2019 و اول جولای 2019 است، بررسی میکنیم:
1LocalDate firstDate = LocalDate.of(2019, 8, 10);
2LocalDate secondDate = LocalDate.of(2019, 7, 1);
در ادامه قصد داریم دو شیء LocalDate را با استفاده از ()isAfter() ،isBefore و ()isEqual و همچنین ()equals و ()compareTo مقایسه کنیم. از متد ()isAfter برای بررسی این که آیا وهله تاریخ پس از تاریخ خاصی است یا نه استفاده میکنیم. بدین ترتیب JUnit assertion بعدی پاس میشود:
1assertThat(firstDate.isAfter(secondDate), is(true));
به طور مشابه متد ()isBefore بررسی میکند آیا یک وهله از تاریخ پس از تاریخ خاصی است یا نه:
1assertThat(firstDate.isBefore(secondDate), is(false));
متد ()isEqual بررسی میکند آیا یک تاریخ که در تایملاین محلی بیانشده است با تاریخ خاصی برابر است یا نه:
1assertThat(firstDate.isEqual(firstDate), is(true));
2assertThat(firstDate.isEqual(secondDate), is(false));
مقایسه تاریخها با اینترفیس Comparable
متد ()equals همان نتیجه ()isEqual را به دست میدهد، اما تنها در صورتی که آرگومان ارسالی از همان نوع (در این مورد به صورت LocalDate) باشد:
1assertThat(firstDate.equals(secondDate), is(false));
اما از سوی دیگر متد ()isEqual میتواند برای مقایسه دو شیء از نوع متفاوت مانند JapaneseDate ،ThaiBuddhistDate و غیره استفاده شود. میتوانیم دو وهله از تاریخ را با استفاده از متد ()compareTo چنان که در اینترفیس Comparable تعریف شدهاند مقایسه کنیم:
1assertThat(firstDate.compareTo(secondDate), is(1));
2assertThat(secondDate.compareTo(firstDate), is(-1));
مقایسه وهلههای تاریخ شامل مؤلفه Time
در این بخش شیوه مقایسه دو وهله از LocalDateTime را توضیح میدهیم. وهلههای LocalDateTime شامل تاریخ و همچنین مؤلفه Time هستند. همانند LocalDate در مورد LocalDateTime نیز میتوانیم وهلههای مختلف را با استفاده از متدهای ()isAfter() و isBefore و ()isEqual مقایسه کنیم. به علاوه ()equals و ()compareTo میتوانند به روشی مشابه چنان که در مورد LocalDate توضیح دادیم استفاده شوند.
به طور مشابه میتوانیم از همان متدها برای مقایسه وهلههای ZonedDateTime استفاده کنیم. برای نمونه فرض کنید میخواهیم زمان محلی 8:00 را در نیویورک با زمان محلی 14:00 در برلین در روز یکسان مقایسه کنیم:
1ZonedDateTime timeInNewYork =
2 ZonedDateTime.of(2019, 8, 10, 8, 0, 0, 0, ZoneId.of("America/New_York"));
3ZonedDateTime timeInBerlin =
4 ZonedDateTime.of(2019, 8, 10, 14, 0, 0, 0, ZoneId.of("Europe/Berlin"));
5
6assertThat(timeInNewYork.isAfter(timeInBerlin), is(false));
7assertThat(timeInNewYork.isBefore(timeInBerlin), is(false));
8assertThat(timeInNewYork.isEqual(timeInBerlin), is(true));
گرچه هر دو وهله ZonedDateTime نماینده لحظه واحدی از زمان هستند، اما اشیای جاوای برابری را نمایندگی نمیکنند. آنها در درون خود فیلدهای LocalDateTime و ZoneId متفاوتی دارند:
1assertThat(timeInNewYork.equals(timeInBerlin), is(false));
2assertThat(timeInNewYork.compareTo(timeInBerlin), is(-1));
مقایسههای دیگر
در این بخش یک کلاس کاربردی ساده میسازیم که برای مقایسههای کمی پیچیدهتر استفاده میشود. ابتدا بررسی میکند آیا وهلههای LocalDateTime و LocalDate در روز واحدی هستند یا نه:
1public static boolean isSameDay(LocalDateTime timestamp,
2 LocalDate localDateToCompare) {
3 return timestamp.toLocalDate().isEqual(localDateToCompare);
4}
سپس بررسی میکند آیا دو وهله از LocalDateTime در روز واحدی هستند یا نه:
1public static boolean isSameDay(LocalDateTime timestamp,
2 LocalDateTime timestampToCompare) {
3 return timestamp.truncatedTo(DAYS)
4 .isEqual(timestampToCompare.truncatedTo(DAYS));
5}
متد truncatedTo(TemporalUnit) یک تاریخ را روی سطح مفروض خلاصه میکند که در این مثال سطح روز مورد نظر است. در ادامه میتوانیم مقایسه را در سطح ساعت نیز پیادهسازی کنیم:
1public static boolean isSameHour(LocalDateTime timestamp,
2 LocalDateTime timestampToCompare) {
3 return timestamp.truncatedTo(HOURS)
4 .isEqual(timestampToCompare.truncatedTo(HOURS));
5}
در نهایت به روشی مشابه میتوانیم بررسی کنیم آیا دو وهله از ZonedDateTime در ساعت یکسانی رخ میدهند یا نه:
1public static boolean isSameHour(ZonedDateTime zonedTimestamp,
2 ZonedDateTime zonedTimestampToCompare) {
3 return zonedTimestamp.truncatedTo(HOURS)
4 .isEqual(zonedTimestampToCompare.truncatedTo(HOURS));
5}
میبینیم که دو شیء ZonedDateTime در عمل درون ساعت واحدی قرار میگیرند، هر چند ساعتهای محلی متفاوت هستند:
1ZonedDateTime zonedTimestamp =
2 ZonedDateTime.of(2019, 8, 10, 8, 30, 0, 0, ZoneId.of("America/New_York"));
3ZonedDateTime zonedTimestampToCompare =
4 ZonedDateTime.of(2019, 8, 10, 14, 0, 0, 0, ZoneId.of("Europe/Berlin"));
5
6assertThat(DateTimeComparisonUtils.
7 isSameHour(zonedTimestamp, zonedTimestampToCompare), is(true));
مقایسه با API قدیمی Java Date
تا پیش از جاوا 8 مجبور بودیم از کلاسهای java.util.Date و java.util.Calendar برای دستکاری اطلاعات تاریخ/زمان استفاده کنیم. طراحی API قدیمی java.util.Date و java.util.Calendar معایب زیادی داشت مثلاً پیچیده بود و thread-safe نبود. وهله java.util.Date نماینده یک لحظه در زمان است و نه تاریخ واقعی.
در آن زمان یکی از راهحلها استفاده از کتابخانه Joda Time بود. از زمان انتشار نسخه 8 جاوا توصیه شده که از API این نسخه به نام Date/Time استفاده کنیم. اشیای java.util.Date و java.util.Calendar مشابه LocalDate و LocalDateTime دارای متدهای after() ،before() ،compareTo و ()equals برای مقایسه دو وهله از تاریخ هستند. تاریخها به صورت وهلههای از زمان و در سطح میکروثانیه مقایسه میشوند:
1Date firstDate = toDate(LocalDateTime.of(2019, 8, 10, 0, 00, 00));
2Date secondDate = toDate(LocalDateTime.of(2019, 8, 15, 0, 00, 00));
3
4assertThat(firstDate.after(secondDate), is(false));
5assertThat(firstDate.before(secondDate), is(true));
6assertThat(firstDate.compareTo(secondDate), is(-1));
7assertThat(firstDate.equals(secondDate), is(false));
در مورد مقایسههای پیچیدهتر، میتوانیم از DateUtils از کتابخانه Apache Commons Lang استفاده کنیم. این کلاس شامل متدهای کارآمد زیادی برای کار کردن با اشیای Date و Calendar است:
1public static boolean isSameDay(Date date, Date dateToCompare) {
2 return DateUtils.isSameDay(date, dateToCompare);
3}
4
5public static boolean isSameHour(Date date, Date dateToCompare) {
6 return DateUtils.truncatedEquals(date, dateToCompare, Calendar.HOUR);
7}
برای مقایسه اشیای تاریخ که از API-های مختلفی نشأت میگیرند، باید ابتدا آنها را به نوع مناسب تبدیل کنیم و سپس میتوانیم مقایسه را اجرا کنیم.
سخن پایانی
در این مقاله به بررسی روشهای مختلف برای مقایسه وهلههای تاریخ در جاوا پرداختیم. کلاسهای Date/Time در جاوا 8 API-های قدرتمندی برای مقایسه تاریخها با یا بدون زمان و مناطق زمانی دارند. همچنین با روش مقایسه تاریخها در سطوح روز، ساعت، دقیقه و غیره آشنا شدیم. همه کدهای معرفی شده در این ریپوی گیتهاب (+) در دسترس شما قرار دارند.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی جاوا (Java)
- مجموعه آموزشهای برنامهنویسی
- گنجینه آموزشهای جاوا (Java)
- زبان برنامه نویسی جاوا (Java) — از صفر تا صد
- ۱۰ مفهوم اصلی زبان جاوا که هر فرد مبتدی باید بداند
==