Tại sao các lớp java.time Java 8 thiếu phương thức getMillis ()?


64

Java 8 có một thư viện hoàn toàn mới về ngày và thời gian trong gói java.time, đây là điều rất đáng hoan nghênh cho bất kỳ ai đã phải sử dụng JodaTime trước đây hoặc gặp rắc rối với việc tạo các phương thức trợ giúp xử lý ngày của riêng nó. Nhiều lớp trong gói này đại diện cho dấu thời gian và có các phương thức trợ giúp như getHour()lấy giờ từ dấu thời gian, getMinute()để lấy phút từ dấu thời gian, getNano()để lấy nanos từ dấu thời gian, v.v ...

Tôi nhận thấy rằng họ không có một phương pháp nào được gọi là getMillis()lấy một phần triệu dấu thời gian. Thay vào đó người ta sẽ phải gọi phương thức get(ChronoField.MILLI_OF_SECOND). Đối với tôi nó có vẻ như một sự không nhất quán trong thư viện. Có ai biết tại sao một phương thức như vậy bị thiếu hay không, vì Java 8 vẫn đang được phát triển nên có khả năng nó sẽ được thêm vào sau không?

https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

Các lớp được định nghĩa ở đây đại diện cho các khái niệm thời gian chính, bao gồm thời gian, thời lượng, ngày, thời gian, múi giờ và thời gian. Chúng dựa trên hệ thống lịch ISO, đây là lịch thế giới thực tế theo các quy tắc Gregorian phổ biến. Tất cả các lớp là bất biến và an toàn chủ đề.

Mỗi phiên bản thời gian ngày bao gồm các trường được API cung cấp một cách thuận tiện. Để truy cập cấp thấp hơn vào các trường tham khảo java.time.temporalgói. Mỗi lớp bao gồm hỗ trợ in và phân tích cú pháp tất cả các ngày và thời gian. Tham khảo java.time.formatgói cho các tùy chọn tùy chỉnh ...

Ví dụ về loại lớp học này:
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

Thời gian ngày không có múi giờ trong hệ thống lịch ISO-8601, chẳng hạn như 2007-12-03T10: 15: 30.

LocalDateTimelà một đối tượng thời gian ngày bất biến đại diện cho thời gian ngày, thường được xem là năm-tháng-ngày-giờ-phút-giây. Các trường ngày và giờ khác, chẳng hạn như ngày trong năm, ngày trong tuần và tuần, cũng có thể được truy cập. Thời gian được biểu diễn cho độ chính xác nano giây. Ví dụ: giá trị "ngày 2 tháng 10 năm 2007 lúc 13: 45.30.123456789" có thể được lưu trữ trong LocalDateTime...


Có vẻ như họ muốn sử dụng đa hình để giải quyết một loạt các phương thức được gọi get(), thay vì đặt cho chúng các tên riêng lẻ. Nếu nó làm phiền bạn, hãy viết một lớp kế thừa lớp gốc và đặt getMillis()phương thức của riêng bạn vào lớp mới.
Robert Harvey

@RobertHarvey Hầu hết các lớp trong gói java.time là bất biến và không thể mở rộng.
assylias

2
@RobertHarvey Câu hỏi cho tôi không phải là làm thế nào tôi có thể giải quyết điều này. Nó chỉ tạo ra một sự mâu thuẫn kỳ lạ và tôi tự hỏi liệu có một lời giải thích thú vị cho việc này.
Tarmo

Tôi có ý tưởng rằng một số kiến ​​trúc / hệ điều hành không hỗ trợ đáng tin cậy trong một phần nghìn giây. Nói cách khác, thời gian hệ thống không thể được truy xuất đến mili giây, chỉ đến phần trăm hoặc phần trăm giây.
Marco

Xem stackoverflow.com/a/23945792/40064 về cách thực hiện thông qua Instantlớp học
Wim Deblauwe 17/03/2016

Câu trả lời:


63

JSR-310 dựa trên nano giây, không phải mili giây. Như vậy, tập hợp tối thiểu các phương pháp hợp lý dựa trên giờ, phút, giây và nano giây. Quyết định có cơ sở nano giây là một trong những quyết định ban đầu của dự án và là quyết định mà tôi tin tưởng là chính xác.

Thêm một phương pháp cho millis sẽ chồng lấp lên của nano giây là một cách không rõ ràng. Người dùng sẽ phải suy nghĩ xem liệu trường nano là nano giây hay nano-milli chẳng hạn. Thêm một phương thức bổ sung khó hiểu là không mong muốn, vì vậy phương pháp đã bị bỏ qua. Như đã chỉ ra, sự thay thế get(MILLI_OF_SECOND)có sẵn.

FWIW, tôi sẽ phản đối việc thêm getMillis()phương thức này trong tương lai.


1
Tôi đã nhận được một số câu trả lời rất hay cho câu hỏi này nhưng câu trả lời của bạn là câu hỏi ưa thích của tôi vì nó ngắn và nó vẫn đưa ra một quan điểm rất hay và thực sự thuyết phục tôi về sự cần thiết của phương pháp này. Cảm ơn bạn.
Tarmo

12
@ s3ib nếu bạn kiểm tra hồ sơ của người trả lời , bạn cũng sẽ nhận thấy rằng anh ta là người dẫn đầu về thông số kỹ thuật cho chính API mà bạn đang hỏi về. Điều này làm cho một câu trả lời là có thẩm quyền vì nó không phải là nó :)
gnat

Vì vậy, phải làm instant.getEpochSecond * 1000 + instant.getNano / 1000000là soạn sẵn hợp lý để có thể giao tiếp với di sản (tại thời điểm này, tất cả) API Java, Javascript, v.v?
nilskp

10
không, trong trường hợp đó bạn chỉ có thể sử dụng instant.toEpochMilli () download.java.net/jdk8/docs/api/java/time/...
JodaStephen

20

Trước khi là một phần của openJDK, threeten đã ở trên github và trước đó nó đã ở trên sourceforge. Trước đó, Stephen Colebourne, người dẫn đầu về đặc điểm kỹ thuật trên jsr-310, đã thực hiện một cuộc khảo sát mà bạn vẫn có thể tìm thấy trên trang web sourceforge .

The fourth question on the survey covered the method names for LocalTime:
1) getHourOfDay(), getMinuteOfHour(), getSecondOfMinute(), getNanoOfSecond()
2) getHour(), getMinute(), getSecond(), getNanoOfSecond()
3) getHour(), getMinute(), getSecond(), getNano()
4) another idea

chỉ 6,23% chọn câu trả lời số 4 và trong số đó có khoảng 15% yêu cầu a getMillis(), tức là ít hơn 1% tổng số phiếu.

Đó có lẽ là lý do tại sao không có getMillisở nơi đầu tiên và tôi không thể tìm thấy bất cứ điều gì liên quan trong danh sách gửi thư openjdk vì vậy vấn đề rõ ràng không được thảo luận sau đó.


3
Tôi nghĩ rằng việc cung cấp cho mọi người một số lựa chọn sẽ giúp họ có nhiều khả năng chọn một trong những lựa chọn đó, ngay cả khi lựa chọn lý tưởng của họ nằm dưới "lựa chọn khác". Tôi có thể sai mặc dù.
Allon Guralnek

2
@ ALLonGuralnek Có chắc chắn - tuy nhiên thành phần mili giây rất quan trọng trong API ngày vì mọi thứ đều dựa trên một số millis kể từ kỷ nguyên. Trong API mới, IMO ít liên quan hơn. Trong hầu hết các trường hợp sử dụng, bạn cần độ chính xác thứ hai hoặc độ chính xác tốt nhất có sẵn (nanos). Tôi có thể sai.
assylias

1
Điều này dường như hỏi về cách đặt tên của các phương thức, không phải phương thức nào nên tồn tại.
Svick

1
Phải, xin lỗi, tôi không rõ: Tôi có nghĩa là câu hỏi từ cuộc khảo sát, rằng nó không tìm kiếm liên quan trực tiếp đến câu hỏi này.
Svick

15

Các lớp biểu thị thời gian UTC không rõ ràng (đó là Instant, OffsetDateTime, ZencedDateTime) có hai phương thức trợ giúp để truy cập phần bù tuyệt đối từ epoch Java, tức là bạn gọi là 'mili giây' trong java.util.Date, mà bạn có thể sử dụng để có được ở mili giây

long getEpochSecond()
int getNano()

1000L*getEpochSecond() + getNano() / 1000000L;

Một số lý do tại sao điều này đã được chọn thay vì long getEpochMillis()được thảo luận trong danh sách gửi thư jsr 310 , một số lý do tôi đã trích xuất để thuận tiện:

có vẻ hợp lý khi cho rằng độ chính xác của mili giây sẽ không đủ. Tuy nhiên, bất cứ điều gì lớn hơn độ chính xác của nano giây dường như quá mức

...

Để thực hiện điều này, tùy chọn ưa thích của tôi sẽ là 64 giây dài (đã ký) + 32 bit int nano giây (không dấu).

...

Tôi thích sự phân chia ở cấp độ thứ hai vì đó là đơn vị thời gian SI chính thức trong khoa học và là tiêu chuẩn được thống nhất phổ biến nhất.

Việc chia tách ở cấp độ ngày là vấn đề đối với các instants vì nó không xử lý các bước nhảy vọt. Chia tách ở mức mili giây, trong khi tích hợp tốt hơn một chút với phần còn lại của Java, có vẻ thực sự khá kỳ quặc. Thêm vào đó nó mất trong phạm vi được hỗ trợ.

Việc tách ra ở lần thứ hai như đề xuất, mang lại một loạt các phần tử nano giây trong hơn 290 tỷ năm. Mặc dù không ai nên sử dụng độ chính xác đó trong phạm vi dòng thời gian đó, tôi khuyên bạn nên hỗ trợ nó dễ dàng hơn là chặn nó. Việc chia tách ở cấp độ ngày là vấn đề đối với các instants vì nó không xử lý giây nhuận

Tôi có cảm giác rằng một lý do khác là cố tình chuyển đổi từ các lớp java.util.Date sang JSR 310, hy vọng rằng các nhà phát triển sẽ cố gắng hiểu sự khác biệt giữa các tùy chọn khác nhau và không chỉ sử dụng các lớp mới một cách mù quáng.

Về lý do tại sao LocalDateTimelớp không có các phương thức đó - chúng không thể tồn tại ở đó vì LocalDateTimekhông bị ràng buộc với dòng thời gian UTC cho đến khi bạn quyết định bạn đang ở khu vực nào hoặc phần bù UTC của bạn là gì, tại thời điểm đó bạn có cho mình một OffsetDateTimehoặc ZonedDateTime(cả hai đều có các phương thức cần thiết).

Ngoài ra, bạn có thể xác định bạn sở hữu LOCAL_EPOCHhằng số 1970-01-01T00:00:00và sau đó thực hiện MILLIS.between(LOCAL_EPOCH, localTime)để có được một số loại thời lượng tính bằng mili giây. Tuy nhiên, giá trị này sẽ không tương thích với bất kỳ giá trị nào được trả về bởi System.currentTimeMilliseconds()hoặc java.util.Date.getTime(), trừ khi tất nhiên bạn xác định giờ địa phương của mình là giờ UTC; nhưng trong trường hợp này, bạn cũng có thể sử dụng Instant trực tiếp hoặc OffsetDateTime với Zone Offerset.UTC.


4
" chúng không thể tồn tại ở đó vì LocalDateTime không bị ràng buộc với dòng thời gian UTC " => LocalDateTime chắc chắn có thể có một getMillisphương thức về cơ bản sẽ quay trở lại getNanos()/1e6- thực tế là nó không phải là tức thời không ngăn nó có một phần nghìn giây thành phần.
assylias

2
" Tôi có cảm giác rằng một lý do khác là cố tình chuyển đổi từ các lớp java.util.Date sang JSR 310 " Có lẽ đúng, nhưng thật không may "millis kể từ epoch" đã trở thành một đại diện gần như phổ biến của thời gian, vì vậy, đối với bất cứ điều gì cần để giao tiếp với các API Java cũ hơn, Javascript, bất cứ điều gì khác, thiếu sót này là một rắc rối thực sự.
nilskp

Đoạn mã của bạn ở trên cùng là không chính xác - bạn cần nhân số getEpochSecond với 1000.
Tin Man

@nilskp Chúng là hai thứ khác nhau. Câu hỏi được hỏi về getMillis()như trong getMillis-of-second; bạn đang nói về "millis kể từ kỷ nguyên". Các cựu vắng mặt như được giải thích trong câu trả lời được chấp nhận. Thứ hai đã có sẵn như là Instant.toEpochMillis(). Vì vậy, đối với a LocalDateTime, bạn sẽ đi:ldt.toInstant(offset).toEpochMillis()
SusanW
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.