TL; DR
Instant
และLocalDateTime
เป็นสัตว์สองชนิดที่ต่างกันโดยสิ้นเชิง: ตัวหนึ่งแสดงถึงช่วงเวลาหนึ่งช่วงเวลาอื่น ๆ ไม่ได้
Instant
แสดงถึงช่วงเวลาหนึ่งซึ่งเป็นจุดเฉพาะในไทม์ไลน์
LocalDateTime
แสดงถึงวันที่และเวลาของวัน แต่ไม่มีเขตเวลาหรือออฟเซ็ตจาก UTC ชั้นนี้ไม่สามารถแสดงได้ในขณะนี้ มันแสดงถึงช่วงเวลาที่อาจเกิดขึ้นตามช่วงเวลาประมาณ 26-27 ชั่วโมงซึ่งเป็นช่วงของเขตเวลาทั้งหมดทั่วโลก
ข้อสันนิษฐานที่ไม่ถูกต้อง
LocalDateTime
ค่อนข้างเป็นตัวแทนวันที่ / นาฬิการวมถึงเขตเวลาสำหรับมนุษย์
คำสั่งของคุณไม่ถูกต้อง: มีไม่มีโซนเวลา ไม่มีโซนเวลาเป็นจุดรวมของคลาสนั้นLocalDateTime
ในการอ้างอิงเอกสารของชั้นเรียน:
คลาสนี้ไม่ได้จัดเก็บหรือเป็นตัวแทนของเขตเวลา แต่มันเป็นคำอธิบายของวันที่ที่ใช้สำหรับวันเกิดรวมกับเวลาท้องถิ่นตามที่เห็นบนนาฬิกาแขวน ไม่สามารถเป็นตัวแทนของทันเวลาบนเส้นเวลาโดยไม่มีข้อมูลเพิ่มเติมเช่นออฟเซ็ตหรือโซนเวลา
ดังนั้นLocal…
หมายถึง“ ไม่กำหนดเขตไม่มีการชดเชย”
Instant
An Instant
คือช่วงเวลาบนเส้นเวลาในUTCซึ่งนับเป็นนาโนวินาทีนับตั้งแต่ช่วงเวลาในช่วงเวลาแรกของปี 1970 UTC (โดยทั่วไปโปรดดูเอกสารรายละเอียดของ nitty-gritty) เนื่องจากตรรกะทางธุรกิจส่วนใหญ่ของคุณพื้นที่เก็บข้อมูลและการแลกเปลี่ยนข้อมูลควรอยู่ใน UTC นี่เป็นคลาสที่ใช้งานได้ง่าย
Instant instant = Instant.now() ; // Capture the current moment in UTC.
OffsetDateTime
คลาสของOffsetDateTime
ชั้นแสดงถึงช่วงเวลาเป็นวันที่และเวลาโดยมีบริบทเป็นจำนวนชั่วโมง - นาที - วินาทีก่อนเวลาหรือหลัง UTC จำนวนออฟเซ็ตจำนวนชั่วโมง - นาที - วินาทีแสดงโดยZoneOffset
คลาส
หากจำนวนชั่วโมง - นาที - วินาทีเป็นศูนย์จะOffsetDateTime
แสดงช่วงเวลาใน UTC เหมือนกับInstant
เวลา
ZoneOffset
ZoneOffset
ชั้นหมายถึงการชดเชยจากที่ UTCจำนวนชั่วโมงนาทีวินาทีข้างหน้าของ UTC หรือด้านหลัง UTC
A ZoneOffset
เป็นเพียงจำนวนชั่วโมงนาทีนาทีไม่มีอะไรเพิ่มเติม โซนนั้นมีมากขึ้นโดยมีชื่อและประวัติการเปลี่ยนแปลงเพื่อชดเชย ดังนั้นการใช้โซนจะดีกว่าการใช้ออฟเซ็ตเท่านั้น
ZoneId
โซนเวลาเป็นตัวแทนจากZoneId
ระดับ
ยกตัวอย่างเช่นวันใหม่ในปารีสนั้นเร็วกว่าในมอนทรีออล ดังนั้นเราจำเป็นต้องขยับเข็มนาฬิกาเพื่อสะท้อนเวลาเที่ยง (เมื่อดวงอาทิตย์อยู่เหนือศีรษะโดยตรง) สำหรับภูมิภาคที่กำหนด ไกลออกไปทางทิศตะวันออก / ทิศตะวันตกจากเส้น UTC ในยุโรปตะวันตก / แอฟริกาที่มีขนาดใหญ่ชดเชย
เขตเวลาเป็นชุดของกฎสำหรับจัดการกับการปรับและความผิดปกติที่ชุมชนท้องถิ่นหรือภูมิภาคปฏิบัติ ที่พบมากที่สุดคือความผิดปกติบ้าทุกเกินไปนิยมที่รู้จักกันเป็นเวลาออมแสง (DST)
เขตเวลามีประวัติของกฎที่ผ่านมากฎปัจจุบันและกฎที่ยืนยันสำหรับอนาคตอันใกล้
กฎเหล่านี้เปลี่ยนแปลงบ่อยกว่าที่คุณคาดหวัง ตรวจสอบให้แน่ใจว่าได้ปฏิบัติตามกฎของห้องสมุดวันที่ของคุณโดยปกติจะเป็นสำเนาของฐานข้อมูล 'tz' ซึ่งเป็นข้อมูลล่าสุด การรักษาขึ้นไปวันที่ง่ายกว่าที่เคยในขณะนี้ใน Java 8 กับ Oracle ปล่อยอัพเดตเครื่องมือเขตเวลา
ระบุชื่อโซนเวลาที่เหมาะสมในรูปแบบของContinent/Region
เช่นAmerica/Montreal
, หรือAfrica/Casablanca
Pacific/Auckland
อย่าใช้ตัวย่อ 2-4 ตัวอักษรเช่นEST
หรือIST
เนื่องจากไม่ใช่เขตเวลาจริงไม่ใช่แบบมาตรฐานและไม่ซ้ำกัน (!)
เขตเวลา = ออฟเซ็ต + กฎการปรับค่า
ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
ZonedDateTime
คิดว่าZonedDateTime
แนวคิดเป็นกับที่ได้รับมอบหมายInstant
ZoneId
ZonedDateTime = (ทันที + โซนหมายเลข)
ในการจับภาพช่วงเวลาปัจจุบันตามที่เห็นในเวลานาฬิกาแขวนที่ผู้คนในภูมิภาคนั้นใช้ (เขตเวลา):
ZonedDateTime zdt = ZonedDateTime.now( z ) ; // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`.
เกือบทุกแบ็กเอนด์ฐานข้อมูลตรรกะทางธุรกิจการคงอยู่ของข้อมูลการแลกเปลี่ยนข้อมูลควรอยู่ใน UTC แต่สำหรับการนำเสนอต่อผู้ใช้คุณต้องปรับเป็นเขตเวลาที่ผู้ใช้คาดหวัง นี่คือจุดประสงค์ของZonedDateTime
คลาสและคลาสตัวจัดรูปแบบที่ใช้เพื่อสร้างการแทนค่าสตริงของค่าวันที่และเวลา
ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ; // Standard ISO 8601 format.
DateTimeFormatter
คุณสามารถสร้างข้อความในรูปแบบที่มีการแปลโดยใช้
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
String outputFormatted = zdt.format( f ) ;
mardi 30 avril 2019 à 23 h 22 min 55 s heure de l'Inde
LocalDate
, LocalTime
,LocalDateTime
ว่า "ท้องถิ่น" เรียนวันเวลาLocalDateTime
, LocalDate
, LocalTime
เป็นชนิดที่แตกต่างกันของสัตว์ The ไม่ได้เชื่อมโยงกับท้องที่หรือเขตเวลาใดเขตหนึ่ง พวกเขาไม่ได้เชื่อมโยงกับไทม์ไลน์ พวกเขาไม่มีความหมายที่แท้จริงจนกว่าคุณจะนำไปใช้กับท้องที่เพื่อหาจุดบนเส้นเวลา
คำว่า "Local" ในชื่อชั้นเรียนเหล่านี้อาจตอบโต้ผู้ที่ไม่ได้ฝึกหัด คำนี้หมายถึงสถานที่ใด ๆหรือทุกท้องที่ แต่ไม่ใช่สถานที่เฉพาะ
ดังนั้นสำหรับแอปทางธุรกิจประเภท "ท้องถิ่น" จึงไม่ได้ใช้บ่อยเพราะเป็นเพียงแนวคิดทั่วไปของวันที่หรือเวลาที่เป็นไปได้ไม่ใช่ช่วงเวลาเฉพาะบนไทม์ไลน์ แอปทางธุรกิจมีแนวโน้มที่จะใส่ใจในช่วงเวลาที่ใบแจ้งหนี้มาถึงสินค้าที่จัดส่งสำหรับการขนส่งพนักงานถูกจ้างหรือแท็กซี่ออกจากโรงรถ ดังนั้นนักพัฒนาแอพพลิเคชั่นทางธุรกิจจึงใช้งานInstant
และZonedDateTime
คลาสทั่วไป
แล้วเราจะใช้เมื่อไหร่LocalDateTime
? ในสามสถานการณ์: ที่ที่เราต้องการใช้วันที่และเวลาที่แน่นอนในหลาย ๆ สถานที่ที่เราทำการจองการนัดหมายหรือที่เรามีเขตเวลาที่ตั้งใจยังไม่ได้กำหนด โปรดสังเกตว่าไม่มีทั้งสามกรณีนี้เป็นจุดเฉพาะเจาะจงหนึ่งเดียวบนไทม์ไลน์ไม่มีสิ่งเหล่านี้สักครู่
ครั้งเดียวหลายช่วงเวลา
บางครั้งเราต้องการแสดงเวลาที่แน่นอนในวันที่กำหนด แต่ต้องการนำไปใช้กับหลาย ๆ เมืองในเขตเวลา
ยกตัวอย่างเช่น "คริสมาสต์เริ่มต้นที่เที่ยงคืนวันที่ 25 ธันวาคม 2015 ว่า" LocalDateTime
เป็น เที่ยงคืนนัดในช่วงเวลาที่แตกต่างกันในกรุงปารีสกว่าในมอนทรีออและที่แตกต่างกันอีกครั้งในซีแอตเติและในโอ๊คแลนด์
LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ; // 00:00:00
LocalTime ldt = LocalDateTime.of( ld , lt ) ; // Xmas morning anywhere.
อีกตัวอย่างหนึ่ง "Acme บริษัท ฯ มีนโยบายที่จะเริ่มต้นเวลาอาหารกลางวันที่ 12:30 ในแต่ละโรงงานทั่วโลก" LocalTime
คือ เพื่อให้มีความหมายที่แท้จริงคุณต้องนำไปใช้กับเส้นเวลาเพื่อกำหนดช่วงเวลา 12:30 ที่โรงงานสตุตการ์ตหรือ 12:30 ที่โรงงานราบัตหรือ 12:30 ที่โรงงานซิดนีย์
นัดหมายจอง
อีกสถานการณ์ที่จะใช้LocalDateTime
สำหรับการจองกิจกรรมในอนาคต (เช่นการนัดหมายทันตแพทย์) การนัดหมายเหล่านี้อาจมีมากพอที่จะเกิดขึ้นในอนาคตซึ่งคุณอาจเสี่ยงต่อการกำหนดเขตเวลาใหม่ นักการเมืองมักจะเตือนล่วงหน้าเล็กน้อยหรือไม่มีการเตือนเลย หากคุณหมายถึง "15.00 น. ถัดไปวันที่ 23 มกราคม" โดยไม่คำนึงว่านักการเมืองจะเล่นอย่างไรกับนาฬิกาคุณจะไม่สามารถบันทึกช่วงเวลานั้นได้ซึ่งจะเห็นเวลา 15.00 น. กลายเป็น 14.00 น. หรือ 16.00 น. หากภูมิภาคนั้นรับรองหรือลดเวลาตามฤดูกาล ตัวอย่างเช่น.
สำหรับการนัดหมายให้จัดเก็บ a LocalDateTime
และ a ZoneId
แยกกัน ต่อมาเมื่อสร้างตารางเวลา on-the-fly จะกำหนดช่วงเวลาโดยการโทรLocalDateTime::atZone( ZoneId )
เพื่อสร้างZonedDateTime
วัตถุ
ZonedDateTime zdt = ldt.atZone( z ) ; // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.
หากจำเป็นคุณสามารถปรับเป็น UTC สารสกัดจากInstant
ZonedDateTime
Instant instant = zdt.toInstant() ; // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.
เขตที่ไม่รู้จัก
บางคนอาจใช้LocalDateTime
ในสถานการณ์ที่ไม่ทราบเขตเวลาหรือออฟเซ็ต
ฉันพิจารณากรณีนี้ไม่เหมาะสมและไม่ฉลาด หากมีการกำหนดเขตหรือออฟเซ็ต แต่ไม่ได้ระบุว่าคุณมีข้อมูลที่ไม่ดี นั่นจะเป็นเหมือนการเก็บราคาสินค้าโดยไม่ทราบสกุลเงินที่ต้องการ ไม่ใช่ความคิดที่ดี
ประเภทวันที่และเวลา
เพื่อความสมบูรณ์นี่คือตารางประเภทวันที่และเวลาที่เป็นไปได้ทั้งหมดทั้งทันสมัยและดั้งเดิมใน Java เช่นเดียวกับที่กำหนดโดยมาตรฐาน SQL สิ่งนี้อาจช่วยวางInstant
& LocalDateTime
คลาสในบริบทที่กว้างขึ้น
สังเกตเห็นทางเลือกแปลก ๆ ที่สร้างขึ้นโดยทีมงาน Java ในการออกแบบ JDBC 4.2 พวกเขาเลือกที่จะสนับสนุนเวลาjava.timeทั้งหมด ... ยกเว้นสองคลาสที่ใช้บ่อยที่สุด: Instant
& ZonedDateTime
.
แต่ไม่ต้องกังวล เราสามารถแปลงไปมาได้อย่างง่ายดาย
Instant
แปลง
// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;
// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;
ZonedDateTime
แปลง
// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;
// Retrieving
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ;
เกี่ยวกับjava.time
java.timeกรอบถูกสร้างขึ้นใน Java 8 และต่อมา ชั้นเรียนเหล่านี้แย่งลำบากเก่ามรดกเรียนวันที่เวลาเช่นjava.util.Date
, และCalendar
SimpleDateFormat
Joda เวลาโครงการขณะนี้อยู่ในโหมดการบำรุงรักษาให้คำแนะนำแก่การโยกย้ายไปยังjava.timeชั้นเรียน
ต้องการเรียนรู้เพิ่มเติมโปรดดูที่ออราเคิลกวดวิชา และค้นหา Stack Overflow สำหรับตัวอย่างและคำอธิบายมากมาย สเปกJSR 310
คุณสามารถแลกเปลี่ยนวัตถุjava.timeโดยตรงกับฐานข้อมูลของคุณ ใช้ไดรเวอร์ JDBC ที่สอดคล้องกับJDBC 4.2หรือใหม่กว่า ไม่จำเป็นต้องใช้สตริงไม่จำเป็นต้องมีjava.sql.*
คลาส
จะรับคลาส java.time ได้ที่ไหน?
โครงการThreeTen-Extraขยาย java.time ด้วยคลาสเพิ่มเติม โครงการนี้เป็นพื้นฐานที่พิสูจน์ได้สำหรับการเพิ่มเติมในอนาคตไปยัง java.time คุณอาจพบว่าการเรียนที่มีประโยชน์บางอย่างที่นี่เช่นInterval
, YearWeek
, YearQuarter
และอื่น ๆ อีกมากมาย