Java วันที่และเวลา
⚡ สรุปอย่างชาญฉลาด
Java การจัดการวันที่และเวลาเป็นการผสานรวมคลาส java.util.Date และ SimpleDateFormat แบบดั้งเดิมเข้ากับ API java.time ที่ทันสมัยซึ่งเปิดตัวในเวอร์ชันใหม่ Java 8. มอบประเภทข้อมูลที่ไม่เปลี่ยนแปลงและปลอดภัยต่อการทำงานแบบมัลติเธรดให้แก่นักพัฒนา เพื่อการทำงานปฏิทินที่แม่นยำ

การจัดการวันที่และเวลาใน Java การกำหนดวันที่เป็นส่วนหนึ่งของขั้นตอนการสร้างระบบการจัดตารางเวลา การบันทึกเวลา การสร้างรายงาน และการตรวจสอบประวัติการทำงาน ก่อนที่จะเขียนโค้ดใดๆ การรู้พารามิเตอร์ที่ประกอบขึ้นเป็นวันที่นั้นเป็นสิ่งสำคัญ:
- การขอ ปี (เป็นตัวเลขสองหรือสี่หลัก)
- การขอ เดือน (อาจเป็นตัวเลขสองหลัก ตัวอักษรสามตัวแรกของเดือน หรือชื่อเดือนเต็ม)
- การขอ ข้อมูล (หมายเลขวันในเดือนจริง)
- การขอ วัน (ชื่อวันในวันที่กำหนด เช่น อาทิตย์ จันทร์ อังคาร)
Java โปรแกรมนี้แสดงพารามิเตอร์อื่นๆ อีกมากมายที่ใช้อธิบายช่วงเวลาบนไทม์ไลน์ รวมถึงยุคสมัย สัปดาห์ในรอบปี เขตเวลา และค่าชดเชย ส่วนต่างๆ ด้านล่างจะกล่าวถึงแต่ละพารามิเตอร์พร้อมตัวอย่างที่สามารถใช้งานได้จริง
แสดงวันที่ใน Java
Java ให้ Date ชั้นเรียนใน java.util แพ็กเกจนี้ คลาสจะจัดเก็บช่วงเวลาที่เฉพาะเจาะจงด้วยความแม่นยำระดับมิลลิวินาที และมีเมธอดช่วยในการพิมพ์ เปรียบเทียบ และจัดรูปแบบช่วงเวลานั้น หากต้องการรับวันที่และเวลาปัจจุบัน ให้สร้างอินสแตนซ์ของคลาสโดยใช้คอนสตรัคเตอร์เริ่มต้น:
import java.util.Date; class Date_Ex1 { public static void main(String args[]) { // Instantiate a Date object by invoking its constructor Date objDate = new Date(); // Display the Date and Time using toString() System.out.println(objDate.toString()); } }
Output:
Wed Nov 29 06:36:22 UTC 2017
ตัวอย่างนี้แสดงวันที่ในรูปแบบ toString ตามค่าเริ่มต้น หากต้องการแสดงเวลาเดียวกันในรูปแบบอื่น คุณต้องเข้าใจตัวอักษรการจัดรูปแบบก่อน Java การใช้งาน
SimpleDateFormat: แยกวิเคราะห์และจัดรูปแบบวันที่
การขอ SimpleDateFormat ชั้นเรียนใน java.text แปลง Date แปลงอ็อบเจ็กต์เป็นสตริงที่มีรูปแบบ และแปลงสตริงที่มีรูปแบบนั้นกลับเป็นอ็อบเจ็กต์อีกครั้ง Dateระบบนี้ใช้ตัวอักษรรูปแบบที่เชื่อมโยงกับส่วนประกอบของวันที่หรือเวลา ตารางด้านล่างแสดงรายการตัวอักษรที่รองรับทั้งหมด:
| จดหมาย | ส่วนประกอบวันที่หรือเวลา | ตัวอย่าง |
|---|---|---|
| G | ผู้กำหนดยุคสมัย | AD |
| y | ปี | 2026 |
| M | เดือนในปี | กรกฎาคม หรือ กรกฎาคม หรือ 07 |
| w | สัปดาห์ในปี | 27 |
| W | สัปดาห์ในเดือน | 2 |
| D | วันในปี | 189 |
| d | วันในเดือน | 10 |
| F | วันในสัปดาห์ในเดือน | 2 |
| E | ชื่อวันในสัปดาห์ | วันอังคารหรืออังคาร |
| u | จำนวนวันของสัปดาห์ (1 = Monday, 7 = วันอาทิตย์) | 1 |
| a | เครื่องหมาย AM หรือ PM | PM |
| H | ชั่วโมงต่อวัน (0-23) | 0 |
| k | ชั่วโมงต่อวัน (1-24) | 24 |
| K | ชั่วโมง (เช้าหรือบ่าย) (0-11) | 0 |
| h | ชั่วโมง (เช้าหรือบ่าย) (1-12) | 12 |
| m | นาทีต่อชั่วโมง | 30 |
| s | วินาทีในนาที | 55 |
| S | มิลลิวินาที | 978 |
| z | เขตเวลา (ชื่อ) | เวลามาตรฐานแปซิฟิก; PST; GMT-08:00 |
| Z | เขตเวลา (ค่าชดเชย RFC 822) | -0800 |
| X | เขตเวลา (ค่าชดเชย ISO 8601) | -08 หรือ -0800 หรือ -08:00 น |
คุณไม่จำเป็นต้องจำตารางทั้งหมด ให้ดูตารางนี้ทุกครั้งที่คุณสร้างแพทเทิร์นใหม่
วิธีใช้งาน SimpleDateFormat
SimpleDateFormat เป็นคลาสย่อยของ DateFormat ซึ่งช่วยให้คุณจัดรูปแบบและแยกวิเคราะห์วันที่โดยใช้ตัวอักษรตามรูปแบบด้านบน รวมตัวอักษรเข้าด้วยกันเพื่อสร้างหรืออ่านข้อความที่ต้องการได้อย่างแม่นยำ
ตัวอย่างเช่น:
- ต้องระบุรูปแบบวันที่: 2012.10.23 น. 20 20:45:XNUMX น. ตามเวลาแปซิฟิกรูปแบบที่เหมาะสมคือ
yyyy.MM.dd HH:mm:ss zzz. - ต้องระบุรูปแบบวันที่: 09:30:00 AM 23-May-2012รูปแบบที่เหมาะสมคือ
hh:mm:ss a dd-MMM-yyyy.
เคล็ดลับ: ดูตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก M คือเดือน ตัวพิมพ์เล็ก m เล็กมาก ตัวพิมพ์ใหญ่ H เป็นนาฬิกา 24 ชั่วโมง ตัวพิมพ์เล็ก h เป็นนาฬิกา 12 ชั่วโมง การสลับเวลาจะทำให้เกิดผลลัพธ์ที่ผิดพลาดโดยไม่มีการแจ้งเตือน
โปรแกรมด้านล่างนี้จะพิมพ์วันที่ปัจจุบันสองครั้ง ครั้งแรกในรูปแบบมาตรฐาน และครั้งที่สองโดยใช้รูปแบบ SimpleDateFormat:
import java.text.SimpleDateFormat; import java.util.Date; class TestDates_Format { public static void main(String args[]) { // Current system date and time is assigned to objDate Date objDate = new Date(); System.out.println(objDate); // Build the target pattern and format the date String strDateFormat = "hh:mm:ss a dd-MMM-yyyy"; SimpleDateFormat objSDF = new SimpleDateFormat(strDateFormat); System.out.println(objSDF.format(objDate)); } }
Output:
Wed Nov 29 06:31:41 UTC 2017 06:31:41 AM 29-Nov-2017
ตัวอย่างการเปรียบเทียบวันที่
วิธีที่น่าเชื่อถือที่สุดในการสั่งซื้อสองชิ้น Date วัตถุคือ compareTo() เมธอดนี้จะคืนค่าจำนวนเต็มลบเมื่อเวลาของผู้เรียกใช้มาก่อน ค่าศูนย์เมื่อเวลาทั้งสองเท่ากัน และค่าจำนวนเต็มบวกเมื่อเวลาของผู้เรียกใช้มาทีหลัง โค้ดด้านล่างนี้จะแยกวิเคราะห์สตริงวันที่สองสตริงและพิมพ์ลำดับสัมพัทธ์ของวันที่เหล่านั้น:
import java.text.SimpleDateFormat; import java.text.ParseException; import java.util.Date; class TestDates_Compare { public static void main(String args[]) throws ParseException { SimpleDateFormat objSDF = new SimpleDateFormat("dd-MM-yyyy"); Date dt_1 = objSDF.parse("20-08-1981"); Date dt_2 = objSDF.parse("12-10-2012"); System.out.println("Date1 : " + objSDF.format(dt_1)); System.out.println("Date2 : " + objSDF.format(dt_2)); // compareTo returns > 0 when dt_1 is after dt_2 if (dt_1.compareTo(dt_2) > 0) { System.out.println("Date 1 occurs after Date 2"); } // compareTo returns < 0 when dt_1 is before dt_2 else if (dt_1.compareTo(dt_2) < 0) { System.out.println("Date 1 occurs before Date 2"); } // compareTo returns 0 when both dates are equal else { System.out.println("Both are the same date"); } } }
Output:
Date1 : 20-08-1981 Date2 : 12-10-2012 Date 1 occurs before Date 2
หมายเหตุ โค้ดต้นฉบับใช้รูปแบบดังกล่าว dd-mm-yyyyตัวพิมพ์เล็ก mm ตัวอักษรคือนาที ไม่ใช่เดือน ดังนั้นตัวแยกวิเคราะห์จึงแสดงค่าเดือนที่ไม่ถูกต้องโดยไม่แจ้งให้ทราบ การแก้ไขข้างต้นใช้ตัวพิมพ์ใหญ่ MM สำหรับเดือนนั้น ตัวอักษรใดคือแบบแผนที่ถูกต้อง
Java 8. API วันที่และเวลาสมัยใหม่ (java.time)
Java 8 ได้แนะนำ java.time แพ็กเกจนี้คือ API ที่ได้รับการออกแบบใหม่ โดยได้รับแรงบันดาลใจจากไลบรารี Joda-Time คลาสใหม่เหล่านี้เป็นแบบไม่เปลี่ยนแปลง (immutable) ปลอดภัยต่อการทำงานแบบมัลติเธรด (thread-safe) และแยกปฏิทินของมนุษย์ออกจากไทม์ไลน์ของเครื่อง ประเภทที่พบบ่อยที่สุด ได้แก่:
LocalDateสำหรับวันนัดหมายที่ไม่ได้ระบุเวลาหรือเขตเวลา (เช่น วันเกิด)LocalTimeสำหรับเวลาที่แสดงบนนาฬิกาติดผนังโดยไม่มีวันที่หรือโซนเวลาLocalDateTimeสำหรับวันที่และเวลาที่ไม่ระบุโซนเวลาZonedDateTimeสำหรับวันที่และเวลาที่ระบุเขตเวลาที่แน่นอนOffsetDateTimeสำหรับวันที่และเวลาที่มีค่าชดเชย UTC แต่ไม่มีชื่อโซนเวลาInstantสำหรับการประทับเวลาของเครื่องที่วัดจากยุค UNIXDurationและPeriodสำหรับจำนวนเงินที่คำนวณตามเวลาและวันที่
ตัวอย่างด้านล่างนี้แสดงวันที่ปัจจุบัน เวลา เวลาประทับ และเขตเวลา โดยใช้ API รุ่นใหม่:
import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.time.Instant; import java.time.ZoneId; class ModernDateDemo { public static void main(String args[]) { LocalDate today = LocalDate.now(); LocalDateTime now = LocalDateTime.now(); ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Asia/Kolkata")); Instant epoch = Instant.now(); System.out.println("LocalDate : " + today); System.out.println("LocalDateTime : " + now); System.out.println("ZonedDateTime : " + zoned); System.out.println("Instant : " + epoch); } }
แต่ละประเภทมีวิธีการผลิตในโรงงาน (now, of, parse) และการดำเนินการที่ไม่สามารถเปลี่ยนแปลงได้ (plusDays, minusHours, withYear) ซึ่งจะส่งคืนค่าใหม่แทนที่จะเปลี่ยนแปลงอ็อบเจ็กต์เดิม
DateTimeFormatter: จัดรูปแบบวันที่ในรูปแบบสมัยใหม่ Java
DateTimeFormatter in java.time.format แทนที่ SimpleDateFormatมันใช้รูปแบบตัวอักษรแบบเดียวกัน ไม่สามารถเปลี่ยนแปลงได้ และปลอดภัยที่จะแชร์ข้ามเธรดโดยไม่ต้องซิงโครไนซ์เพิ่มเติม คลาสนี้ยังเปิดเผยค่าคงที่สำเร็จรูป เช่น ISO_LOCAL_DATE และ ISO_ZONED_DATE_TIME สำหรับรูปแบบมาตรฐาน
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; class FormatterDemo { public static void main(String args[]) { LocalDateTime now = LocalDateTime.now(); DateTimeFormatter iso = DateTimeFormatter.ISO_LOCAL_DATE_TIME; DateTimeFormatter human = DateTimeFormatter.ofPattern("hh:mm:ss a dd-MMM-yyyy"); System.out.println(now.format(iso)); System.out.println(now.format(human)); LocalDateTime parsed = LocalDateTime.parse("2026-07-04T09:30:00", iso); System.out.println("Parsed back : " + parsed); } }
ในการเปรียบเทียบวันที่สองวันใน API รุ่นใหม่ ให้เรียกใช้คำสั่งต่อไปนี้ isBefore, isAfterหรือ isEqualวิธีการเหล่านี้อ่านเข้าใจง่ายกว่า compareTo และทำงานร่วมกับทุกๆ java.time ชั้นเรียน
ความปลอดภัยของเกลียวและแนวปฏิบัติที่ดีที่สุดสำหรับ Java วันที่และเวลา
ทั้งสอง java.util.Date และ SimpleDateFormat มาก่อนยุคปัจจุบัน Javaและแต่ละวิธีก็มีข้อเสียที่ทราบกันดีอยู่แล้ว ปฏิบัติตามแนวทางด้านล่างนี้เพื่อให้การจัดการข้อมูลในโค้ดที่ใช้งานจริงถูกต้อง:
- ควรเลือกใช้ java.time แทน Date และ Calendar ประเภทข้อมูลใหม่เหล่านี้ไม่สามารถเปลี่ยนแปลงได้ ปลอดภัยต่อการใช้งานแบบมัลติเธรด และจำลองโดเมนได้อย่างแม่นยำยิ่งขึ้น (เช่น วันที่โดยไม่มีเวลา เวลาโดยไม่มีโซนเวลา เป็นต้น)
- ห้ามใช้ SimpleDateFormat ร่วมกันในเธรดต่างๆ คลาสนี้เก็บสถานะการแยกวิเคราะห์ภายในและไม่ปลอดภัยต่อการใช้งานแบบมัลติเธรด ควรห่อหุ้มไว้ใน
ThreadLocalซิงโครไนซ์บนอินสแตนซ์ หรือเปลี่ยนไปใช้DateTimeFormatter. - ระบุภาษาท้องถิ่นเสมอ ชื่อเดือนและวันจะเปลี่ยนแปลงไปตามการตั้งค่าภาษาเริ่มต้นของ JVM ซึ่งทำให้รูปแบบต่างๆ เช่น
MMMและEEEไม่สามารถพกพาได้ ต้องระบุภาษาอย่างชัดเจน (ตัวอย่างเช่นLocale.ENGLISH). - ระบุเขตเวลาให้ชัดเจน
LocalDateTimeไม่มีโซน ดังนั้นแปลงเป็นZonedDateTimeorInstantเมื่อใดก็ตามที่จังหวะเวลาที่แน่นอนมีความสำคัญ โดยเฉพาะอย่างยิ่งสำหรับบันทึกข้อมูล คอลัมน์ฐานข้อมูล และข้อมูลที่ส่งผ่านเครือข่าย - ควรแปลงข้อมูลระหว่าง API ทั้งสองอย่างระมัดระวัง ใช้
date.toInstant(),Date.from(instant)และcalendar.toInstant().atZone(zone)ตรงรอยต่อระหว่างโค้ดเก่าและโค้ดใหม่ - บันทึกเวลาในรูปแบบ UTC อดทนและ transmit วันที่ในรูปแบบ UTC (an)
Instantหรือสตริง ISO 8601) และแปลงเป็นโซนผู้ใช้เฉพาะเมื่อแสดงผลเท่านั้น


