2013-02-13 38 views
7

Chúng ta biết rằng phương thức getTime của java.util.Date trả về số mili giây kể từ ngày 1 tháng 1 năm 1970, 00:00:00 GMT được đại diện bởi đối tượng Date này.Tại sao ngày thay đổi với cùng số mili giây trên các múi giờ khác nhau?

Tôi nhận thấy một tình huống kỳ lạ như sau;

Hệ thống múi giờ là: (UTC + 02: 00) Istanbul

Date currentDate = new Date(); 
System.out.println(currentDate .getTime()); 
System.out.println(currentDate); 

Java ConsoleOutput:

Wed 13 tháng 2 13:00:17 VET 2013


Sau đó, plugin javascript của tôi đang sử dụng đối tượng dài này như dưới đây;

Javascript:

console.log(new Date(1360753217219)); 

Trình duyệt ConsoleOutput:

ngày {Wed 13 Tháng 2 2013 13:00:17 GMT + 0200 (Thời gian Thổ Nhĩ Kỳ Standard)}


Thats tất cả ok, tuy nhiên! Sau khi thay đổi múi giờ địa phương (UTC-04: 30) Caracas, tình hình và giờ thay đổi như sau với cùng một số mili giây;


Javascript:

console.log(new Date(1360753217219)); 

Trình duyệt ConsoleOutput:

ngày {Wed 13 Tháng Hai 2013 06:30:17 GMT-0430 (Thời gian Venezuela chuẩn)}

Ai đó có thể giải thích điều này? Đó có phải là lỗi js không? Hoặc quan trọng hơn, làm thế nào tôi nên xử lý điều này ở phía bên java, để có được cùng một ngày với cùng số miliseconds cho các múi giờ khác nhau ở phía bên j?

Cảm ơn!

+0

'console.log ((ngày mới (1360753217219)). ToString())' và 'console.log ((ngày mới (1360753217219)). ToUTCString())' cung cấp cho bạn? – robertc

+6

Tôi xin lỗi, tôi không thấy vấn đề. 6:30 ở Caracas là 13:00 ở Thổ Nhĩ Kỳ. Chỉ cần bạn đang cố gắng làm gì? – arcy

+0

mili giây tương đối so với UTC, điểm là gì? –

Trả lời

2

không phải là lỗi, đó chỉ là cách múi giờ hoạt động.

nếu bạn gọi cho ai đó ở Venezuela ngay bây giờ và hỏi anh ấy thời gian là gì, anh ấy sẽ cho bạn biết đó là 6.5 (theo ví dụ của bạn) giờ sớm hơn thời gian ở gà tây.

như bạn đã đề cập, số bạn đang xử lý đại diện cho số mili giây từ năm 1970, 00:00:00 GMT, ở Caracas tại thời điểm đó, thời gian là 31,12.1969 19:30 GMT-0430

vì vậy, tuy nhiên nhiều giây sau, thời gian ở Venezuela vẫn sẽ sớm hơn 4:30 giờ so với GMT.

bạn không thể có cùng ngày chính xác trong các múi giờ khác nhau nếu bạn sử dụng cùng một đầu vào (mili giây) vì điều đó chỉ đơn giản là sai.

nếu bạn muốn nhận được kết quả tương tự, bạn có thể thêm sự khác biệt về múi giờ (6,5 giờ trong trường hợp này) vào đầu ra. theo lời khuyên của Dr.Dredel, có lẽ bạn không nên lộn xộn với mili giây.

+0

thay đổi mili giây thực sự thay đổi thời gian (không phải múi giờ). Mỗi tem ngày có độ lệch múi giờ như một phần của chuỗi ngang. Nó khá dễ dàng để làm việc ra bao nhiêu giờ cần phải được thêm/trừ từ dấu thời gian dễ đọc của con người dựa trên đó. Tua xung quanh với mili giây được đảm bảo để giúp bạn gặp rắc rối và hoàn toàn sai lầm khi làm việc này. –

+0

@ Dr.Dredel cảm ơn nhận xét, tôi đã sửa lại phản hồi của tôi cho phù hợp. – yurib

6

Mili giây là thời gian bất khả tri. Thời gian được tính là tuyệt đối kể từ ngày 1 tháng 1 năm 1970 GMT. Vì vậy, ý tưởng là bạn nhận được mili giây và sau đó tìm ra thời gian địa phương cho một múi giờ nhất định là sau khi thực tế. Nếu bạn nghĩ về nó, nó có ý nghĩa. Số lượng mili giây đã trôi qua kể từ năm 1970 là như nhau dù bạn ở đâu.

Nó hơi khó hiểu nhưng KHÔNG NÊN xung quanh với mili giây để điều chỉnh múi giờ. Mỗi thư viện ngày có các cơ chế dịch dấu mili giây thành múi giờ địa phương cụ thể theo múi giờ. Vì vậy, nếu câu hỏi cụ thể của bạn là cách giao tiếp ngày hiệu quả giữa máy chủ và ứng dụng khách (ngôn ngữ bạn đang sử dụng không quan trọng), câu trả lời là hoàn toàn an toàn để vượt qua mili giây qua lại và làm việc trên ở hai bên thời gian cụ thể toàn cầu mà bạn đang nói đến, nếu điều đó quan trọng đối với bối cảnh của những gì bạn đang làm với thời gian đó.

+1

Đó là "kể từ ngày 1 tháng 1 năm 1970, * GMT * - có thể sự nhầm lẫn của OP bắt nguồn từ việc không hiểu rằng thời gian kỷ nguyên là trong một múi giờ, vì nó sẽ phải như vậy. Nếu không, số mili giây có thông qua sẽ không được "cùng một không có vấn đề bạn đang ở đâu" – arcy

+0

Phải ... xin lỗi, tôi sẽ sửa câu trả lời của tôi. –

0

tl; dr

Instant.ofEpochMilli(1_360_753_217_219L)   // UTC 

2013-02-13T11: 00: 17.219Z

Instant.ofEpochMilli(1_360_753_217_219L)  
     .atZone(ZoneId.of("Europe/Istanbul")) // Same moment, two hours *ahead* of UTC. 

2013-02-13T13: 00: 17,219 + 02: 00 [Châu Âu/Istanbul]

Instant.ofEpochMilli(1_360_753_217_219L)  
     .atZone(ZoneId.of("America/Caracas")) // Same moment, four-and-a-half hours *behind* UTC. 

2013-02-13T06: 30: 17,219-04: 30 [Mỹ/Caracas]

Sử dụng java.time

Bạn đang sử dụng các lớp học ngày thời gian cũ phiền hà kèm với sớm nhất phiên bản Java. Chúng bây giờ là di sản, được thay thế bởi các lớp java.time, thư viện thời gian tốt nhất trên bất kỳ nền tảng nào.

Bắt đầu với số mili giây của bạn kể từ ngày epoch reference date vào đầu năm 1970 ở UTC (1970-01-01T00: 00: 00Z). Những người khác chỉ ra rằng bạn có thể không hiểu rằng một ngày tham chiếu thời đại có một múi giờ, và ở đây với kỷ nguyên này mà khu vực là UTC, một sự bù đắp của 0 giờ. Tất cả các bù trừ khác được tính dựa vào số dư này, số giờ và số phút trước UTC hoặc sau UTC.

Lớp Instant đại diện cho một thời điểm trên dòng thời gian ở UTC với độ phân giải nanoseconds (tối đa chín (9) chữ số thập phân).

long input = 1_360_753_217_219L ; 
Instant instant = Instant.ofEpochMilli(input) ; 

instant.toString(): 2013-02-13T11: 00: 17.219Z

Nếu bạn muốn để thấy rằng cùng một thời điểm thông qua ống kính của một khu vực cụ thể của wall-clock time, áp dụng một Múi giờ.

Múi giờ là lịch sử của những thay đổi trong quá khứ, hiện tại và tương lai đối với chênh lệch được sử dụng bởi một khu vực cụ thể.

Chỉ định proper time zone name ở định dạng continent/region, chẳng hạn như America/Montreal, Africa/Casablanca hoặc Pacific/Auckland. Không bao giờ sử dụng từ viết tắt 3-4 ký tự như EST hoặc IST vì chúng là không múi giờ thực, không được chuẩn hóa và thậm chí không độc đáo (!).

ZoneId zEurope_Istanbul = ZoneId.of("Europe/Istanbul") ; 
ZonedDateTime zdtEurope_Istanbul = instant.atZone(zEurope_Istanbul) ; 

zdtEurope_Istanbul.toString(): 2013-02-13T13: 00: 17,219 + 02: 00 [Châu Âu/Istanbul]

Bạn có thể áp dụng múi giờ khác.

ZoneId zAmerica_Caracas = ZoneId.of("America/Caracas") ; 
ZonedDateTime zdtAmerica_Caracas = zdtEurope_Istanbul.withZoneSameInstant(zAmerica_Caracas) ; 

zdtAmerica_Caracas.toString(): 2013-02-13T06: 30: 17,219-04: 30 [Mỹ/Caracas]

Xem code live at IdeOne.com này.

Cả ba đối tượng, ngay lập tức & zdtEurope_Istanbul & zdtAmerica_Caracas, tất cả các đại diện lúc đồng thời rất giống, điểm giống nhau trên timeline.

Số đếm từ thời đại của bạn đại diện cho 11 giờ sáng theo giờ UTC. Istanbul là hai giờ trước của UTC, do đó, thời gian trong ngày tại cùng một thời điểm là hai giờ sau 11 giờ sáng, 1 giờ chiều (13:00). Venezuela là bốn giờ rưỡi phía sau UTC, do đó, thời gian trong ngày tại cùng một thời điểm là 6:30 sáng. Tất cả đều có ý nghĩa, tất cả cùng một thời điểm nhưng thời gian đồng hồ treo tường khác nhau.

ISO 8601

Không sử dụng số đếm từ thời đại để trao đổi hoặc lưu trữ các giá trị ngày giờ. Đó là dễ bị lỗi, không thể đọc được một cách có ý nghĩa bởi con người và không rõ ràng vì có ít nhất một vài ngày tham chiếu epoch được sử dụng bởi các hệ thống phần mềm khác nhau và các chi tiết khác nhau (toàn bộ giây, mili giây, micro giây, nano giây, v.v.).

Khi chuyển giá trị ngày giờ ngoài JVM của bạn, hãy sử dụng các định dạng chuẩn ISO 8601 để trình bày văn bản. Các lớp java.time sử dụng các định dạng chuẩn theo mặc định khi phân tích cú pháp/tạo chuỗi. Bạn có thể xem các định dạng đó trong mã ví dụ của Câu trả lời này.


Về java.time

Khung java.time được xây dựng vào Java 8 và sau đó.Các lớp này thay thế các lớp học ngày giờ legacy phiền hà cũ như java.util.Date, Calendar, & SimpleDateFormat.

Dự án Joda-Time, hiện đang ở maintenance mode, khuyên di chuyển đến các lớp java.time.

Để tìm hiểu thêm, hãy xem Oracle Tutorial. 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.

Nơi lấy các lớp java.time?

Dự án mở rộng ThreeTen-Extra 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 những bổ sung có thể có trong tương lai vào java.time. Bạn có thể tìm thấy một số lớp học hữu ích tại đây như Interval, YearWeek, YearQuartermore.

Các vấn đề liên quan