2011-09-20 39 views
83

Tôi có danh sách có giá trị dài (ví dụ: 1220227200, 1220832000, 1221436800 ...) mà tôi đã tải xuống từ dịch vụ web. Tôi phải chuyển đổi nó thành Ngày. Đáng tiếc là theo cách này, ví dụ:Chuyển đổi Long to Date trong Java trả về 1970

Date d = new Date(1220227200); 

lợi nhuận 1 tháng 1 năm 1970. Bất cứ ai biết một cách khác để chuyển đổi nó một cách chính xác?

+0

Bạn có thể cho biết giá trị nào bạn mong đợi? Câu hỏi về giây/mili giây có thể là giá trị hợp lệ, nhưng 1220227200 không phải là 1/1/1970.Có vẻ như bạn đang truyền 0 cho hàm tạo. Một số mã khác có thể hữu ích. – SJuan76

+1

@mmmiki - bạn nên chấp nhận câu trả lời – Stewart

+0

nó trả về ngày 15 tháng 1 năm 1970, tại đây, không phải jan 1st. – njzk2

Trả lời

111

Date constructor (nhấp vào liên kết!) Chấp nhận thời gian là long trong mili giây, không phải giây. Bạn cần nhân nó với 1000 và đảm bảo rằng bạn cung cấp nó là long.

Date d = new Date(1220227200L * 1000); 

Điều này cho thấy đây

Sun 31 tháng 8 20:00:00 GMT-04: 00 2008

+10

Hoặc cách khác, sử dụng 'Date d = new Date (TimeUnit.SECONDS.toMillis (1220227200L));' cho một giải pháp sạch hơn và ít * ma thuật số *. –

35

Dường như chờ đợi của bạn là giây, và không mili giây. Ngày constructor mất nhiều thời gian như millis, vì vậy

Date d = new Date(timeInSeconds * 1000); 
+4

lý do tại sao điều này có được một downvote? Ở đây, thưởng thức một cuộc bỏ phiếu. – f1sh

+4

@ f1sh: Tôi đã không downvote, nhưng câu trả lời ban đầu là khác nhau. Anh ta chỉnh sửa nó trong vòng 5 phút ân hạn. – BalusC

+0

cảm ơn bạn đã làm rõ. Đó là SO riêng của mình có ...: -/ – f1sh

8

Đó là những lẽ timestamps trong giây và không có trong mili giây đó là cần thiết cho java new Date (dài) constructor. Chỉ cần nhân chúng với 1000 và bạn sẽ ổn thôi.

+0

Bah .. 30 giây quá chậm: P –

+19

chính xác hơn 30000 mili giây quá chậm – SJuan76

0

Ngày mới (số) trả về ngày number mili giây sau ngày 1 tháng 1 năm 1970. Tỷ lệ là định dạng ngày của bạn không hiển thị giờ, phút và giây để bạn thấy rằng chỉ một chút sau ngày 1 tháng 1 năm 1970.

Bạn cần phân tích cú pháp ngày theo định tuyến phân tích cú pháp chính xác. Tôi không biết 1220227200 là gì, nhưng nếu nó là giây sau 1 JAN 1970, sau đó nhân nó để mang lại mili giây. Nếu không, sau đó chuyển đổi nó theo cách nào đó thành mili giây sau năm 1970 (nếu bạn muốn tiếp tục sử dụng java.util.Date).

0

Làm việc cho tôi. Bạn có thể muốn nhân nó với 1000, kể từ những gì bạn nhận được là những giây từ năm 1970 và bạn phải vượt qua mili giây từ jan 1 1970

1

1220227200 tương ứng với ngày 15 tháng 1 năm 1980 (và ngày thực sự mới (1220227200) .toString () trả về "Thu Jan 15 03:57:07 CET 1970"). Nếu bạn vượt qua một giá trị dài cho một ngày, đó là trước ngày 01/01/1970 nó sẽ trong thực tế trả về một ngày 01/01/1970. Đảm bảo rằng giá trị của bạn không ở trong tình huống này (thấp hơn 82800000).

3

Hãy thử điều này:

Calendar cal = Calendar.getInstance(); 
cal.setTimeInMillis(1220227200 * 1000); 
System.out.println(cal.getTime()); 
3

Các giá trị lâu dài, có khả năng nhất, tương ứng với Epoch timestamps, và các giá trị là:

1220227200 = Mon, 01 Tháng Chín 2008 00:00:00 GMT

1220832000 = Mon, 08 Sep 2008 00:00:00 GMT

1221436800 = Mon, 15 Sep 2008 00:00:00 GMT

Người ta có thể chuyển đổi các giá trị dài này thành java.util.Date, có tính đến thực tế java.util.Ngày sử dụng millisecs - như gợi ý ở trên, nhưng với một số lỗ hổng - như thế này:

// note: enforcing long literals (L), without it the values would just be wrong. 
Date date = new Date(1220227200L * 1000L); 

Bây giờ, để hiển thị ngày tháng chính xác, người ta có thể sử dụng java.text.DateFormat như sau đây minh họa:

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL); 
df.setTimeZone(TimeZone.getTimeZone("UTC")); 
System.out.println("Wrong date time value: " + date); 
System.out.println("Correct date time value: " + df.format(date)); 

dưới đây là kết quả hiển thị giá trị lâu được chuyển đổi để java.util.Date mà không sử dụng và sử dụng DateFormat:

Date wrong (off by 2 hours): Mon Sep 01 02:00:00 CEST 2008 
Correct date : Monday, 1 September 2008 00:00:00 o'clock UTC 
7

Chỉ đặt thời gian trong các nhà máy trên Lịch đối tượng

Calendar c = Calendar.getInstance(); 
c.setTimeInMillis(1385355600000l); 
System.out.println(c.get(Calendar.YEAR)); 
System.out.println(c.get(Calendar.MONTH)); 
System.out.println(c.get(Calendar.DAY_OF_MONTH)); 
// get Date 
System.out.println(c.getTime()); 
36

tl; dr

Instant.ofEpochSecond(1_220_227_200L) 

biết dữ liệu của bạn

dân sử dụng độ chính xác khác nhau trong thời gian theo dõi như một số từ một epoch. Vì vậy, khi bạn nhận được một số số được hiểu là số đếm từ kỷ nguyên, bạn phải xác định:

  • Kỷ nguyên gì?
    Many epochs dates đã được sử dụng trong các hệ thống khác nhau. Thường được sử dụng là POSIX/Unix time, nơi kỷ nguyên là thời điểm đầu tiên của năm 1970 tại UTC. Nhưng bạn không nên giả sử thời đại này.
  • Độ chính xác là gì?
    Chúng ta đang nói giây, milliseconds, microseconds hoặc nanoseconds từ thời đại?
  • Múi giờ nào?
    Thông thường, tính từ thời điểm epoch nằm trong múi giờ UTC/GMT, nghĩa là không có chênh lệch múi giờ. Nhưng đôi khi, khi liên quan đến các lập trình viên thiếu kinh nghiệm hoặc không biết ngày, có thể có một múi giờ ngụ ý.

Trong trường hợp của bạn, như những người khác đã lưu ý, có vẻ như bạn đã nhận được vài giây từ kỷ nguyên Unix. Nhưng bạn đang truyền những giây đó cho một nhà xây dựng dự kiến ​​là mili giây. Vì vậy, giải pháp là nhân với 1.000.

Bài học kinh nghiệm:

  • Xác định, đừng cho rằng, ý nghĩa của dữ liệu nhận được.
  • Đọc the doc.

Graph showing various granularities of resolution in date-time systems including whole seconds, milliseconds, microseconds, and nanoseconds.

liệu

Dữ liệu của bạn của bạn có vẻ là toàn bộ giây. Nếu chúng ta giả định một kỷ nguyên của sự khởi đầu của năm 1970, và nếu chúng ta giả định múi giờ UTC, sau đó 1,220,227,200 là giây phút đầu tiên của ngày đầu tiên của tháng Chín năm 2008.

Joda thời gian

Các java.util.Date và các lớp .Calendar đi kèm với Java nổi tiếng là rắc rối. Tránh chúng.Thay vào đó, hãy sử dụng thư viện Joda-Time hoặc java.time package mới trong Java 8 (và được lấy cảm hứng từ Joda-Time).

Lưu ý rằng không giống như j.u.Date, DateTime trong Joda-Time thực sự biết được chỉ định riêng time zone. Vì vậy, trong ví dụ mã Joda-Time 2.4 được thấy bên dưới, lưu ý rằng trước tiên chúng tôi phân tích cú pháp mili giây bằng cách sử dụng giả định mặc định của UTC. Sau đó, thứ hai, chúng tôi chỉ định múi giờ của Paris để điều chỉnh. Cùng thời điểm trong dòng thời gian của Vũ trụ, nhưng khác nhau wall-clock time. Để trình diễn, chúng tôi điều chỉnh lại, sang UTC. Hầu như luôn luôn tốt hơn để xác định rõ ràng múi giờ mong muốn/mong đợi của bạn hơn là dựa vào một mặc định ngầm định (thường là nguyên nhân của sự cố trong công việc ngày giờ).

Chúng tôi cần mili giây để tạo DateTime. Vì vậy, lấy đầu vào của bạn trong vài giây, và nhân với một ngàn. Lưu ý rằng kết quả phải là 6423 bit long vì chúng tôi sẽ tràn một bit32 bit.

long input = 1_220_227_200L; // Note the "L" appended to long integer literals. 
long milliseconds = (input * 1_000L); // Use a "long", not the usual "int". Note the appended "L". 

Nạp số milli giây đó vào hàm tạo. Nhà xây dựng cụ thể đó giả định số đếm là từ kỷ nguyên Unix năm 1970. Vì vậy, điều chỉnh múi giờ như mong muốn, sau khi xây dựng.

Sử dụng proper time zone tên, kết hợp lục địa và thành phố/khu vực. Không bao giờ sử dụng 3 hoặc 4 mã thư như EST vì chúng không được tiêu chuẩn hóa không phải là duy nhất.

DateTime dateTimeParis = new DateTime(milliseconds).withZone(DateTimeZone.forID("Europe/Paris")); 

Để trình diễn, hãy điều chỉnh lại múi giờ.

DateTime dateTimeUtc = dateTimeParis.withZone(DateTimeZone.UTC); 
DateTime dateTimeMontréal = dateTimeParis.withZone(DateTimeZone.forID("America/Montreal")); 

Dump to console. Lưu ý cách ngày tháng khác ở Montréal, vì ngày mới bắt đầu ở châu Âu nhưng chưa bắt đầu ở Mỹ.

System.out.println("dateTimeParis: " + dateTimeParis); 
System.out.println("dateTimeUTC: " + dateTimeUtc); 
System.out.println("dateTimeMontréal: " + dateTimeMontréal); 

Khi chạy.

dateTimeParis: 2008-09-01T02:00:00.000+02:00 
dateTimeUTC: 2008-09-01T00:00:00.000Z 
dateTimeMontréal: 2008-08-31T20:00:00.000-04:00 

java.time

Các nhà sản xuất Joda thời gian đã yêu cầu chúng tôi chuyển sang thay thế của nó, khuôn khổ java.time càng sớm càng thuận tiện. Trong khi Joda-Time tiếp tục được hỗ trợ tích cực, tất cả các phát triển trong tương lai sẽ được thực hiện trên các lớp java.time và các phần mở rộng của chúng trong dự án ThreeTen-Extra.

Khung thời gian java được xác định bởi JSR 310 và được tích hợp vào Java 8 trở lên. Các lớp java.time đã được chuyển về Java 6 & 7 trong dự án ThreeTen-Backport và Android trong dự án ThreeTenABP.

An Instant là thời điểm trên dòng thời gian trong UTC với độ phân giải nano giây. Kỷ nguyên của nó là thời điểm đầu tiên của năm 1970 tại UTC.

Instant instant = Instant.ofEpochSecond(1_220_227_200L); 

Áp dụng một offset-from-UTCZoneOffset để có được một OffsetDateTime.

Tốt hơn, nếu biết, hãy áp dụng múi giờ ZoneId để nhận được ZonedDateTime.

ZoneId zoneId = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant , zoneId); 
+1

Chúc mừng bạn thân. Lời giải thích tuyệt vời. Tôi đã nhận được DateTime mới () từ năm 1970 khi tôi nhận ra rằng tôi đã cho nó trong vài giây và yêu cầu trong mili giây –

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