tl; dr
Phần mềm phân tích cú pháp từ một múi giờ Chuỗi không được chỉ định. Tôi muốn đặt múi giờ cụ thể
LocalDateTime.parse( "2018-01-23T01:23:45.123456789" ) // Parse string, lacking an offset-from-UTC and lacking a time zone, as a `LocalDateTime`.
.atZone( ZoneId.of( "Africa/Tunis" ) ) // Assign the time zone for which you are certain this date-time was intended. Instantiates a `ZonedDateTime` object.
Không có múi giờ trong juDate
Như câu trả lời đúng khác tuyên bố, một java.util.Date không có múi giờ † . Nó đại diện cho UTC / GMT (không có bù múi giờ). Rất khó hiểu vì toString
phương thức của nó áp dụng múi giờ mặc định của JVM khi tạo biểu diễn Chuỗi.
Tránh juDate
Vì lý do này và nhiều lý do khác, bạn nên tránh sử dụng java.util.Date & .CalWiki & java.text.SimpleDateFormat tích hợp. Họ nổi tiếng là rắc rối.
Thay vào đó, hãy sử dụng gói java.time đi kèm với Java 8 .
java.time
Các lớp java.time có thể biểu thị một khoảnh khắc trên dòng thời gian theo ba cách:
- UTC (
Instant
)
- Với phần bù (
OffsetDateTime
có ZoneOffset
)
- Với múi giờ (
ZonedDateTime
với ZoneId
)
Instant
Trong java.time , khối xây dựng cơ bản là Instant
một khoảnh khắc trên dòng thời gian trong UTC. Sử dụng Instant
các đối tượng cho phần lớn logic kinh doanh của bạn.
Instant instant = Instant.now();
OffsetDateTime
Áp dụng offset-từ-UTC để điều chỉnh thời gian đồng hồ treo tường của một số địa phương .
Áp dụng một ZoneOffset
để có được một OffsetDateTime
.
ZoneOffset zoneOffset = ZoneOffset.of( "-04:00" );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );
ZonedDateTime
Tốt hơn là áp dụng múi giờ , bù trừ cộng với các quy tắc để xử lý các bất thường như Giờ tiết kiệm ánh sáng ban ngày (DST) .
Áp dụng một ZoneId
một Instant
để có được mộtZonedDateTime
. Luôn chỉ định một tên múi giờ thích hợp . Không bao giờ sử dụng 3-4 chữ viết tắt như EST
hoặc IST
không độc đáo cũng không được tiêu chuẩn hóa.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
LocalDateTime
Nếu chuỗi đầu vào thiếu bất kỳ chỉ báo nào về offset hoặc vùng, hãy phân tích thành a LocalDateTime
.
Nếu bạn chắc chắn về múi giờ dự định, chỉ định a ZoneId
để sản xuất a ZonedDateTime
. Xem ví dụ mã ở trên trong phần tl; dr ở trên cùng.
Chuỗi định dạng
Gọi toString
phương thức trên bất kỳ lớp nào trong ba lớp này để tạo Chuỗi biểu thị giá trị thời gian theo định dạng ISO 8601 tiêu chuẩn . Các ZonedDateTime
lớp mở rộng định dạng chuẩn bằng cách thêm tên của múi giờ trong ngoặc đơn.
String outputInstant = instant.toString(); // Ex: 2011-12-03T10:15:30Z
String outputOdt = odt.toString(); // Ex: 2007-12-03T10:15:30+01:00
String outputZdt = zdt.toString(); // Ex: 2007-12-03T10:15:30+01:00[Europe/Paris]
Đối với các định dạng khác sử dụng DateTimeFormatter
lớp. Nói chung, tốt nhất để cho lớp đó tạo các định dạng cục bộ bằng cách sử dụng các chuẩn mực văn hóa và ngôn ngữ của con người. Hoặc bạn có thể chỉ định một định dạng cụ thể.
Giới thiệu về java.time
Các java.time khung được xây dựng vào Java 8 và sau đó. Các lớp này thay thế các lớp thời gian cũ kế thừa rắc rối như java.util.Date
,Calendar
, & SimpleDateFormat
.
Các Joda thời gian dự án, bây giờ trong chế độ bảo trì , khuyên chuyển đổi sang các java.time lớp.
Để tìm hiểu thêm, hãy xem Hướng dẫn của Oracle . Và tìm kiếm Stack Overflow cho nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310 .
Bạn có thể trao đổi các đối tượng java.time trực tiếp với cơ sở dữ liệu của bạn. Sử dụng trình điều khiển JDBC tương thích với JDBC 4.2 trở lên. Không cần chuỗi, không cần java.sql.*
lớp.
Nơi để có được các lớp java.time?
Các ThreeTen-Extra dự án mở rộng java.time với các lớp bổ sung. Dự án này là một nền tảng chứng minh cho các bổ sung có thể trong tương lai cho java.time. Bạn có thể tìm thấy một số các lớp học hữu ích ở đây chẳng hạn như Interval
, YearWeek
, YearQuarter
, và nhiều hơn nữa .
Joda-Thời gian
Trong khi Joda-Time vẫn được duy trì tích cực, các nhà sản xuất của nó đã bảo chúng tôi chuyển sang java.time ngay khi thuận tiện. Tôi để phần này nguyên vẹn như một tài liệu tham khảo, nhưng tôi đề nghị sử dụng java.time
phần trên thay thế.
Trong Joda-Time , một đối tượng thời gian ( DateTime
) thực sự biết múi giờ được chỉ định của nó. Điều đó có nghĩa là sự bù đắp từ UTC và các quy tắc và lịch sử của Giờ tiết kiệm ánh sáng ban ngày (DST) của múi giờ đó và các dị thường khác.
String input = "2014-01-02T03:04:05";
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( input, timeZone );
DateTime dateTimeUtcGmt = dateTimeIndia.withZone( DateTimeZone.UTC );
Gọi toString
phương thức để tạo Chuỗi theo định dạng ISO 8601 .
String output = dateTimeIndia.toString();
Joda-Time cũng cung cấp các khả năng phong phú để tạo tất cả các loại định dạng Chuỗi khác.
Nếu được yêu cầu, bạn có thể chuyển đổi từ Joda-Time DateTime sang java.util.Date.
Java.util.Date date = dateTimeIndia.toDate();
Tìm kiếm StackOverflow cho "ngày joda" để tìm thêm nhiều ví dụ, một số khá chi tiết.
† Trên thực tế có là một múi giờ nhúng trong một java.util.Date, được sử dụng cho một số chức năng nội bộ (xem bình luận trên trả lời này). Nhưng múi giờ nội bộ này không được hiển thị như một tài sản và không thể được đặt. Múi giờ nội bộ này không phải là múi giờ được sử dụng bởi toString
phương thức trong việc tạo biểu diễn chuỗi của giá trị thời gian ngày; thay vào đó, múi giờ mặc định hiện tại của JVM được áp dụng nhanh chóng. Vì vậy, như cách viết tắt, chúng ta thường nói là ju juDate không có múi giờ. Gây nhầm lẫn? Đúng. Một lý do khác để tránh những lớp học cũ mệt mỏi.