JavaRush /จาวาบล็อก /Random-TH /ในที่สุดไลบรารี่ที่ใช้งานง่ายและมีประสิทธิภาพสำหรับการทำง...
theGrass
ระดับ
Саратов

ในที่สุดไลบรารี่ที่ใช้งานง่ายและมีประสิทธิภาพสำหรับการทำงานกับเวลาและวันที่ก็พร้อมใช้งานแล้วใน Java (ตอนที่ 1)

เผยแพร่ในกลุ่ม
    ในที่สุดJavaก็มีวิธีที่ใช้งานง่ายและเชื่อถือได้ในการทำงานกับวันที่และเวลา หลักการของวันที่และเวลาเป็นพื้นฐานในการใช้งานหลายอย่าง สิ่งต่างๆ เช่น วันเกิด วันที่เช่า เวลากิจกรรม และเวลาเปิดทำการของร้านค้า ล้วนขึ้นอยู่กับวันที่และเวลา แต่Java SEไม่มีวิธีที่สะดวกในการทำงานกับสิ่งเหล่านั้น เริ่มต้นด้วยJava SE 8 มีชุด แพ็คเกจjava.timeซึ่งมีAPI ที่มีโครงสร้างดี สำหรับการทำงานกับวันที่และเวลา
พื้นหลัง
    เมื่อJavaเปิดตัวครั้งแรก ในเวอร์ชัน1.0คลาสเดียวสำหรับการทำงานกับวันที่และเวลาคือjava.util.Date สิ่งแรกที่นักพัฒนาสังเกตเห็นคือมันไม่ได้แสดงถึง "วันที่" ในความเป็นจริง มันแสดงถึงช่วงเวลาหนึ่งซึ่งมีความแม่นยำถึงมิลลิวินาที วัดจากวันที่ 1 มกราคม 1970 อย่างไรก็ตาม จากข้อเท็จจริงที่ว่า เมธอด toString()ของDateแสดงวันที่และเวลาในเขตเวลาที่ระบุใน การตั้งค่า java ของเครื่อง นักพัฒนาบางรายจึงสรุปอย่างผิดพลาดว่าDateสามารถทำงานกับเขตเวลาได้ การแก้ไขคลาสนี้กลายเป็นเรื่องยาก (หรือขี้เกียจมาก) ซึ่งในเวอร์ชัน1.1เราต้องเพิ่มคลาสใหม่- java.util.Calendar น่าเสียดายที่ คลาส Calendarกลับกลายเป็นว่าไม่ได้ดีไปกว่าDate มาก นัก ต่อไปนี้คือรายการปัญหาเล็กๆ น้อยๆ ที่มีอยู่ในการใช้งาน:
  • เปลี่ยนแปลงได้ คลาสเช่นวันที่และเวลาควรไม่เปลี่ยนรูป
  • ออฟเซ็ต ปีในวันที่เริ่มต้นจาก 1900 เดือนในทั้งสองชั้นเรียนเริ่มต้นจากศูนย์
  • ชื่อ. วันที่ไม่ใช่ "วันที่" จริงๆ และปฏิทินไม่ใช่ปฏิทิน
  • การจัดรูปแบบ การจัดรูปแบบใช้ได้กับวันที่เท่านั้น ไม่ใช่ปฏิทิน และไม่ปลอดภัยสำหรับเธรด
    ในปี 2544 โครงการ Joda-Time ถูกสร้างขึ้น เป้าหมายของเขานั้นเรียบง่าย - เพื่อสร้างไลบรารี่ คุณภาพสูงสำหรับการทำงานกับวันที่และเวลาใน Java ใช้เวลานานพอสมควร แต่ในที่สุด เวอร์ชัน 1.0ก็ออกสู่ตลาดและได้รับความนิยมอย่างรวดเร็วและใช้กันอย่างแพร่หลาย เมื่อเวลาผ่านไป นักพัฒนาเรียกร้องมากขึ้นเรื่อยๆ ว่าต้องจัดเตรียมไลบรารี่ที่มีความสะดวกสบายคล้ายคลึงกันให้เป็นส่วนหนึ่งของ JDK ด้วยการมีส่วนร่วมของ Michael Nascimento Santos จากบราซิล โครงการ JSR-310ได้เปิดตัวซึ่งเป็นกระบวนการอย่างเป็นทางการสำหรับการสร้างและบูรณา การ APIใหม่ สำหรับการทำงานกับวันที่และเวลาใน JDK
ทบทวน
java.time API ใหม่ประกอบด้วย 5 แพ็คเกจ:
  • java.time - แพ็คเกจพื้นฐานที่มีอ็อบเจ็กต์เพื่อเก็บค่า
  • java.time.chrono - ให้การเข้าถึงปฏิทินต่างๆ
  • java.time.format - การจัดรูปแบบและการจดจำวันที่และเวลา
  • java.time.temporal - ไลบรารีระดับต่ำและฟังก์ชันขั้นสูง
  • java.time.zone - คลาสสำหรับการทำงานกับเขตเวลา
    นักพัฒนาส่วนใหญ่จะใช้แพ็คเกจฐานและการจัดรูปแบบเป็นส่วนใหญ่ และบางทีอาจเป็น java.time.temporal ดังนั้นแม้ว่าจะมีการเพิ่มประเภทใหม่ถึง 68 ประเภท แต่นักพัฒนาจะใช้เพียงประมาณหนึ่งในสามเท่านั้น
วันที่
    คลาส LocalDateเป็นหนึ่งในคลาสที่สำคัญที่สุดใน APIใหม่ ประกอบด้วยค่าที่ไม่เปลี่ยนรูปซึ่งแสดงถึงวันที่ คุณไม่สามารถตั้งเวลาหรือโซนเวลาได้ ชื่อ "local" อาจคุ้นเคยกับคุณจาก Joda-Timeและมาจาก มาตรฐาน ISO - 8601 มันหมายถึงการไม่มีเขตเวลาอย่างแม่นยำ โดยพื้นฐานแล้ว LocalDateคือคำอธิบายของวันที่ เช่น "5 เมษายน 2014" เวลาจริงของวันที่นี้จะแตกต่างกันไปขึ้นอยู่กับเขตเวลาของคุณ ตัวอย่างเช่น ในออสเตรเลีย วันที่นี้จะเร็วกว่าในลอนดอน 10 ชั่วโมง และเร็วกว่าในซานฟรานซิสโก 18 ชั่วโมง คลาส LocalDateมีวิธีการที่จำเป็นโดยทั่วไปทั้งหมด: LocalDate date = LocalDate.of(2014, Month.JUNE, 10); int year = date.getYear(); // 2014 Month month = date.getMonth(); // Июнь int dom = date.getDayOfMonth(); // 10 DayOfWeek dow = date.getDayOfWeek(); // Вторник int len = date.lengthOfMonth(); // 30 (дней в Июне) boolean leap = date.isLeapYear(); // false (не високосный год)     ในตัวอย่างของเรา เราจะเห็นวันที่ที่สร้างขึ้นโดยใช้วิธีการของโรงงาน (ตัวสร้างทั้งหมดเป็นแบบส่วนตัว) ต่อไปเราจะขอข้อมูลบางอย่างจากวัตถุ โปรดทราบว่า การแจง นับเดือนและ วันสัปดาห์ได้รับการออกแบบมาเพื่อให้โค้ดสามารถอ่านและเชื่อถือได้มากขึ้น ในตัวอย่างต่อไปนี้ เราจะดูวิธีแก้ไขวันที่ เนื่องจากคลาสไม่เปลี่ยนรูป ผลลัพธ์จะเป็นอ็อบเจ็กต์ใหม่ แต่คลาสดั้งเดิมจะยังคงเหมือนเดิม LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.withYear(2015); // 2015-06-10 date = date.plusMonths(2); // 2015-08-10 date = date.minusDays(1); // 2015-08-09     สิ่งเหล่านี้เป็นการเปลี่ยนแปลงที่ค่อนข้างง่าย แต่บ่อยครั้งที่คุณต้องทำการแก้ไขวันที่ที่ซับซ้อนมากขึ้น มีกลไกพิเศษสำหรับสิ่งนี้ใน java.time API - TemporalAdjuster วัตถุประสงค์คือเพื่อให้มีเครื่องมือในตัวที่ช่วยให้คุณสามารถจัดการวันที่ได้ เช่น การรับวัตถุที่ตรงกับวันสุดท้ายของเดือน บางส่วนรวมอยู่ใน APIแต่คุณสามารถเพิ่มของคุณเองได้ การใช้ตัวแก้ไขนั้นง่ายมาก แต่ต้องมีการนำเข้าแบบคงที่: import static java.time.DayOfWeek.* import static java.time.temporal.TemporalAdjusters.* LocalDate date = LocalDate.of(2014, Month.JUNE, 10); date = date.with(lastDayOfMonth()); date = date.with(nextOrSame(WEDNESDAY));     การใช้ตัวแก้ไขจะทำให้โค้ดของคุณง่ายขึ้นอย่างมาก ไม่มีใครอยากเห็นการจัดการวันที่ด้วยตนเองมากนัก หากการบิดเบือนวันที่เกิดขึ้นหลายครั้งในโปรเจ็กต์ของคุณ ให้เขียนตัวแก้ไขของคุณเอง จากนั้นทีมของคุณจะสามารถใช้เป็นองค์ประกอบที่เขียนและทดสอบแล้วได้
เวลาและวันที่เป็นค่า
    คุ้มค่าที่จะใช้เวลาสักหน่อยเพื่อทำความเข้าใจว่าอะไรทำให้ LocalDateมีคุณค่า ค่าเป็นประเภทข้อมูลธรรมดาที่สามารถใช้แทนกันได้อย่างสมบูรณ์ เมื่อมีค่าเท่ากัน ตัวตนของวัตถุก็จะไม่มีความหมาย ตัวอย่างคลาสสิกของคลาสค่าคือ String เราเปรียบเทียบสตริงโดยใช้เท่ากับ ()และเราไม่สนใจว่าวัตถุจะเหมือนกันหรือไม่เมื่อเปรียบเทียบกับ ตัวดำเนินการ == คลาสส่วนใหญ่สำหรับการทำงานกับวันที่และเวลาก็เป็นค่าเช่นกัน ดังนั้นการเปรียบเทียบโดยใช้ ตัวดำเนินการ ==จึงเป็นความคิดที่ไม่ดี ดังที่ระบุไว้ในเอกสารประกอบ สำหรับผู้ที่สนใจเรียนรู้เพิ่มเติม โปรดดูคำจำกัดความล่าสุดของฉัน ของ VALJOsซึ่งสรุปชุดกฎที่เข้มงวดซึ่งให้ความสำคัญกับวัตถุใน Java จะต้องปฏิบัติตาม ซึ่งรวมถึงความไม่เปลี่ยนรูป วิธีการจากโรงงาน และคำจำกัดความที่เหมาะสมของเท่ากับ () , hashCode , toString()และ เปรียบเทียบถึง . () .
ปฏิทินทางเลือก
    คลาส LocalDateเช่นเดียวกับคลาสหลักทั้งหมดใน java.time จะถูก ผูกไว้กับปฏิทินเดียว ตามที่อธิบายไว้ใน มาตรฐาน ISO-8601 มาตรฐาน 8601 อธิบายปฏิทินมาตรฐานทั่วโลกหรือที่เรียกว่าปฏิทินเกรกอเรียน ปีมาตรฐานประกอบด้วย 365 วัน ปีอธิกสุรทิน - 366 ทุกๆ ปีที่สี่จะเป็นปีอธิกสุรทิน เว้นแต่จะหารด้วย 100 ลงตัวหรือหารด้วย 400 ลงตัว ปีก่อนปีแรกของศักราชใหม่จะถือเป็นศูนย์เพื่อให้ง่ายต่อการคำนวณ ผลที่ตามมา ประการแรกของระบบเริ่มต้นคือผลลัพธ์ไม่ตรงกับที่คำนวณโดยใช้ GregorianCalendar เสมอไป คลาส GregorianCalendarมีสวิตช์ในตัวเป็นระบบ Julian สำหรับทุกวันก่อนวันที่ 15 ตุลาคม 1582 ในระบบจูเลียน ทุกๆ ปีที่สี่จะเป็นปีอธิกสุรทิน โดยไม่มีข้อยกเว้น คำถามก็คือ เนื่องจากการเปลี่ยนจากระบบหนึ่งไปอีกระบบหนึ่งนั้นเป็นข้อเท็จจริงทางประวัติศาสตร์ ทำไม java.time จึงไม่ สร้างแบบจำลองมัน ใช่ เนื่องจากประเทศต่างๆ เปลี่ยนมาใช้ระบบเกรโกเรียนในเวลาที่ต่างกัน และเมื่อพิจารณาเฉพาะวันที่เปลี่ยนผ่านของวาติกัน เราจะได้รับข้อมูลที่ไม่ถูกต้องสำหรับประเทศอื่นๆ ส่วนใหญ่ ตัวอย่างเช่น จักรวรรดิอังกฤษ รวมทั้งอาณานิคมในอเมริกาเหนือ ได้เปลี่ยนมาใช้ปฏิทินเกรกอเรียนในวันที่ 14 กันยายน พ.ศ. 2295 หรือเกือบ 200 ปีต่อมา รัสเซียไม่เปลี่ยนปฏิทินจนกระทั่งวันที่ 14 กุมภาพันธ์ พ.ศ. 2461 และการเปลี่ยนแปลงของสวีเดนโดยทั่วไปมักเป็นเรื่องที่มืดมน ด้วยเหตุนี้ ความหมายที่แท้จริงของวันที่ก่อนปี 1918 จึงแตกต่างกันไปขึ้นอยู่กับสถานการณ์ ผู้เขียน โค้ด LocalDateได้ทำการตัดสินใจอย่างมีเหตุผลอย่างสมบูรณ์ที่จะไม่จำลองการเปลี่ยนจากปฏิทินจูเลียนไปเป็นปฏิทินเกรกอเรียนเลย เพื่อหลีกเลี่ยงความคลาดเคลื่อน ผลลัพธ์ประการที่สองของการใช้ ISO-8601เป็นปฏิทินเริ่มต้นในคลาสหลักทั้งหมดก็คือ จำเป็นต้องมีชุดคลาสเพิ่มเติมเพื่อจัดการปฏิทินที่เหลือ อิน เทอร์เฟซลำดับเหตุการณ์เป็นพื้นฐานสำหรับการทำงานกับปฏิทินทางเลือก ช่วยให้คุณสามารถค้นหาปฏิทินที่ต้องการตามชื่อสถานที่ได้ Java 8 มา พร้อมกับปฏิทินเพิ่มเติม 4 ปฏิทิน - ไทยพุทธ, หมิงกัว (ไต้หวัน), ญี่ปุ่น และอิสลาม ปฏิทินอื่นๆอาจมีโปรแกรมมาด้วย แต่ละปฏิทินมี ชั้นวันที่พิเศษ เช่น ThaiBuddhistDate , MinguoDate , JapaneseDateและ HijrahDate ควรใช้แอปพลิเคชันเหล่านี้ในแอปพลิเคชันที่มีการแปลเป็นภาษาท้องถิ่นอย่างมาก เช่น แอปพลิเคชันสำหรับรัฐบาลญี่ปุ่น อินเทอร์เฟซเพิ่มเติม ChronoLocalDateถูกใช้เป็นนามธรรมหลักของสี่คลาสด้านบนพร้อมกับ LocalDateซึ่งช่วยให้คุณเขียนโค้ดโดยไม่ขึ้นกับประเภทปฏิทินที่ใช้ แม้ว่านามธรรมนี้จะมีอยู่ แต่ก็ไม่แนะนำให้ใช้ การทำความเข้าใจว่าเหตุใดจึงไม่แนะนำให้ใช้นามธรรมนี้จึงเป็นสิ่งสำคัญในการทำความเข้าใจว่าjava.time API ทำงานอย่างไร บรรทัดล่างคือโค้ดส่วนใหญ่ที่เขียนโดยไม่มีการอ้างอิงถึงปฏิทินใดปฏิทินหนึ่งๆ กลับกลายเป็นว่าใช้งานไม่ได้ ตัวอย่างเช่น คุณไม่สามารถแน่ใจได้ว่าในหนึ่งปีมี 12 เดือน แต่นักพัฒนาซอฟต์แวร์บางรายบวก 12 เดือนและคิดว่าเพิ่มทั้งปี คุณไม่สามารถแน่ใจได้ว่าทุกเดือนมีจำนวนวันเท่ากันโดยประมาณ - ในปฏิทินคอปติกมี 12 เดือน 30 วัน และ 1 เดือนมี 5 หรือ 6 วัน อีกทั้งท่านไม่อาจแน่ใจได้ว่าจำนวนปีถัดไปจะมากกว่าปีปัจจุบัน 1 เพราะในปฏิทินญี่ปุ่นนับปีนับจากวันประกาศจักรพรรดิ์องค์ต่อไป (ในกรณีนี้คือ 2 วันของเดือนเดียวกันด้วยซ้ำ สามารถอยู่คนละปีได้) วิธีเดียวที่จะเขียนโค้ดคุณภาพสูงและใช้งานได้ซึ่งใช้งานได้กับหลายปฏิทินพร้อมกันคือแกนหลักของโค้ดของคุณซึ่งดำเนินการทั้งหมดตามวันที่และเวลานั้นจะต้องเขียนโดยใช้ปฏิทินมาตรฐาน และเฉพาะเมื่อป้อน/ส่งออกวันที่เท่านั้น ควรแปลงเป็นระบบปฏิทินอื่นหรือไม่ นั่นคือ ขอแนะนำให้ใช้ LocalDateสำหรับการจัดเก็บและการจัดการวันที่ทั้งหมดในแอปพลิเคชันของคุณ และเฉพาะเมื่อแปลวันที่อินพุตและเอาต์พุตเป็นภาษาท้องถิ่นเท่านั้น คุณควรใช้ ChronoLocalDateซึ่งโดยปกติจะได้มาจากคลาสปฏิทินที่เก็บไว้ในโปรไฟล์ผู้ใช้ จริงอยู่ที่แอปพลิเคชันส่วนใหญ่ไม่ต้องการการแปลเป็นภาษาท้องถิ่นที่จริงจังเช่นนี้ หากคุณต้องการคำอธิบายโดยละเอียดเพิ่มเติมเกี่ยวกับทุกสิ่งที่อธิบายไว้ในบทนี้ ยินดีต้อนรับสู่เอกสาร      ประกอบ ของ คลาส ChronoLocalDate ความต่อเนื่องของบทความ      บทความต้นฉบับ
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION