tl; dr
Có cách nào, bằng mã hoặc với các đối số JVM, để ghi đè thời gian hiện tại, như được trình bày qua System.civerseTimeMillis, ngoài việc thay đổi thủ công đồng hồ hệ thống trên máy chủ không?
Đúng.
Instant.now(
Clock.fixed(
Instant.parse( "2016-01-23T12:34:56Z"), ZoneOffset.UTC
)
)
Clock
Trong java.time
Chúng tôi có một giải pháp mới cho vấn đề thay thế đồng hồ có thể cắm để tạo điều kiện kiểm tra với các giá trị ngày giờ giả . Các gói java.time trong Java 8 bao gồm một lớp trừu tượng java.time.Clock
, với một mục đích rõ ràng:
để cho phép đồng hồ thay thế được cắm vào và khi cần thiết
Bạn có thể tự mình thực hiện Clock
, mặc dù bạn có thể tìm thấy một cái đã được thực hiện để đáp ứng nhu cầu của bạn. Để thuận tiện cho bạn, java.time bao gồm các phương thức tĩnh để mang lại các triển khai đặc biệt. Những triển khai thay thế này có thể có giá trị trong quá trình thử nghiệm.
Thay đổi nhịp
Các tick…
phương pháp khác nhau tạo ra đồng hồ làm tăng thời điểm hiện tại với một nhịp khác nhau.
Mặc định Clock
báo cáo thời gian được cập nhật thường xuyên như mili giây trong Java 8 và trong Java 9 tốt như nano giây (tùy thuộc vào phần cứng của bạn). Bạn có thể yêu cầu thời điểm hiện tại thực sự được báo cáo với độ chi tiết khác nhau.
Đồng hồ sai
Một số đồng hồ có thể nói dối, tạo ra kết quả khác với đồng hồ phần cứng của hệ điều hành chủ.
fixed
- Báo cáo một khoảnh khắc không thay đổi (không tăng) như thời điểm hiện tại.
offset
- Báo cáo thời điểm hiện tại nhưng thay đổi bởi các Duration
đối số được thông qua .
Ví dụ, khóa trong khoảnh khắc đầu tiên của Giáng sinh sớm nhất trong năm nay. nói cách khác, khi ông già Noel và tuần lộc của mình dừng chân đầu tiên . Múi giờ sớm nhất hiện nay dường như là Pacific/Kiritimati
tại +14:00
.
LocalDate ld = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate xmasThisYear = MonthDay.of( Month.DECEMBER , 25 ).atYear( ld.getYear() );
ZoneId earliestXmasZone = ZoneId.of( "Pacific/Kiritimati" ) ;
ZonedDateTime zdtEarliestXmasThisYear = xmasThisYear.atStartOfDay( earliestXmasZone );
Instant instantEarliestXmasThisYear = zdtEarliestXmasThisYear.toInstant();
Clock clockEarliestXmasThisYear = Clock.fixed( instantEarliestXmasThisYear , earliestXmasZone );
Sử dụng đồng hồ cố định đặc biệt đó để luôn luôn trả lại cùng một thời điểm. Chúng tôi có được khoảnh khắc đầu tiên của ngày Giáng sinh ở Kiritimati , với UTC hiển thị thời gian đồng hồ treo tường là mười bốn giờ trước đó, 10 giờ sáng vào ngày trước của ngày 24 tháng 12.
Instant instant = Instant.now( clockEarliestXmasThisYear );
ZonedDateTime zdt = ZonedDateTime.now( clockEarliestXmasThisYear );
tức thì.toString (): 2016-12-24T10: 00: 00Z
zdt.toString (): 2016-12-25T00: 00 + 14: 00 [Thái Bình Dương / Kiritimati]
Xem mã trực tiếp trong IdeOne.com .
Đúng giờ, múi giờ khác
Bạn có thể kiểm soát múi giờ nào được chỉ định bởi việc Clock
thực hiện. Điều này có thể hữu ích trong một số thử nghiệm. Nhưng tôi không khuyến nghị điều này trong mã sản xuất, nơi bạn phải luôn chỉ định rõ ràng các tùy chọn ZoneId
hoặc ZoneOffset
đối số.
Bạn có thể chỉ định rằng UTC là vùng mặc định.
ZonedDateTime zdtClockSystemUTC = ZonedDateTime.now ( Clock.systemUTC () );
Bạn có thể chỉ định bất kỳ múi giờ cụ thể. Chỉ định một tên múi giờ thích hợp trong các định dạng của continent/region
, chẳng hạn như America/Montreal
, Africa/Casablanca
hoặc Pacific/Auckland
. Không bao giờ sử dụng chữ viết tắt 3-4 chữ cái như EST
hoặc IST
chúng không phải là múi giờ thực, không được chuẩn hóa và thậm chí không phải là duy nhất (!).
ZonedDateTime zdtClockSystem = ZonedDateTime.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
Bạn có thể chỉ định múi giờ mặc định hiện tại của JVM phải là mặc định cho một Clock
đối tượng cụ thể.
ZonedDateTime zdtClockSystemDefaultZone = ZonedDateTime.now ( Clock.systemDefaultZone () );
Chạy mã này để so sánh. Lưu ý rằng tất cả họ báo cáo cùng một thời điểm, cùng một điểm trên dòng thời gian. Chúng chỉ khác nhau về thời gian đồng hồ treo tường ; nói cách khác, ba cách để nói cùng một điều, ba cách để hiển thị cùng một khoảnh khắc.
System.out.println ( "zdtClockSystemUTC.toString(): " + zdtClockSystemUTC );
System.out.println ( "zdtClockSystem.toString(): " + zdtClockSystem );
System.out.println ( "zdtClockSystemDefaultZone.toString(): " + zdtClockSystemDefaultZone );
America/Los_Angeles
là vùng mặc định hiện tại của JVM trên máy tính chạy mã này.
zdtClockSystemUTC.toString (): 2016-12-31T20: 52: 39.688Z
zdtClockSystem.toString (): 2016-12-31T15: 52: 39.750-05: 00 [Mỹ / Montreal]
zdtClockSystemDefaultZone.toString (): 2016-12-31T12: 52: 39.762-08: 00 [America / Los_Angele]
Các Instant
lớp luôn trong UTC theo định nghĩa. Vì vậy, ba công Clock
dụng liên quan đến khu vực này có tác dụng chính xác như nhau.
Instant instantClockSystemUTC = Instant.now ( Clock.systemUTC () );
Instant instantClockSystem = Instant.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
Instant instantClockSystemDefaultZone = Instant.now ( Clock.systemDefaultZone () );
tức thìClockSystemUTC.toString (): 2016-12-31T20: 52: 39.763Z
tức thìClockSystem.toString (): 2016-12-31T20: 52: 39.763Z
tức thìClockSystemDefaultZone.toString (): 2016-12-31T20: 52: 39.763Z
Đồng hồ mặc định
Việc thực hiện được sử dụng theo mặc định Instant.now
là một trong đó được trả về Clock.systemUTC()
. Đây là việc thực hiện được sử dụng khi bạn không chỉ định a Clock
. Xem cho chính mình trong mã nguồn Java 9 trước khi phát hànhInstant.now
.
public static Instant now() {
return Clock.systemUTC().instant();
}
Mặc định Clock
cho OffsetDateTime.now
và ZonedDateTime.now
là Clock.systemDefaultZone()
. Xem mã nguồn .
public static ZonedDateTime now() {
return now(Clock.systemDefaultZone());
}
Hành vi của các triển khai mặc định đã thay đổi giữa Java 8 và Java 9. Trong Java 8, thời điểm hiện tại được ghi lại với độ phân giải chỉ tính bằng mili giây mặc dù khả năng của các lớp là lưu trữ độ phân giải nano giây . Java 9 mang đến một triển khai mới có thể ghi lại khoảnh khắc hiện tại với độ phân giải nano giây - tất nhiên phụ thuộc vào khả năng của đồng hồ phần cứng máy tính của bạn.
Giới thiệu về java.time
Các java.time khung được xây dựng vào Java 8 và sau đó. Những lớp học thay thế cái cũ phiền hà di sản lớp học ngày thời gian 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, xem Hướng dẫn 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?
- Java SE 8 , Java SE 9 và mới hơn
- Được xây dựng trong.
- Một phần của API Java tiêu chuẩn với việc triển khai đi kèm.
- Java 9 thêm một số tính năng nhỏ và sửa lỗi.
- Java SE 6 và Java SE 7
- Phần lớn chức năng java.time được chuyển ngược lại sang Java 6 & 7 trong ThreeTen-Backport .
- Android
- Các phiên bản sau của triển khai gói Android của các lớp java.time.
- Đối với Android trước đó (<26), các ThreeTenABP dự án thích nghi ThreeTen-backport (nêu trên). Xem Cách sử dụng ThreeTenABP .
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 .