เวลาของวัน
เรามาต่อกันดีกว่า เอนทิตีถัด ไปหลังจาก date คือเวลาของวัน ซึ่งแสดงโดย คลาส
LocalTime ตัวอย่างคลาสสิกจะแสดงเวลาเปิดทำการของร้านค้า เช่น ตั้งแต่เวลา 7.00 น. ถึง 23.00 น. ร้านค้าที่เปิดในเวลานี้ทั่วประเทศ แต่เวลาจริงจะแตกต่างกันไปขึ้นอยู่กับเขตเวลา
LocalTimeเป็นคลาสค่าที่เก็บเฉพาะเวลา โดยไม่มีวันที่หรือเขตเวลาที่เกี่ยวข้อง เมื่อบวกหรือลบระยะเวลาจะตัดเวลาเที่ยงคืน นั่นคือ 20:00 น. บวก 6 ชั่วโมงคือ 2:00 น. การใช้
LocalTimeนั้นคล้ายคลึงกับ
LocalDate :
LocalTime time = LocalTime.of(20, 30); int hour = date.getHour(); // 20 int minute = date.getMinute(); // 30 time = time.withSecond(6); // 20:30:06 time = time.plusMinutes(3); // 20:33:06
ตัวดัดแปลงสามารถทำงานร่วมกับ
LocalTimeได้ แต่โดยปกติแล้วการดำเนินการด้านเวลาจะไม่ซับซ้อนจนจำเป็นต้องมีตัวดัดแปลง
ผสมผสานวันที่และเวลา
คลาสต่อไปที่เราจะดูคือ
LocalDateTime คลาสค่า นี้เป็นการรวมกันของ
LocalDateและ
LocalTime แสดงถึงทั้งวันที่และเวลาโดยไม่มีเขตเวลา
LocalDateTimeสามารถสร้างได้โดยตรงหรือโดยการรวมวันที่และเวลา:
LocalDateTime dt1 = LocalDateTime.of(2014, Month.JUNE, 10, 20, 30); LocalDateTime dt2 = LocalDateTime.of(date, time); LocalDateTime dt3 = date.atTime(20, 30); LocalDateTime dt4 = date.atTime(time);
ตัวเลือกที่สามและสี่ใช้ เมธอด
atTime()ซึ่งให้วิธีที่ยืดหยุ่นในการรวมวันที่และเวลา คลาสของระบบวันที่และเวลาส่วนใหญ่มีเมธอด "at" ที่สามารถใช้เพื่อรวมอ็อบเจ็กต์ของคุณเข้ากับคลาสอื่นเพื่อสร้างคลาสที่ซับซ้อนมากขึ้น วิธีการอื่นๆ ของคลาส
LocalDateTimeนั้นคล้ายคลึงกับวิธีการของ
LocalDateและ
LocalTime
รูปแบบการตั้งชื่อวิธีการที่คล้ายกันทำให้ APIเรียนรู้ได้ง่ายขึ้น ตารางนี้แสดงรายการคำนำหน้าวิธีการที่เกี่ยวข้องทั้งหมด:
ทันที
เมื่อเราจัดการกับวันที่และเวลา เรามักจะทำงานกับปี เดือน วัน ชั่วโมง นาที วินาที อย่างไรก็ตาม นี่เป็นเพียงรูปแบบหนึ่งของเวลาที่สามารถเรียกได้ว่าเป็น "มนุษย์" แบบที่สองที่ใช้กันทั่วไปคือเวลา "เครื่องจักร" หรือ "ต่อเนื่อง" ในแบบจำลองนี้ จุดบนแกนเวลาจะแสดงด้วยตัวเลขขนาดใหญ่ตัวเดียว วิธีการนี้ทำให้อัลกอริทึมการคำนวณง่ายขึ้น และใช้เพื่อจัดเก็บเวลาใน ระบบปฏิบัติการ
Unixโดยที่เวลาจะแสดงด้วยจำนวนวินาทีที่ผ่านไปตั้งแต่วันที่ 1 มกราคม 1970 ในทำนองเดียวกันใน
Javaเวลาจะถูกจัดเก็บเป็นจำนวนมิลลิวินาทีที่ผ่านไปตั้งแต่วันที่ 1 มกราคม 1970 วิธีการคำนวณเวลาของเครื่องในjava.time
API จัดทำโดยคลาส
Instant value โดยให้ความสามารถในการแสดงจุดบนแกนเวลาโดยไม่ต้องมีข้อมูลประกอบทั้งหมด เช่น เขตเวลา ที่จริงแล้ว คลาสนี้ประกอบด้วยจำนวนนาโนวินาทีที่ผ่านไปตั้งแต่เที่ยงคืนของวันที่ 1 มกราคม 1970
Instant start = Instant.now(); // произведем вычисления Instant end = Instant.now(); assert end.isAfter(start); //машина времени не сработала
โดยทั่วไปแล้ว คลาส
Instantจะใช้ในการจัดเก็บและเปรียบเทียบคะแนนในเวลาที่คุณต้องการจัดเก็บเมื่อมีเหตุการณ์บางอย่างเกิดขึ้น แต่คุณไม่สนใจเขตเวลาที่เหตุการณ์นั้นเกิดขึ้น ในกรณีส่วนใหญ่ สิ่งที่น่าสนใจกว่าสิ่งที่เราทำกับ คลาส
Instant ไม่ได้ มากกว่าสิ่งที่เราสามารถทำได้ ตัวอย่างเช่น บรรทัดของโค้ดต่อไปนี้จะเกิดข้อยกเว้น:
instant.get(ChronoField.MONTH_OF_YEAR); instant.plus(6, ChronoUnit.YEARS);
ข้อยกเว้นเกิดขึ้นเนื่องจาก วัตถุ
ทันทีเก็บเฉพาะจำนวนนาโนวินาที และไม่ได้ให้ความสามารถในการทำงานกับหน่วยเวลาที่เป็นประโยชน์ต่อมนุษย์มากกว่า หากต้องการใช้หน่วยวัดอื่น อย่างน้อยคุณต้องระบุเขตเวลา
โซนเวลา
หลักการของเขตเวลาได้รับการพัฒนาในประเทศอังกฤษ เมื่อมีการประดิษฐ์ทางรถไฟและการปรับปรุงวิธีการสื่อสารอื่นๆ ทำให้ผู้คนสามารถเดินทางในระยะทางที่เพียงพอเพื่อให้เห็นความแตกต่างของเวลาสุริยะได้ จนถึงขณะนี้ แต่ละหมู่บ้านและเมืองต่างใช้ชีวิตตามเวลาของตนเอง ซึ่งส่วนใหญ่มักวัดด้วยนาฬิกาแดด รูปภาพนี้แสดงตัวอย่างความยากลำบากที่นำไปสู่สิ่งนี้ - เข็มสีแดงบนนาฬิกาแสดงเวลากรีนิช และเข็มสีดำแสดงเวลาท้องถิ่น ซึ่งต่างกัน 10 นาที: ระบบโซนเวลาที่พัฒนาขึ้นมาแทนที่เวลาสุริยะใน
ท้องถิ่น แต่ข้อเท็จจริงที่สำคัญก็คือเขตเวลาถูกสร้างขึ้นโดยนักการเมือง และมักจะใช้เพื่อแสดงให้เห็นถึงการควบคุมทางการเมืองเหนือพื้นที่หนึ่งๆ เช่นเดียวกับนโยบายอื่นๆ กฎที่เกี่ยวข้องกับเขตเวลามักจะท้าทายตรรกะ นอกจากนี้ กฎเหล่านี้สามารถเปลี่ยนแปลงได้และมักจะเปลี่ยนแปลงโดยไม่มีการเตือนล่วงหน้า กฎเขตเวลารวบรวมโดยกลุ่มระหว่างประเทศที่เผยแพร่ ฐาน ข้อมูล เขตเวลา
IANA ประกอบด้วยตัวระบุของแต่ละภูมิภาคของโลก และประวัติของเขตเวลาจะเปลี่ยนแปลงไป ตัวระบุมีลักษณะเป็น
"ยุโรป/ลอนดอน"หรือ"
อเมริกา/นิวยอร์ก" ก่อนที่
java.time API จะออก คลาส
TimeZoneจะถูกนำมาใช้เพื่อแสดงเขตเวลา ตอนนี้ ใช้
ZoneIdแทน มีความแตกต่างที่สำคัญสองประการระหว่างพวกเขา ประการแรก
ZoneIdจะไม่เปลี่ยนรูป ซึ่งทำให้สามารถจัดเก็บอ็อบเจ็กต์ของคลาสนี้เป็นตัวแปรคงที่ได้ และอื่นๆ อีกมากมาย ประการที่สอง ตัวกฎจะถูกจัดเก็บไว้ใน คลาส
ZoneRulesไม่ใช่ใน
ZoneIdเองและเพื่อให้ได้กฎนั้น คุณจะต้องเรียกใช้ เมธอด
getRules() บน อ็อบเจ็กต์คลาส
ZoneId คุณลักษณะทั่วไปของเขตเวลาทั้งหมดคือการชดเชยคงที่จาก
UTC/ Greenwich ส่วนใหญ่คุณมักจะใช้คำนี้เมื่อพูดถึงความแตกต่างของเวลาระหว่างเมืองต่างๆ เช่น "นิวยอร์กช้ากว่าลอนดอน 5 ชั่วโมง" คลาส
ZoneOffsetซึ่งเป็นคลาสสืบทอดของ
ZoneIdแสดงถึงความแตกต่างของเวลากับเส้นลมปราณสำคัญที่ผ่านกรีนิชในลอนดอน จากมุมมองของนักพัฒนา จะเป็นการดีที่ไม่ต้องจัดการกับเขตเวลาและความซับซ้อนของเขตเวลา
java.time APIช่วยให้คุณดำเนินการนี้ได้ตราบเท่าที่เป็นไปได้ หากเป็นไปได้ ให้ใช้ คลาส
LocalDate, LocalTime, LocalDateTime และ
Instant ในกรณีที่คุณไม่สามารถทำได้ โดยไม่มีเขตเวลา ให้ใช้ คลาส
ZonedDateTime คลาส
ZonedDateTimeช่วยให้คุณสามารถแปลงวันที่และเวลาจากหน่วยการวัดของมนุษย์ซึ่งเราเห็นในปฏิทินและนาฬิกาเป็นหน่วยเครื่องจักร ด้วยเหตุนี้ คุณสามารถสร้าง
ZonedTimeDateจาก คลาส
Localหรือจาก
คลาส Instant :
ZoneId zone = ZoneId.of("Europe/Paris"); LocalDate date = LocalDate.of(2014, Month.JUNE, 10); ZonedDateTime zdt1 = date.atStartOfDay(zone); Instant instant = Instant.now(); ZonedDateTime zdt2 = instant.atZone(zone);
หนึ่งในคุณสมบัติที่ไม่พึงประสงค์ที่สุดของเขตเวลาคือสิ่งที่เรียกว่าเวลาออมแสง เมื่อเวลาออมแสงสลับไปและกลับจากกรีนิช ความแตกต่างของเขตเวลาของคุณกับกรีนิชจะเปลี่ยนสองครั้ง (หรือมากกว่า) ต่อปี โดยปกติจะเพิ่มขึ้นในฤดูใบไม้ผลิและลดลงในฤดูใบไม้ร่วง เมื่อสิ่งนี้เกิดขึ้นเราต้องเปลี่ยนนาฬิกาทั้งหมดในบ้านของเรา ใน คลาส
java.timeข้อมูลออฟเซ็ตจะแสดงเป็น"
การแปลงออฟเซ็ต" ในฤดูใบไม้ผลิ สิ่งนี้ทำให้เกิด "ช่องว่าง" ของเวลา เมื่อค่าของเวลาบางค่าเป็นไปไม่ได้ และในฤดูใบไม้ร่วง ในทางกลับกัน ค่าของเวลาบางค่าจะเกิดขึ้นสองครั้ง ทั้งหมดนี้ได้รับการสนับสนุนโดย คลาส
ZonedDateTimeผ่านวิธีการจากโรงงานและวิธีการแปลง ตัวอย่างเช่น การเพิ่มหนึ่งวันจะเพิ่มวันตามตรรกะ ซึ่งสามารถแสดงได้มากหรือน้อยกว่า 24 ชั่วโมงหากเราสลับไปเป็นเวลาออมแสงหรือย้อนกลับ ใน ทำนอง เดียวกัน เมธอด
atStartOfDay()ได้รับการตั้งชื่อเช่นนั้น เนื่องจากเราไม่สามารถรับประกันได้ว่าวันนั้นจะเริ่มตอนเที่ยงคืนพอดี เราต้องคำนึงถึงช่องว่างของเวลาเมื่อเปลี่ยนมาใช้การปรับเวลาตามฤดูกาล และเคล็ดลับสุดท้ายประการหนึ่งเกี่ยวกับเวลาออมแสง หากคุณต้องการแสดงให้เห็นว่าคุณได้คำนึงถึงเวลาที่ทับซ้อนกันระหว่างการเปลี่ยนจากฤดูร้อนเป็นฤดูหนาว (เมื่อค่าเวลาเดียวกันปรากฏขึ้นสองครั้ง) คุณสามารถใช้หนึ่งในสองวิธีพิเศษที่ออกแบบมาสำหรับสถานการณ์ดังกล่าว: วิธีการเหล่านี้จะส่งกลับก่อนหน้านี้หรือหลังจากนั้น
zdt = zdt.withEarlierOffsetAtOverlap(); zdt = zdt.withLaterOffsetAtOverlap();
ค่า หากวัตถุติดอยู่ในการทับซ้อนกันระหว่างการเปลี่ยนจากฤดูร้อนเป็นเวลาฤดูหนาว ในสถานการณ์อื่นๆ ทั้งหมด ค่าที่ส่งคืนจะเหมือนกัน
ช่วงเวลา
ชั้นเรียนทั้งหมดที่เราพูดคุยกันก่อนหน้านี้เป็นประเด็นในไทม์ไลน์ จำเป็นต้องมีคลาสค่าเพิ่มเติมสองคลาสเพื่อแสดงช่วงเวลา คลาส
Durationแสดงถึงระยะเวลา โดยมีหน่วยเป็นวินาทีและนาโนวินาที เช่น “23.6 วินาที” คลาส
Periodแสดงถึงช่วงเวลาที่วัดเป็นปี เดือน และวัน ตัวอย่างเช่น - “3 ปี 2 เดือน 6 วัน” สามารถเพิ่มหรือลบช่วงเวลาเหล่านี้ออกจากวันที่หรือเวลาได้:
Period sixMonths = Period.ofMonths(6); LocalDate date = LocalDate.now(); LocalDate future = date.plus(sixMonths);
การจัดรูปแบบและการแยกวิเคราะห์
แพคเกจทั้งหมดได้รับการออกแบบมาเพื่อจัดรูปแบบและแสดงวันที่และเวลา-
java.time.format แพ็คเกจหมุนรอบ คลาส
DateTimeFormatterและโรงงาน
DateTimeFormatterBuilder วิธีทั่วไปในการสร้างฟอร์แมตเตอร์คือการใช้วิธีสแตติกและค่าคงที่ใน
DateTimeFormatterได้แก่:
- ค่าคงที่สำหรับรูปแบบทั่วไปที่อธิบายไว้ใน ISO เช่น ISO_LOCAL_DATE
- รูปแบบที่ระบุด้วยตัวอักษร เช่น ofPattern("dd/MM/uuuu")
- สไตล์ที่แปลแล้ว เช่น ofLocalizedDate(FormatStyle.MEDIUM)
เมื่อคุณสร้างฟอร์แมตเตอร์แล้ว โดยทั่วไปคุณจะใช้มันโดยส่งต่อไปยังเมธอดคลาสวันที่ที่เหมาะสม:
DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM/uuuu"); LocalDate date = LocalDate.parse("24/06/2014", f); String str = date.format(f);
ด้วยวิธีนี้ โค้ดที่รับผิดชอบในการจัดรูปแบบเอาต์พุตวันที่จะถูกแยกออกเป็นคลาสที่แยกจากกัน หากคุณต้องการระบุภาษาแยกต่างหากสำหรับการจัดรูปแบบวันที่ ให้ใช้เมธอด ตัวจัดรูปแบบ
withLocale(Locale) คลาสที่รับผิดชอบเกี่ยวกับปฏิทิน เขตเวลา และอินพุต/เอาท์พุตของตัวเลขเศษส่วนมีวิธีการที่คล้ายกัน หากคุณต้องการตัวเลือกการปรับแต่งเพิ่มเติม โปรดดูเอกสารประกอบสำหรับ คลาส
DateTimeFormatterBuilderซึ่งช่วยให้คุณสร้างตัวจัดรูปแบบที่ซับซ้อนทีละขั้นตอน นอกจากนี้ยังช่วยให้คุณตั้งค่าการแยกวิเคราะห์ข้อความที่ไม่คำนึงถึงขนาดตัวพิมพ์ ละเว้นข้อผิดพลาดในการแยกวิเคราะห์ ตั้งค่าออฟเซ็ต และองค์ประกอบเสริม
บรรทัดล่าง
java.time APIเป็นโมเดลที่ครอบคลุมใหม่สำหรับการทำงานกับวันที่และเวลาในJava
SE 8 นำแนวคิดและการนำไปปฏิบัติจาก
Joda-Timeไปสู่อีกระดับ และในที่สุดช่วยให้นักพัฒนาหลีกเลี่ยงการใช้
java.util.Dateและ
Calendar ตอนนี้การทำงานตามวันที่และเวลาเป็นเรื่องสนุก!
บทความต้นฉบับ
GO TO FULL VERSION