Java Ngày và Giờ
⚡ Tóm tắt thông minh
Java Việc xử lý ngày và giờ kết hợp các lớp java.util.Date và SimpleDateFormat cũ với API java.time hiện đại được giới thiệu trong Java 8, cung cấp cho các nhà phát triển các kiểu dữ liệu bất biến, an toàn cho đa luồng để thực hiện công việc lập lịch chính xác.

Xử lý ngày và giờ trong Java Đây là một phần thường xuyên trong việc xây dựng logic lập lịch, ghi nhật ký thời gian, báo cáo và nhật ký kiểm toán. Trước khi viết bất kỳ đoạn mã nào, việc nắm rõ các tham số tạo nên một ngày tháng là rất hữu ích:
- năm (hai hoặc bốn chữ số).
- tháng (dưới dạng hai chữ số, ba chữ cái đầu tiên của tháng, hoặc toàn bộ tên tháng).
- ngày (số ngày cụ thể trong tháng).
- ngày (Tên ngày trong tuần, ví dụ như Chủ Nhật, Thứ Hai, Thứ Ba).
Java Nó hiển thị nhiều tham số khác mô tả một thời điểm trên dòng thời gian, bao gồm kỷ nguyên, tuần trong năm, múi giờ và độ lệch. Các phần bên dưới sẽ trình bày chi tiết từng tham số với các ví dụ minh họa.
Ngày hiển thị trong Java
Java cung cấp một Date lớp học trong java.util Gói này lưu trữ một thời điểm cụ thể với độ chính xác đến từng mili giây và cung cấp các phương thức hỗ trợ để in, so sánh và định dạng thời điểm đó. Để lấy ngày giờ hiện tại, hãy khởi tạo lớp bằng hàm tạo mặc định của nó:
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()); } }
Đầu ra:
Wed Nov 29 06:36:22 UTC 2017
Ví dụ này in ngày tháng theo định dạng toString mặc định. Để hiển thị cùng một thời điểm theo định dạng khác, trước tiên bạn cần hiểu các ký tự định dạng. Java sử dụng.
SimpleDateFormat: Phân tích và định dạng ngày tháng
SimpleDateFormat lớp trong java.text chuyển đổi một Date Chuyển đổi đối tượng thành chuỗi được định dạng và phân tích chuỗi được định dạng đó trở lại thành một DateNó sử dụng các chữ cái mẫu tương ứng với thành phần ngày hoặc giờ. Bảng dưới đây liệt kê tất cả các chữ cái được hỗ trợ:
| Bức thư | Thành phần ngày hoặc giờ | Ví dụ |
|---|---|---|
| G | Người chỉ định thời đại | AD |
| y | Năm | 2026 |
| M | Tháng trong năm | Tháng 07 hoặc tháng XNUMX hoặc XNUMX |
| w | Tuần trong năm | 27 |
| W | Tuần trong tháng | 2 |
| D | Ngày trong năm | 189 |
| d | Ngày trong tháng | 10 |
| F | Ngày trong tuần trong tháng | 2 |
| E | Tên ngày trong tuần | Thứ ba hoặc thứ ba |
| u | Số ngày trong tuần (1 = Monday, 7 = Chủ nhật) | 1 |
| a | Dấu hiệu AM hoặc PM | PM |
| H | Giờ trong ngày (0-23) | 0 |
| k | Giờ trong ngày (1-24) | 24 |
| K | Giờ sáng hoặc chiều (0-11) | 0 |
| h | Giờ sáng hoặc chiều (1-12) | 12 |
| m | Phút trong giờ | 30 |
| s | Thứ hai trong phút | 55 |
| S | Mili giây | 978 |
| z | Múi giờ (tên) | Múi giờ Thái Bình Dương; PST; GMT-08:00 |
| Z | Múi giờ (độ lệch RFC 822) | -0800 |
| X | Múi giờ (độ lệch ISO 8601) | -08 hoặc -0800 hoặc -08:00 |
Bạn không cần phải nhớ toàn bộ bảng. Hãy tham khảo nó mỗi khi bạn tạo một mẫu mới.
Cách sử dụng SimpleDateFormat
SimpleDateFormat là một lớp con của DateFormat Công cụ này cho phép bạn định dạng và phân tích cú pháp ngày tháng bằng cách sử dụng các chữ cái mẫu ở trên. Kết hợp các chữ cái để mô tả chính xác chuỗi bạn muốn tạo ra hoặc đọc.
Ví dụ:
- Định dạng ngày tháng bắt buộc: 2012.10.23/20/20 45:XNUMX:XNUMX giờ chuẩn Thái Bình DươngMẫu định dạng phù hợp là...
yyyy.MM.dd HH:mm:ss zzz. - Định dạng ngày tháng bắt buộc: 09:30:00 AM 23-May-2012Mẫu định dạng phù hợp là...
hh:mm:ss a dd-MMM-yyyy.
Mẹo: Xem chữ viết hoa. M là tháng, chữ thường m rất nhỏ. Chữ in hoa H là đồng hồ 24 giờ, chữ thường h Đây là đồng hồ 12 giờ. Việc nhầm lẫn giữa chúng sẽ dẫn đến kết quả sai mà không gây ra tác dụng phụ nào.
Chương trình dưới đây in ngày tháng hiện tại hai lần, một lần theo định dạng mặc định và một lần theo mẫu 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)); } }
Đầu ra:
Wed Nov 29 06:31:41 UTC 2017 06:31:41 AM 29-Nov-2017
So sánh ngày Ví dụ
Cách đáng tin cậy nhất để đặt hai cái Date các đối tượng là compareTo() Phương thức này trả về một số nguyên âm khi người gọi ở thời điểm sớm hơn, số 0 khi cả hai thời điểm bằng nhau và một số nguyên dương khi người gọi ở thời điểm muộn hơn. Đoạn mã bên dưới phân tích hai chuỗi ngày tháng và in ra thứ tự tương đối của chúng:
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"); } } }
Đầu ra:
Date1 : 20-08-1981 Date2 : 12-10-2012 Date 1 occurs before Date 2
Lưu ý: Mã gốc sử dụng mẫu dd-mm-yyyy. Chữ thường mm Chữ cái biểu thị phút, không phải tháng, vì vậy trình phân tích cú pháp đã âm thầm tạo ra giá trị tháng sai. Cách khắc phục ở trên sử dụng chữ hoa. MM Đối với tháng, đó là chữ cái theo mẫu chính xác.
Java 8. API ngày giờ hiện đại (java.time)
Java 8 đã giới thiệu java.time Gói này là một API được thiết kế lại, lấy cảm hứng từ thư viện Joda-Time. Các lớp mới là bất biến, an toàn cho đa luồng và tách biệt lịch của con người khỏi dòng thời gian của máy móc. Các kiểu dữ liệu phổ biến nhất là:
LocalDateDùng cho ngày tháng không có giờ hoặc múi giờ (ví dụ: ngày sinh nhật).LocalTimeDùng để hiển thị giờ trên đồng hồ treo tường mà không có ngày tháng hoặc múi giờ.LocalDateTimeĐối với ngày và giờ không có múi giờ.ZonedDateTimeCho một ngày và giờ cụ thể với múi giờ nhất định.OffsetDateTimeĐối với ngày và giờ có độ lệch UTC nhưng không có múi giờ cụ thể.Instantđối với dấu thời gian của máy được đo từ thời điểm bắt đầu kỷ nguyên UNIX.DurationvàPeriodĐối với các khoản tiền tính theo thời gian và theo ngày.
Ví dụ dưới đây in ra ngày, giờ, dấu thời gian và múi giờ hiện tại bằng cách sử dụng API hiện đại:
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); } }
Mỗi loại đều có các phương thức tạo (now, of, parse) và các thao tác bất biến (plusDays, minusHours, withYear) trả về một giá trị mới thay vì làm thay đổi đối tượng gốc.
DateTimeFormatter: Định dạng ngày tháng theo cách hiện đại Java
DateTimeFormatter in java.time.format thay thế SimpleDateFormatNó sử dụng cùng một kiểu chữ cái mẫu, không thể thay đổi và an toàn khi chia sẻ giữa các luồng mà không cần đồng bộ hóa bổ sung. Lớp này cũng cung cấp các hằng số có sẵn như... ISO_LOCAL_DATE và ISO_ZONED_DATE_TIME cho các định dạng tiêu chuẩn.
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); } }
Để so sánh hai ngày trong API hiện đại, hãy gọi isBefore, isAfter, hoặc là isEqualCác phương pháp này dễ hiểu hơn compareTo và làm việc với mọi người java.time lớp học.
An toàn khi sử dụng ren và các biện pháp tốt nhất Java Ngày và Giờ
Cả hai java.util.Date và SimpleDateFormat có trước thời kỳ đồng thời hiện đại JavaMỗi phương pháp đều có những nhược điểm riêng. Hãy tuân thủ các quy tắc dưới đây để đảm bảo việc xử lý ngày tháng chính xác trong mã nguồn sản xuất:
- Nên ưu tiên sử dụng java.time hơn Date và Calendar. Các kiểu dữ liệu mới này là bất biến và an toàn cho đa luồng, đồng thời mô hình hóa miền dữ liệu chính xác hơn (ngày tháng không có giờ, giờ không có múi giờ, v.v.).
- Không nên dùng chung một SimpleDateFormat giữa các luồng. Lớp này lưu trữ trạng thái phân tích cú pháp nội bộ và không an toàn cho đa luồng. Hãy bọc nó trong một lớp khác.
ThreadLocal, đồng bộ hóa trên phiên bản hoặc chuyển sangDateTimeFormatter. - Luôn luôn chỉ định Ngôn ngữ/Vùng miền (Locale). Tên tháng và ngày thay đổi theo ngôn ngữ mặc định của JVM, điều này tạo ra các mẫu như sau:
MMMvàEEEKhông tương thích đa nền tảng. Hãy truyền rõ ràng ngôn ngữ địa phương (ví dụ:Locale.ENGLISH). - Hãy nêu rõ múi giờ.
LocalDateTimekhông có vùng, vì vậy hãy chuyển đổi thànhZonedDateTimeorInstantKhi thời điểm chính xác là rất quan trọng, đặc biệt là đối với nhật ký, cột cơ sở dữ liệu và tải trọng mạng. - Hãy chuyển đổi giữa hai API một cách cẩn thận. Sử dụng
date.toInstant(),Date.from(instant)vàcalendar.toInstant().atZone(zone)tại ranh giới giữa mã nguồn cũ và mã nguồn hiện đại. - Lưu trữ dấu thời gian theo múi giờ UTC. Kiên trì và transmit ngày tháng dưới dạng UTC (một
Instanthoặc một chuỗi ISO 8601) và chỉ chuyển đổi sang vùng người dùng khi hiển thị.


