CodeGym /Java Blog /Random /Paano hindi mawawala sa oras: DateTime at Calendar
John Squirrels
Antas
San Francisco

Paano hindi mawawala sa oras: DateTime at Calendar

Nai-publish sa grupo
Hi! Ngayon ay magsisimula kaming magtrabaho gamit ang isang bagong uri ng data na hindi pa namin nakatagpo dati, ibig sabihin, mga petsa. Paano hindi mawawala sa oras: Petsa Oras at Kalendaryo - 1Parang hindi ko na kailangan ipaliwanag kung ano ang date. :) Sa prinsipyo, maaari naming iimbak ang kasalukuyang petsa at oras sa isang ordinaryong Java String.

public class Main {
   public static void main(String[] args) {

       String date = "June 11, 2018";
       System.out.println(date);
   }
}
Ngunit ang pamamaraang ito ay may maraming mga kawalan. Ang Stringklase ay idinisenyo upang gumana sa teksto, at ang mga pamamaraan nito ay angkop para sa gawaing ito. Kung kailangan nating manipulahin ang isang petsa sa anumang paraan (magdagdag ng 2 oras, halimbawa), Stringay hindi gumagana nang maayos. O kung gusto naming ipakita ang kasalukuyang petsa at oras kung kailan ang programa ay pinagsama-sama. Stringay hindi rin nakakatulong dito: sa oras na isulat mo ang code at patakbuhin ito, ang oras ay magbabago at ang console ay magpapakita ng maling impormasyon. Iyon ang dahilan kung bakit nagbigay ang mga tagalikha ng Java ng ilang klase para sa pagtatrabaho sa mga petsa at oras. Ang una sa mga ito ayjava.util.Date

Mag-date ng klase

Tinukoy namin ang buong pangalan nito, dahil isa pang Java package ang may java.sql.Dateklase. Huwag ihalo ang mga ito! Ang unang bagay na kailangan mong malaman tungkol dito ay ang pag-iimbak nito ng petsa bilang bilang ng mga millisecond na lumipas mula noong Enero 1, 1970. Ang sistema ng oras na ito ay may sariling pangalan: " Unix-time " Isang medyo kawili-wiling diskarte, gagawin. pumayag ka ba :) Ang pangalawang bagay na dapat tandaan ay ito: Kung lumikha ka ng isang Datebagay gamit ang default na tagabuo, ang resulta ay kumakatawan sa kasalukuyang petsa at oras sa sandaling nilikha ang bagay . Tandaan na sinabi namin na ang isang petsa ay kinakatawan bilang isang Stringpakikibaka sa ganoong gawain? DateMadali itong hinahawakan ng klase.

public class Main {
   public static void main(String[] args) {

       Date date = new Date();
       System.out.println(date);
   }
}
Patakbuhin ang code na ito nang maraming beses, at makikita mo ang paulit-ulit na pagbabago ng oras. :) Ito ay posible dahil ang oras ay nakaimbak bilang millisecond: ang mga ito ay napakaliit na mga yunit ng oras, kaya ang mga resulta ay lubos na tumpak. Ang Dateklase ay isa pang tagabuo: maaari mong ipasa ang eksaktong bilang ng mga millisecond mula 00:00 noong Enero 1, 1970 hanggang sa kinakailangang petsa, at isang katumbas na object ng petsa ang gagawin:

public class Main {
   public static void main(String[] args) {

       Date date = new Date(1212121212121L);
       System.out.println(date);
   }
}
Output ng console: Biy Mayo 30 04:20:12 GMT 2008 Makukuha natin ang Mayo 30, 2008. Ang "Biy" ay nagpapahiwatig ng araw ng linggo (Biyernes, duh), at ang GMT ay ang time zone (Greenwich Mean Time). Ang mga millisecond ay ipinapasa bilang longs, dahil ang bilang ng mga millisecond ay hindi karaniwang magkasya sa isang int. Kaya, anong mga operasyon na may mga petsa na maaaring kailanganin nating gawin? Well, ang pinaka-halata, siyempre, ay paghahambing . Upang matukoy kung ang isang petsa ay mauuna o pagkatapos ng isa pa. Magagawa ito sa maraming paraan. Halimbawa, maaari mong tawagan ang Date.getTime()pamamaraan, na nagbabalik ng bilang ng mga millisecond na lumipas mula hatinggabi noong Enero 1, 1970. Tawagan lang ito sa dalawang bagay na Petsa at ihambing ang mga resulta:

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");
   }
}
Output: date1 ay mas maaga kaysa date2 Ngunit mayroon ding isang mas maginhawang paraan, ibig sabihin, sa pamamagitan ng paggamit ng mga espesyal na pamamaraan na ibinigay ng klase ng Petsa: before(), after()at equals(). Lahat sila ay nagbabalik ng boolean value. Sinusuri ng before()pamamaraan kung ang aming petsa ay mas maaga kaysa sa petsang ipinasa bilang isang argumento:

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));
   }
}
Output ng console: true Katulad nito, after()sinusuri ng pamamaraan upang makita kung ang aming petsa ay mas huli kaysa sa petsa na ipinasa bilang isang argumento:

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));
   }
}
Output ng console: false Sa aming mga halimbawa, "ipinatulog namin ang program" sa loob ng 2 segundo, upang matiyak na magkaiba ang dalawang petsa. Sa mabilis na mga computer, ang oras sa pagitan ng paggawa ng date1at date2maaaring mas mababa sa isang millisecond, na nagiging sanhi ng pareho before()at after()magbalik ng false. Ngunit sa kasong ito, ang equals()pamamaraan ay babalik na totoo! Pagkatapos ng lahat, inihahambing nito ang bilang ng mga millisecond mula 00:00 noong Enero 1, 1970 para sa bawat petsa. Ang mga bagay ay itinuturing na pantay lamang kung tumugma ang mga ito sa millisecond :

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));
}
Narito ang isa pang bagay na kailangan mong bigyang pansin. Kung bubuksan mo ang dokumentasyon para sa Dateklase sa website ng Oracle , makikita mo na marami sa mga pamamaraan at constructor nito ang minarkahan bilang Hindi na ginagamit (ibig sabihin, hindi inirerekomenda para sa paggamit). Narito ang sinabi ng mga tagalikha ng Java tungkol sa mga bahagi ng mga klase na hindi na ginagamit:
"Ang isang elemento ng program na may annotate na @Deprecated ay isang bagay na hindi inirerekomenda ng mga programmer na gamitin, kadalasan dahil ito ay mapanganib, o dahil may mas mahusay na alternatibo."
Hindi ito nangangahulugan na ang mga pamamaraang ito ay hindi magagamit sa lahat. Kung susubukan mong patakbuhin ang code gamit ang mga hindi na ginagamit na pamamaraan sa isang IDE, malamang na gagana ito. Halimbawa, isaalang-alang ang hindi na ginagamit na Date.getHours()paraan, na nagbabalik ng bilang ng mga oras na nauugnay sa isang Datebagay.

public static void main(String[] args) {

   Date date1 = new Date();

   System.out.println(date1.getHours());
}
Kung sisimulan mo ang code sa 14:21 (2:21 PM), ipapakita nito ang numero 14. Gaya ng nakikita mo, ang hindi na ginagamit na paraan ay tinatanggal, ngunit gumagana pa rin ito. Ang mga pamamaraang ito ay hindi inaalis upang hindi masira ang malaking katawan ng umiiral na code na gumagamit sa kanila. Sa madaling salita, ang mga pamamaraang ito ay hindi "nasira" o "naalis". Ang mga ito ay hindi inirerekomenda para sa paggamit dahil ang isang mas maginhawang alternatibo ay magagamit. Hindi sinasadya, partikular na binanggit ng dokumentasyon ang alternatibong ito:
Paano hindi mawawala sa oras: PetsaOras at Kalendaryo - 2
Karamihan sa mga Datepamamaraan ng klase ay inilipat sa pinahusay at pinalawig Calendarna klase. Magkakilala na tayo sa klase sa susunod. :)

Klase sa kalendaryo

Ipinakilala ng JDK 1.1 ang isang bagong klase: Calendar. Ginawa nitong medyo mas madali ang pagtatrabaho sa mga petsa sa Java kaysa dati. Ang tanging pagpapatupad ng klase Calendarna aming gagawin ay ang GregorianCalendarklase. Ipinapatupad nito ang kalendaryong Gregorian, na sinusunod ng karamihan sa mga bansa sa mundo. Ang pangunahing bentahe nito ay maaari itong gumana sa mga petsa sa isang mas maginhawang format. Halimbawa, maaari itong:
  • Magdagdag ng buwan o araw sa kasalukuyang petsa
  • Suriin kung ang taon ay isang leap year;
  • Ibalik ang mga indibidwal na bahagi ng petsa (halimbawa, kunin ang numero ng buwan mula sa isang buong petsa)
  • Naglalaman din ito ng isang napaka-maginhawang sistema ng mga constants (marami sa mga ito ay makikita natin sa ibaba).
Ang isa pang mahalagang pagpapahusay ng Calendarklase ay ang Calendar.ERA constant: maaari mong ipahiwatig ang isang petsa bago ang karaniwang panahon (BC - bago si Kristo) o sa karaniwang panahon (AD - Anno Domini). Tingnan natin ang lahat ng ito na may mga halimbawa. Gumawa tayo ng calendarobject na may petsang Enero 25, 2017:

public static void main(String[] args) {

  Calendar calendar = new GregorianCalendar(2017, 0 , 25);
}
Sa Calendarklase (pati na rin ang Dateklase para sa bagay na iyon), ang mga buwan ay nagsisimula sa zero , kaya ipinapasa namin ang numero 0 bilang pangalawang argumento. Kapag nagtatrabaho kasama ang Calendarklase, mahalagang maunawaan na ito lang, isang kalendaryo , hindi isang indibidwal na petsa. Paano hindi mawawala sa oras: Petsa Oras at Kalendaryo - 3 Ang petsa ay ilan lamang sa mga numero na nagsasaad ng partikular na agwat ng oras. Ang kalendaryo ay isang buong sistema na nagbibigay-daan sa iyong gumawa ng maraming bagay sa mga petsa. :) Ito ay lubos na maliwanag kung susubukan mong ipakita ang Calendarbagay: Output: 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_MONTH=25,DAY_OF_DAY=25,DAY_OF_DAY_ ,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?] Tingnan kung gaano karaming impormasyon ang makukuha mo ! Ang isang kalendaryo ay may isang grupo ng mga katangian na wala sa isang normal na petsa, at lahat ng mga ito ay ipinapakita (ito ay kung paanotoString()gumagana ang pamamaraan saCalendarklase). Kung kailangan mo lang makakuha ng isang simpleng petsa mula sa kalendaryo, ibig sabihin, isangDatebagay, gamitin angCalendar.getTime()paraan (ang pangalan ay hindi ang pinaka-lohikal, ngunit ano ang maaari mong gawin?):

public static void main(String[] args) {

   Calendar calendar = new GregorianCalendar(2017, 0 , 25);
   Date date = calendar.getTime();
   System.out.println(date);
}
Output: Wed Ene 25 00:00:00 GMT 2017 Ngayon kinuha namin ang kalendaryo at "binawasan ito" sa isang ordinaryong petsa. Tayo ay pumunta sa karagdagang. Bilang karagdagan sa pagtatalaga ng mga buwan ayon sa kanilang numero, maaari mong gamitin ang pare-parehong mga value ng fieldCalendar ng klase . Ang mga constant na ito ay mga static na field ng klase na may preset na value na hindi mababago. Ito ay talagang isang mas mahusay na pagpipilian, dahil ang paggamit ng mga ito ay nagpapabuti sa pagiging madaling mabasa ng iyong code. Calendar

public static void main(String[] args) {
   GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
}
Kalendaryo.Ang ENERO ay isa sa mga constant na kumakatawan sa mga buwan ng taon. Gamit ang mga pinangalanang constant na ito, walang makakalimutan, halimbawa, na ang numero 3 ay nangangahulugang Abril, at hindi ang ikatlong buwan, na gusto nating tawagan ng Marso. Isulat lang ang Calendar.APRIL , at tapos ka na. :) Lahat ng mga field ng kalendaryo (numero, buwan, minuto, segundo, atbp.) ay maaaring tukuyin nang hiwalay gamit angset()pamamaraan. Ang pamamaraang ito ay napaka-maginhawa, dahil angCalendarklase ay may pare-pareho para sa bawat field, at ang resultang code ay napakadaling basahin. Sa huling halimbawa, gumawa kami ng petsa, ngunit hindi nagtakda ng oras para dito. Itakda natin ang oras 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());
}
Output: Wed Ene 25 19:42:12 GMT 2017 Tinatawag namin ang set()method, pagpasa ng constant (depende sa field na gusto naming baguhin) at ang bagong value para sa field. Lumalabas na ang set()pamamaraang ito ay isang uri ng "super-setter" na alam kung paano itakda ang halaga hindi lamang para sa isang field, ngunit para sa maraming field. :) Ang Calendarklase ay gumagamit ng add()paraan upang magdagdag at magbawas ng mga halaga. Pumasa ka sa field na gusto mong baguhin, at isang numero (kung magkano ang gusto mong idagdag/bawas mula sa kasalukuyang halaga). Halimbawa, kumuha tayo ng petsa na 2 buwan bago ang petsa na ginawa natin:

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());
}
Output: Biy Nob 25 19:42:12 GMT 2016 Napakaganda! Nakuha namin ang date 2 months ago. Hindi lang ito naging dahilan ng pagbabago ng buwan: nagbago din ang taon mula 2017 hanggang 2016. Siyempre, kapag nagko-convert ng mga petsa, awtomatikong kinakalkula ang kasalukuyang taon nang hindi mo kailangang subaybayan ito nang manu-mano. Ngunit kung sa ilang kadahilanan ay kailangan mong huwag paganahin ang pag-uugaling ito, magagawa mo ito. Ang roll()pamamaraan ay maaaring magdagdag at magbawas ng mga halaga nang hindi naaapektuhan ang natitirang mga halaga . Halimbawa, tulad nito:

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());
}
Ginawa namin ang parehong bagay tulad ng sa nakaraang halimbawa: tumagal kami ng 2 buwan mula sa kasalukuyang petsa. Ngunit ngayon ay may ibang ginagawa ang code: ang buwan ay nagbago mula Enero hanggang Nobyembre, ngunit ang taon ay nananatiling hindi nagbabago—2017! Output: Sat Nob 25 10:42:12 GMT 2017 Gumagalaw. Tulad ng sinabi namin sa itaas, maaari naming makuha ang lahat ng Calendarmga field nang hiwalay. Ginagawa namin ito sa get()pamamaraan:

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));

}
Output: Taon: 2017 Buwan: 0 Linggo sa buwan: 5 Araw: 25 Oras: 10 Minuto: 42 Segundo: 12 Milisecond: 0 Kaya, bilang karagdagan sa Calendar"super-setter" ng klase, mayroon ding "super-getter" ". :) Siyempre, isa pang kawili-wiling aspeto ng klase na ito ay gumagana sa mga panahon. Upang lumikha ng petsa ng "BC", kakailanganin mong gamitin ang field na Calendar.ERA Halimbawa, gumawa tayo ng petsa para sa Labanan sa Cannae, kung saan natalo ni Hannibal ang hukbong Romano. Nangyari ito noong Agosto 2, 216 BC:

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()));
}
Dito ginamit namin ang SimpleDateFormatklase upang i-print ang petsa sa isang format na mas madaling maunawaan namin (ang mga titik na "GG" ay nagpapahiwatig na gusto naming ipakita ang panahon). Output: Agosto 02, 216 BC. Ang Calendarklase ay may maraming iba pang mga pamamaraan at pare-pareho. Maaari mong basahin ang tungkol sa mga ito sa dokumentasyon . Kung hindi mo gusto ang format ng petsang ito Sab Nob 25 10:42:12 GMT 2017 pagkatapos ay magagamit mo SimpleDateFormatito upang madaling gawin ito kung ano ang gusto mo.

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()));
}
Output: Sabado, Nobyembre 25, 2017 Mas maganda iyon, di ba? :)
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION