здрасти Днес ще започнем да работим с нов тип данни, който не сме срещали досега, а именно дати.
Мисля, че няма нужда да обяснявам Howво е дата. :) По принцип можем да съхраним текущата дата и час в обикновен Java String.
Това не означава, че тези методи изобщо не могат да се използват. Ако се опитате да изпълните code, използвайки остарели методи в IDE, той най-вероятно ще работи. Например, помислете за остарелия
Повечето от
Датата е само няколко числа, които показват конкретен интервал от време. Календарът е цяла система, която ви позволява да правите много неща с дати. :) Това е много очевидно, ако се опитате да покажете

public class Main {
public static void main(String[] args) {
String date = "June 11, 2018";
System.out.println(date);
}
}
Но този подход има много недостатъци. Класът String
е предназначен за работа с текст и неговите методи са подходящи за тази задача. Ако трябва да манипулираме дата по няHowъв начин (да добавим 2 часа, например), това String
не работи толкова добре. Или ако искаме да покажем текущата дата и час, когато програмата е компorрана. String
не помага и тук: докато напишете codeа и го стартирате, времето ще се е променило и конзолата ще показва грешна информация. Ето защо създателите на Java предоставиха няколко класа за работа с дати и час. Първият от тях еjava.util.Date
Дата клас
Уточнихме пълното му име, защото друг Java пакет има класаjava.sql.Date
. Не ги смесвайте! Първото нещо, което трябва да знаете за нея е, че тя съхранява датата като брой мorсекунди , изминали от 1 януари 1970 г. Тази система за време дори има собствено име: " Unix-време " Доста интересен подход, нали съгласни ли сте? :) Второто нещо, което си струва да запомните, е следното: Ако създадете Date
обект, използвайки конструктора по подразбиране, резултатът представлява текущата дата и час в момента, в който обектът е създаден . Помните ли, че казахме, че дата, представена като a, String
ще се бори с такава задача? Класът Date
се справя с лекота.
public class Main {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date);
}
}
Изпълнете този code няколко пъти и ще видите, че времето се променя многократно. :) Това е възможно, защото времето се съхранява като мorсекунди: те са изключително малки единици за време, така че резултатите са много точни. Класът Date
друг конструктор: можете да подадете точния брой мorсекунди от 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 GMT 2008 г. Получаваме 30 май 2008 г. "Петък" показва деня от седмицата (петък, аха), а GMT е часовата зона (средно време по Гринуич). Мorсекундите се предават като long
s, тъй като броят мorсекунди обикновено не се побира в int
. И така, Howви операции с дати може да трябва да извършим? Е, най-очевидното, разбира се, е сравнението . За да определи дали една дата идва преди or след друга. Това може да стане по няколко начина. Например, можете да извикате Date.getTime()
метода, който връща броя мorсекунди, изминали от полунощ на 1 януари 1970 г. Просто го извикате на два обекта Date и сравнете резултатите:
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));
}
}
Конзолен изход: невярно В нашите примери ние "поставяме програмата да заспи" за 2 секунди, така че двете дати са гарантирано различни. На бързи компютри времето между създаването на date1
и date2
може да бъде по-малко от една мorсекунда, което кара before()
и двете after()
да връщат невярно. Но в този случай equals()
методът ще върне true! В крайна сметка той сравнява броя мorсекунди от 00:00 часа на 1 януари 1970 г. за всяка дата. Обектите се считат за равни само ако съвпадат с точност до мorсекунда :
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));
}
Ето още нещо, на което трябва да обърнете внимание. Ако отворите documentацията за Date
класа на уебсайта на Oracle , ще видите, че много от неговите методи и конструктори са маркирани като Deprecated (т.е. не се препоръчват за употреба). Ето Howво имат да кажат създателите на Java за части от класове, които са отхвърлени:
„Програмен елемент с анотация @Deprecated е нещо, което програмистите не се препоръчва да използват, обикновено защото е опасно or защото има по-добра алтернатива.“ |
Date.getHours()
метод, който връща броя часове, свързани с Date
обект.
public static void main(String[] args) {
Date date1 = new Date();
System.out.println(date1.getHours());
}
Ако стартирате codeа в 14:21 (14:21), той ще покаже числото 14. Както можете да видите, отхвърленият метод е зачеркнат, но все още работи. Тези методи не се премахват, за да не се наруши огромното тяло от съществуващ code, който ги използва. С други думи, тези методи не са нито "счупени", нито "премахнати". Те просто не се препоръчват за употреба, защото има по-удобна алтернатива. Между другото, documentацията изрично споменава тази алтернатива:

Date
методите на класа са преместени в подобрения и разширения Calendar
клас. След това ще се запознаем с този клас. :)
Календар клас
JDK 1.1 въведе нов клас:Calendar
. Това направи работата с дати в Java малко по-лесна от преди. Единственото изпълнение на класа Calendar
, с което ще работим, е класът GregorianCalendar
. Той прилага григорианския календар, който се спазва от повечето страни по света. Основното му предимство е, че може да работи с дати в по-удобен формат. Например може:
- Добавете месец or ден към текущата дата
- Проверете дали годината е високосна;
- Връщане на отделни компоненти на датата (например извличане на номера на месеца от цяла дата)
- Той също така съдържа много удобна система от константи (много от които ще видим по-долу).
Calendar
класа е неговата константа Calendar.ERA : можете да посочите дата преди общата ера (пр.н.е. - преди Христа) or в общата ера (AD - Anno Domini). Нека да разгледаме всичко това с примери. Нека създадем calendar
обект с дата 25 януари 2017 г.:
public static void main(String[] args) {
Calendar calendar = new GregorianCalendar(2017, 0 , 25);
}
В Calendar
класа (Howто и Date
класа по този въпрос) месеците започват от нула , така че предаваме числото 0 като втори аргумент. Когато работите с Calendar
класа, е важно да разберете, че това е просто календар , а не отделна дата. 
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,WEEK_OF_YEAR=?,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,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?] Вижте колко информация получавате ! Календарът има куп свойства, които нормалната дата няма, и всички те се показват (ето HowtoString()
работи методът вCalendar
класа). Ако просто трябва да получите проста дата от календара, т.е. обектDate
, използвайтеCalendar.getTime()
метод (името не е най-логичното, но Howво можете да направите?):
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 GMT 2017 Сега взехме календара и го „намалихме“ до обикновена дата. Да отидем по-нататък. В допълнение към обозначаването на месеци по техния номер, можете да използвате постоянните стойности на полетоCalendar
на класа . Тези константи са статични полета на класа с предварително зададена стойност, която не може да бъде променяна. Това всъщност е още по-добър вариант, защото използването им подобрява четливостта на вашия code. Calendar
public static void main(String[] args) {
GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
}
Calendar.JANUARY е една от константите, които представляват месеците в годината. Използвайки тези именувани константи, никой няма да забрави например, че числото 3 означава април, а не третия месец, който обичаме да наричаме март. Просто напишете Calendar.APRIL и сте готови. :) Всички календарни полета (число, месец, minutesи, секунди и т.н.) могат да бъдат зададени отделно чрез методаset()
. Този метод е много удобен, защотоCalendar
класът има константа за всяко поле и полученият code е много лесен за четене. В последния пример създадохме дата, но не зададохме час за нея. Нека настроим часа 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());
}
Изход: Wed Jan 25 19:42:12 GMT 2017 Извикваме set()
метода, като предаваме константа (в зависимост от полето, което искаме да променим) и новата стойност за полето. Оказва се, че този set()
метод е един вид "супер-задавач", който знае How да зададе стойността не само за едно поле, а за много полета. :) 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. Разбира се, когато преобразувате датите, текущата година се изчислява автоматично, без да е необходимо да я следите ръчно. Но ако по няHowва причина трябва да деактивирате това поведение, можете да го направите. Методът 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 месеца от текущата дата. Но сега codeът прави нещо различно: месецът е променен от януари на ноември, но годината остава непроменена — 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 Мorсекунди: 0 И така, в допълнение към Calendar
„супер-сетер“ на класа има и „супер-гетер“ ". :) Разбира се, друг интересен аспект на този клас е работата с ери. За да създадете дата „пр.н.е.“, ще трябва да използвате полето Calendar.ERA. Например, нека създадем дата за битката при Кана, където Ханибал побеждава римската армия. Това се случи на 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" показват, че искаме ерата да бъде показана). Резултат: 2 август 216 г. пр.н.е. Класът Calendar
има много повече методи и константи. Можете да прочетете за тях в documentацията . Ако не харесвате този формат на датата, събота, 25 ноември 10:42:12 GMT 2017 г. , тогава можете да използвате SimpleDateFormat
, за да я направите лесно такава, Howвато искате да бъде.
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