سلام! امروز کار را با نوع داده جدیدی که قبلاً با آن مواجه نشده بودیم، یعنی تاریخ ها، شروع می کنیم.
فکر نمی کنم نیازی به توضیح تاریخ باشد. :) در اصل، ما می توانیم تاریخ و زمان فعلی را در یک رشته جاوا معمولی ذخیره کنیم.
این بدان معنا نیست که اصلاً نمی توان از این روش ها استفاده کرد. اگر بخواهید کد را با استفاده از روش های منسوخ شده در یک IDE اجرا کنید، به احتمال زیاد کار خواهد کرد. برای مثال، متد منسوخ شده را در نظر بگیرید
اکثر
تاریخ فقط چند عدد است که یک فاصله زمانی خاص را نشان می دهد. تقویم یک سیستم کامل است که به شما امکان می دهد کارهای زیادی را با تاریخ انجام دهید. :) اگر بخواهید
![چگونه در زمان گم نشویم: DateTime و Calendar - 1](https://cdn.codegym.cc/images/article/000a112a-6c34-4b71-aced-66a6687b1b4d/800.jpeg)
public class Main {
public static void main(String[] args) {
String date = "June 11, 2018";
System.out.println(date);
}
}
اما این رویکرد دارای معایب بسیاری است. کلاس String
برای کار با متن طراحی شده است و روش های آن برای این کار مناسب است. اگر لازم باشد تاریخ را به نحوی دستکاری کنیم (مثلاً 2 ساعت اضافه کنیم)، String
به خوبی کار نمی کند. یا اگر بخواهیم تاریخ و ساعت فعلی هنگام کامپایل شدن برنامه نمایش داده شود. String
در اینجا هم کمکی نمی کند: زمانی که کد را بنویسید و آن را اجرا کنید، زمان تغییر کرده و کنسول اطلاعات اشتباهی را نمایش می دهد. به همین دلیل سازندگان جاوا چندین کلاس برای کار با تاریخ و زمان ارائه کردند. اولین مورد این استjava.util.Date
کلاس تاریخ
ما نام کامل آن را مشخص کردیم، زیرا بسته جاوا دیگری دارایjava.sql.Date
کلاس است. آنها را با هم قاطی نکنید! اولین چیزی که باید در مورد آن بدانید این است که تاریخ را به عنوان تعداد میلی ثانیه هایی که از اول ژانویه 1970 گذشته است ذخیره می کند . موافق نیستی؟ :) دومین چیزی که ارزش یادآوری دارد این است: اگر یک شی را با استفاده از سازنده پیش فرض ایجاد کنید ، نتیجه تاریخ و زمان فعلی را در لحظه ایجاد شیء نشان می دهد . به یاد داشته باشید که گفتیم تاریخی که به عنوان یک نشان داده می شود با چنین وظیفه ای دست و پنجه نرم می کند؟ کلاس به راحتی آن را اداره می کند. Date
String
Date
public class Main {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date);
}
}
این کد را چندین بار اجرا کنید و شاهد تغییر مکرر زمان خواهید بود. :) این امکان پذیر است زیرا زمان به صورت میلی ثانیه ذخیره می شود: آنها واحدهای بسیار کوچکی از زمان هستند، بنابراین نتایج بسیار دقیق هستند. کلاس Date
سازنده دیگر: میتوانید تعداد دقیق میلیثانیهها را از ساعت 00:00 در 1 ژانویه 1970 به تاریخ مورد نیاز منتقل کنید، و یک شی تاریخ مربوطه ایجاد میشود:
public class Main {
public static void main(String[] args) {
Date date = new Date(1212121212121L);
System.out.println(date);
}
}
خروجی کنسول: جمعه 30 می 04:20:12 به وقت گرینویچ 2008 ما 30 می 2008 را دریافت می کنیم. "جمعه" روز هفته را نشان می دهد (جمعه، دوشنبه)، و GMT منطقه زمانی (به وقت گرینویچ) است. میلیثانیهها بهعنوان s ارسال میشوند long
، زیرا تعداد میلیثانیهها معمولاً در یک عدد قرار نمیگیرد int
. بنابراین، چه عملیاتی با تاریخ ممکن است لازم باشد انجام دهیم؟ خوب، واضح ترین، البته، مقایسه است . برای تعیین اینکه آیا یک تاریخ قبل یا بعد از دیگری است. این را از راه های گوناگون می توان انجام داد. برای مثال، میتوانید Date.getTime()
روشی را فراخوانی کنید که تعداد میلیثانیههایی را که از نیمهشب ۱ ژانویه ۱۹۷۰ گذشته است را برمیگرداند.
public class Main {
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date();
System.out.println((date1.getTime() > date2.getTime())?
"date1 is later than date2" : "date1 is earlier than date2");
}
}
خروجی: date1 زودتر از date2 است ، اما راه راحتتری نیز وجود دارد، یعنی استفاده از روشهای ویژه ارائهشده توسط کلاس Date before()
:، after()
و equals()
. همه آنها یک مقدار بولی برمی گردانند. این before()
روش بررسی می کند که آیا تاریخ ما زودتر از تاریخی است که به عنوان آرگومان ارسال شده است:
public class Main {
public static void main(String[] args) throws InterruptedException {
Date date1 = new Date();
Thread.sleep(2000);// Suspend the program for 2 seconds
Date date2 = new Date();
System.out.println(date1.before(date2));
}
}
خروجی کنسول: true به طور مشابه، after()
متد بررسی می کند که آیا تاریخ ما دیرتر از تاریخ ارسال شده به عنوان آرگومان است یا خیر:
public class Main {
public static void main(String[] args) throws InterruptedException {
Date date1 = new Date();
Thread.sleep(2000);// Suspend the program for 2 seconds
Date date2 = new Date();
System.out.println(date1.after(date2));
}
}
خروجی کنسول: false در مثالهایمان، برنامه را به مدت 2 ثانیه به حالت Sleep قرار میدهیم تا دو تاریخ متفاوت باشند. در رایانههای سریع، زمان بین ایجاد date1
و date2
میتواند کمتر از یک میلیثانیه باشد، که باعث میشود هر دو before()
اشتباه after()
شوند. اما در این صورت equals()
روش true بر می گردد! به هر حال، تعداد میلی ثانیه ها از ساعت 00:00 در 1 ژانویه 1970 برای هر تاریخ مقایسه می شود. اشیاء فقط در صورتی برابر در نظر گرفته می شوند که با میلی ثانیه مطابقت داشته باشند :
public static void main(String[] args) {
Date date1 = new Date();
Date date2 = new Date();
System.out.println(date1.getTime());
System.out.println(date2.getTime());
System.out.println(date1.equals(date2));
}
در اینجا نکته دیگری است که باید به آن توجه کنید. اگر مستندات کلاس را Date
در وب سایت اوراکل
باز کنید ، خواهید دید که بسیاری از متدها و سازنده های آن به عنوان منسوخ شده علامت گذاری شده اند (یعنی برای استفاده توصیه نمی شود). در اینجا چیزی است که سازندگان جاوا در مورد بخش هایی از کلاس ها که منسوخ شده اند می گویند:
"یک عنصر برنامه با حاشیه نویسی @Deprecated چیزی است که برنامه نویسان استفاده از آن را توصیه نمی کنند، معمولاً به دلیل خطرناک بودن یا به دلیل وجود جایگزین بهتر." |
Date.getHours()
که تعداد ساعت های مرتبط با یک Date
شی را برمی گرداند.
public static void main(String[] args) {
Date date1 = new Date();
System.out.println(date1.getHours());
}
اگر کد را در ساعت 14:21 (2:21 بعد از ظهر) شروع کنید، عدد 14 را نمایش می دهد. همانطور که می بینید، روش منسوخ شده خط خورده است، اما همچنان کار می کند. این روش ها حذف نمی شوند تا حجم عظیمی از کدهای موجود که از آنها استفاده می کنند شکسته نشوند. به عبارت دیگر، این روش ها نه «شکسته» هستند و نه «حذف». آنها به سادگی برای استفاده توصیه نمی شوند زیرا جایگزین راحت تری در دسترس است. اتفاقاً، اسناد به طور خاص به این جایگزین اشاره می کند:
![چگونه در زمان گم نشویم: DateTime و Calendar - 2](https://cdn.codegym.cc/images/article/aeb33a9a-b45e-4d69-ba58-27c92e356f2c/256.jpeg)
Date
متدهای کلاس به کلاس بهبود یافته و توسعه یافته منتقل شده اند Calendar
. در ادامه با آن کلاس آشنا می شویم. :)
کلاس تقویم
JDK 1.1 کلاس جدیدی را معرفی کرد:Calendar
. کار با خرما در جاوا را تا حدودی آسانتر از قبل کرد. تنها پیاده سازی کلاسی Calendar
که با آن کار خواهیم کرد GregorianCalendar
کلاس است. تقویم میلادی را اجرا می کند که توسط اکثر کشورهای جهان رعایت می شود. مزیت اصلی آن این است که می تواند با تاریخ ها در قالب راحت تری کار کند. به عنوان مثال، می تواند:
- یک ماه یا یک روز به تاریخ فعلی اضافه کنید
- بررسی کنید که آیا سال یک سال کبیسه است یا خیر.
- اجزای جداگانه تاریخ را برگردانید (به عنوان مثال، شماره ماه را از یک تاریخ کامل استخراج کنید)
- همچنین شامل یک سیستم بسیار راحت از ثابت ها است (که بسیاری از آنها را در زیر خواهیم دید).
Calendar
آن است : میتوانید تاریخی را قبل از دوران مشترک (پیش از میلاد - قبل از میلاد مسیح) یا در دوره مشترک (AD - Anno Domini) نشان دهید. بیایید به همه اینها با مثال نگاه کنیم. بیایید یک شی با تاریخ 25 ژانویه 2017 ایجاد کنیم: calendar
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar(2017, 0 , 25);
}
در Calendar
کلاس (و همچنین Date
کلاس برای آن موضوع)، ماه ها از صفر شروع می شوند ، بنابراین عدد 0 را به عنوان آرگومان دوم پاس می کنیم. هنگام کار با Calendar
کلاس، درک این نکته مهم است که این فقط یک تقویم است ، نه یک تاریخ فردی. ![چگونه در زمان گم نشویم: DateTime و Calendar - 3](https://cdn.codegym.cc/images/article/4510db89-2412-468c-a52b-fb60b01f5b0a/800.jpeg)
Calendar
شیء را نمایش دهید این کاملاً آشکار است: خروجی: java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id= "Europe/London",offset=0,dstSavings=0,useDaylight=false,transitions=79,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=1,ERA=?,YEAR=2017,MONTH=0,YEEK_OF ,WEEK_OF_MONTH=?,DAY_OF_MONTH=25,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECONDZET=FFF=D,SECONDZET=FFF? ET =؟] ببینید چقدر اطلاعات به دست می آورید! یک تقویم دارای تعدادی ویژگی است که تاریخ معمولی ندارد و همه آنها نمایش داده می شوند (این روش toString()
در Calendar
کلاس کار می کند). اگر فقط نیاز دارید یک تاریخ ساده از تقویم، یعنی یک Date
شیء، بدست آورید، از روش استفاده کنید Calendar.getTime()
(نام منطقی ترین نیست، اما چه کاری می توانید انجام دهید؟):
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar(2017, 0 , 25);
Date date = calendar.getTime();
System.out.println(date);
}
خروجی: چهارشنبه 25 ژانویه 00:00:00 به وقت گرینویچ 2017 اکنون ما تقویم را انتخاب کرده و به یک تاریخ عادی "کاهش" داده ایم. بیایید جلوتر برویم. علاوه بر تعیین ماه ها با تعداد آنها، می توانید از مقادیر فیلد ثابتCalendar
کلاس استفاده کنید . این ثابت ها فیلدهای ثابت کلاس با مقدار از پیش تعیین شده هستند که قابل تغییر نیستند. این در واقع یک گزینه حتی بهتر است، زیرا استفاده از آنها خوانایی کد شما را بهبود می بخشد. Calendar
public static void main(String[] args) {
GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
}
Calendar.JANUARY یکی از ثابت هایی است که ماه های سال را نشان می دهد. با استفاده از این ثابت های نامگذاری شده، هیچ کس فراموش نمی کند که مثلاً عدد 3 به معنای آوریل است و نه ماه سوم که ما دوست داریم آن را مارس بنامیم. فقط Calendar.APRIL را بنویسید و کارتان تمام شد. :) همه فیلدهای تقویم (تعداد، ماه، دقیقه، ثانیه و غیره) را می توان به طور جداگانه با استفاده ازset()
روش مشخص کرد. این روش بسیار راحت است، زیراCalendar
کلاس برای هر فیلد یک ثابت دارد و کد به دست آمده بسیار راحت خوانده می شود. در مثال آخر، ما یک تاریخ ایجاد کردیم، اما زمانی برای آن تعیین نکردیم. بیایید زمان را 19:42:12 تنظیم کنیم
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar();
calendar.set(Calendar.YEAR, 2017);
calendar.set(Calendar.MONTH, 0);
calendar.set(Calendar.DAY_OF_MONTH, 25);
calendar.set(Calendar.HOUR_OF_DAY, 19);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
System.out.println(calendar.getTime());
}
خروجی: چهارشنبه 25 ژانویه 19:42:12 به وقت گرینویچ 2017 ما set()
متد را فراخوانی می کنیم، یک ثابت (بسته به فیلدی که می خواهیم تغییر دهیم) و مقدار جدید را برای فیلد ارسال می کنیم. به نظر می رسد که این set()
روش نوعی "ابر تنظیم کننده" است که می داند چگونه مقدار را نه فقط برای یک فیلد، بلکه برای بسیاری از فیلدها تنظیم کند. :) کلاس از متد برای جمع و تفریق مقادیر Calendar
استفاده می کند . add()
شما در فیلدی که می خواهید تغییر دهید، و یک عدد (دقیقاً چقدر می خواهید از مقدار فعلی اضافه یا کم کنید) ارسال می کنید. به عنوان مثال، بیایید تاریخی را دریافت کنیم که 2 ماه قبل از تاریخی است که ایجاد کردیم:
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
calendar.set(Calendar.HOUR, 19);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
calendar.add(Calendar.MONTH, -2); // To subtract, pass a negative number
System.out.println(calendar.getTime());
}
خروجی: جمعه 25 نوامبر 19:42:12 GMT 2016 بسیار خوب! ما تاریخ را 2 ماه پیش گرفتیم. این نه تنها باعث تغییر ماه نشد، بلکه سال نیز از سال 2017 به 2016 تغییر کرد. البته، هنگام تبدیل تاریخ، سال جاری به طور خودکار محاسبه می شود بدون اینکه نیازی به پیگیری دستی آن باشد. اما اگر به دلایلی نیاز به غیرفعال کردن این رفتار دارید، می توانید این کار را انجام دهید. این روش می تواند مقادیر را بدون تأثیر بر مقادیر باقیماندهroll()
اضافه و کم کند . به عنوان مثال، مانند این:
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
calendar.set(Calendar.HOUR, 10);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
calendar.roll(Calendar.MONTH, -2);
System.out.println(calendar.getTime());
}
ما دقیقاً همان کاری را که در مثال قبلی انجام دادیم انجام دادیم: از تاریخ فعلی 2 ماه طول کشید. اما اکنون کد کار متفاوتی انجام می دهد: ماه از ژانویه تا نوامبر تغییر کرده است، اما سال بدون تغییر باقی می ماند - 2017! خروجی: شنبه 25 نوامبر 10:42:12 GMT 2017 در حال حرکت. همانطور که در بالا گفتیم، می توانیم تمام Calendar
فیلدها را جداگانه دریافت کنیم. ما این کار را با get()
روش زیر انجام می دهیم:
public static void main(String[] args) {
GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
calendar.set(Calendar.HOUR, 10);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
System.out.println("Year: " + calendar.get(Calendar.YEAR));
System.out.println("Month: " + calendar.get(Calendar.MONTH));
System.out.println("Week in the month: " + calendar.get(Calendar.WEEK_OF_MONTH));// Week in this month?
System.out.println("Day: " + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println("Hours: " + calendar.get(Calendar.HOUR));
System.out.println("Minutes: " + calendar.get(Calendar.MINUTE));
System.out.println("Seconds: " + calendar.get(Calendar.SECOND));
System.out.println("Milliseconds: " + calendar.get(Calendar.MILLISECOND));
}
خروجی: سال: 2017 ماه: 0 هفته در ماه: 5 روز: 25 ساعت: 10 دقیقه: 42 ثانیه: 12 میلی ثانیه: 0 بنابراین، علاوه بر Calendar
"سوپر تنظیم کننده" کلاس، یک "سوپرگیرنده" نیز وجود دارد. ". :) البته یکی دیگر از جنبه های جالب این کلاس کار با دوره هاست. برای ایجاد یک تاریخ "BC"، باید از فیلد Calendar.ERA استفاده کنید، به عنوان مثال، اجازه دهید یک تاریخ برای نبرد Cannae ایجاد کنیم، جایی که هانیبال ارتش روم را شکست داد. این در 2 اوت 216 قبل از میلاد اتفاق افتاد:
public static void main(String[] args) {
GregorianCalendar cannae = new GregorianCalendar(216, Calendar.AUGUST, 2);
cannae.set(Calendar.ERA, GregorianCalendar.BC);
DateFormat df = new SimpleDateFormat("MMM dd, yyy GG");
System.out.println(df.format(cannae.getTime()));
}
در اینجا ما از SimpleDateFormat
کلاس برای چاپ تاریخ در قالبی استفاده کردیم که درک آن برای ما آسان تر باشد (حروف "GG" نشان می دهد که ما می خواهیم دوره نمایش داده شود). خروجی: 02 اوت 216 ق.م. کلاس Calendar
متدها و ثابت های بیشتری دارد. شما می توانید در مورد آنها در اسناد
بخوانید . اگر از این قالب تاریخ شنبه 25 نوامبر 10:42:12 به وقت گرینویچ 2017 خوشتان نمی آید ، می توانید از SimpleDateFormat
آن استفاده کنید تا به راحتی آن را همانطور که می خواهید بسازید.
public static void main(String[] args) {
SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, MMMM d, yyyy");
Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
calendar.set(Calendar.HOUR, 10);
calendar.set(Calendar.MINUTE, 42);
calendar.set(Calendar.SECOND, 12);
calendar.roll(Calendar.MONTH, -2);
System.out.println(dateFormat.format(calendar.getTime()));
}
خروجی: شنبه 25 نوامبر 2017 خیلی بهتر است، اینطور نیست؟ :)
GO TO FULL VERSION