Java: Ngày từ dấu thời gian unix


237

Tôi cần chuyển đổi dấu thời gian unix thành đối tượng ngày.
Tôi đã thử điều này:

java.util.Date time = new java.util.Date(timeStamp);

Giá trị dấu thời gian là: 1280512800

Ngày phải là "2010/07/30 - 22:30:00" (khi tôi nhận được bằng PHP) nhưng thay vào đó tôi nhận được Thu Jan 15 23:11:56 IRST 1970.

Nên làm thế nào?


2
Nếu bạn sử dụng Java 8 hoặc mới hơn: Hãy xem câu trả lời này: stackoverflow.com/a/24703644/1115554
micha

1
FYI, các lớp thời gian cũ rắc rối như java.util.Datebây giờ là di sản , được thay thế bởi các lớp java.time . Xem Hướng dẫn của Oracle .
Basil Bourque

Câu trả lời:


429

Đối với 1280512800, nhân với 1000, vì java đang mong đợi một phần nghìn giây:

java.util.Date time=new java.util.Date((long)timeStamp*1000);

Nếu bạn đã có mili giây, thì chỉ cần new java.util.Date((long)timeStamp);

Từ tài liệu :

Phân bổ một đối tượng Ngày và khởi tạo nó để biểu thị số mili giây đã chỉ định kể từ thời gian cơ sở tiêu chuẩn được gọi là "kỷ nguyên", cụ thể là ngày 1 tháng 1 năm 1970, 00:00:00 GMT.


40
Các diễn viên (long)rất quan trọng: không có nó thì số nguyên tràn.
mneri

2
@TomasK java.util.Datelà tên đủ điều kiện của lớp. Datecó lẽ chính xác là điều tương tự với điều kiện bạn nhập java.utilgói trên lớp của bạn.
Pablo Santa Cruz

5
Các diễn viên để lâu là không cần thiết. time = new java.util.Date (timeStamp * 1000L) cũng hoạt động tốt (vì 1000L là một dấu thời gian dài, sẽ được cập nhật trong một thời gian dài trước khi nhân)
Tony

2
Cá nhân tôi sẽ làm:Date time = new Date(TimeUnit.MILLISECONDS.convert(unixTimestamp, TimeUnit.SECONDS));
Ryan Amaral

3
FYI, các lớp thời gian cũ rắc rối như java.util.Datebây giờ là di sản , được thay thế bởi các lớp java.time . Xem Hướng dẫn của Oracle .
Basil Bourque

59

java.time

Java 8 đã giới thiệu một API mới để làm việc với ngày và giờ: gói java.time .

Với java.time, bạn có thể phân tích tổng số giây của mình kể từ tham chiếu kỷ nguyên của khoảnh khắc đầu tiên của năm 1970 trong UTC, 1970-01-01T00: 00Z. Kết quả là một Instant.

Instant instant = Instant.ofEpochSecond( timeStamp );

Nếu bạn cần một java.util.Datetương tác với mã cũ chưa được cập nhật cho java.time , hãy chuyển đổi. Gọi các phương thức chuyển đổi mới được thêm vào các lớp cũ.

Date date = Date.from( instant );

3
Mặc dù Câu trả lời này đúng về mặt kỹ thuật, lưu ý rằng các lớp java.time thay thế các lớp thời gian cũ rắc rối như java.util.Date. Các lớp cũ là di sản và nên tránh. Mặc dù bạn thực sự có thể chuyển đổi sang / từ các lớp kế thừa và java.time, tốt nhất bạn nên gắn bó với java.time bất cứ khi nào có thể.
Basil Bourque

44

Đây là cách đúng đắn:

Date date = new Date ();
date.setTime((long)unix_time*1000);

27

Có vẻ như Lịch là con đường mới để đi:

Calendar mydate = Calendar.getInstance();
mydate.setTimeInMillis(timestamp*1000);
out.println(mydate.get(Calendar.DAY_OF_MONTH)+"."+mydate.get(Calendar.MONTH)+"."+mydate.get(Calendar.YEAR));

Dòng cuối cùng chỉ là một ví dụ về cách sử dụng nó, dòng này sẽ in ví dụ: "14.06.2012".

Nếu bạn đã sử dụng System.cienTimeMillis () để lưu Dấu thời gian, bạn không cần phần "* 1000".

Nếu bạn có dấu thời gian trong một chuỗi, bạn cần phân tích cú pháp đầu tiên dưới dạng dài: Long.parseLong (dấu thời gian).

https://docs.oracle.com/javase/7/docs/api/java/util/CalWiki.html


8
Cảnh báo: nếu timestamplà số nguyên bạn cần đặt (long)trước, nếu không, bạn sẽ kết thúc với ngày sai. mydate.setTimeInMillis((long) timestamp*1000);
svenkapudija

Tôi đã sửa liên kết.
Ricbit

FYI, người già lớp ngày thời gian phiền hà như java.util.Date, java.util.Calendarjava.text.SimpleDateFormatbây giờ là di sản , thay thế bởi sự java.time class built vào Java 8 và sau đó. Xem Hướng dẫn của Oracle .
Basil Bourque

26

tl; dr

Instant.ofEpochSecond( 1_280_512_800L )

2010-07-30T18: 00: 00Z

java.time

Khung công tác java.time mới được tích hợp trong Java 8 trở lên là sự kế thừa của Joda-Time.

Các lớp mới này bao gồm một phương thức xuất xưởng tiện dụng để chuyển đổi tổng số giây từ epoch. Bạn nhận được Instantmột khoảnh khắc trên dòng thời gian trong UTC với độ phân giải lên tới nano giây.

Instant instant = Instant.ofEpochSecond( 1_280_512_800L );

tức thì.toString (): 2010-07-30T18: 00: 00Z

Xem đó chạy trực tiếp tại IdeOne.com .

Bảng các loại thời gian trong Java, cả hiện đại và di sản

Asia/Kabulhay Asia/Tehranmúi giờ?

Bạn đã báo cáo nhận được giá trị thời gian trong ngày là 22:30 thay vì 18:00 được thấy ở đây. Tôi nghi ngờ tiện ích PHP của bạn đang ngầm áp dụng múi giờ mặc định để điều chỉnh từ UTC. Giá trị của tôi ở đây là UTC, được biểu thị bằng Z(viết tắt của ZuluUTC). Bất kỳ cơ hội nào hệ điều hành hoặc PHP máy của bạn được đặt thành Asia/Kabulhoặc Asia/Tehranmúi giờ? Tôi cho rằng khi bạn báo cáo IRSTtrong đầu ra của bạn, điều đó có nghĩa là thời gian của Iran. Hiện tại trong năm 2017, đây là những khu vực duy nhất hoạt động với thời gian mùa hè sớm hơn UTC bốn giờ rưỡi.

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/Casablancahoặc Pacific/Auckland. Không bao giờ sử dụng tên viết tắt 3-4 lá thư như ESThay ISThay IRSTvì họ là không khu đúng thời gian, không được chuẩn hóa, và thậm chí không duy nhất (!).

Nếu bạn muốn xem khoảnh khắc của mình qua lăng kính của múi giờ của một khu vực cụ thể, hãy áp dụng a ZoneIdđể có được ZonedDateTime. Vẫn cùng một khoảnh khắc, nhưng được xem như một thời gian đồng hồ treo tường khác nhau .

ZoneId z = ZoneId.of( "Asia/Tehran" ) ;
ZonedDateTime zdt = instant.atZone( z );  // Same moment, same point on timeline, but seen as different wall-clock time.

2010-07-30T22: 30 + 04: 30 [Châu Á / Tehran]

Chuyển đổi từ java.time sang các lớp kế thừa

Bạn nên gắn bó với các lớp java.time mới. Nhưng bạn có thể chuyển đổi sang cũ nếu cần thiết.

java.util.Date date = java.util.Date.from( instant );

Joda-Thời gian

CẬP NHẬT: Dự án Joda-Time hiện đang ở chế độ bảo trì , với nhóm tư vấn di chuyển sang các lớp java.time .

FYI, công cụ xây dựng cho Thời gian hẹn giờ của Joda tương tự: Nhân với một nghìn để tạo ra một long(không phải một int!).

DateTime dateTime = new DateTime( ( 1_280_512_800L * 1000_L ), DateTimeZone.forID( "Europe/Paris" ) );

Tốt nhất để tránh các lớp java.util.Date và .CalWiki nổi tiếng rắc rối. Nhưng nếu bạn phải sử dụng Ngày, bạn có thể chuyển đổi từ Joda-Time.

java.util.Date date = dateTime.toDate();

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 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 .


11

Hàm tạo của Date dự kiến ​​giá trị timeStamp sẽ tính bằng mili giây. Nhân giá trị dấu thời gian của bạn với 1000, sau đó chuyển là cho hàm tạo.


7

Nếu bạn đang chuyển đổi giá trị dấu thời gian trên một máy khác, bạn cũng nên kiểm tra múi giờ của máy đó. Ví dụ;

Các phân tách ở trên sẽ dẫn đến các giá trị Ngày khác nhau, nếu bạn chạy với các múi giờ EST hoặc UTC.

Để đặt múi giờ; aka đến UTC, bạn có thể chỉ cần viết lại;

    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    java.util.Date time= new java.util.Date((Long.parseLong(timestamp)*1000));

6
Tôi sẽ không đề xuất điều này bởi vì điều này đặt múi giờ cho toàn bộ jvm chứ không chỉ là quá trình phân tích cú pháp!

1

Đối với kotlin

fun unixToDate(timeStamp: Long) : String? {
    val time = java.util.Date(timeStamp as Long * 1000)
    val sdf = SimpleDateFormat("yyyy-MM-dd")
    return sdf.format(time)

}

0

Đôi khi bạn cần phải làm việc với các điều chỉnh.

Đừng dùng diễn viên lâu! Sử dụng điều chỉnh nano.

Ví dụ: sử dụng API Java Oanda để giao dịch, bạn có thể lấy datetime dưới định dạng UNIX.

Ví dụ: 1592523410.590566943

    System.out.println("instant with nano = " + Instant.ofEpochSecond(1592523410, 590566943));
    System.out.println("instant = " + Instant.ofEpochSecond(1592523410));

bạn lấy:

instant with nano = 2020-06-18T23:36:50.590566943Z
instant = 2020-06-18T23:36:50Z

Ngoài ra, sử dụng:

 Date date = Date.from( Instant.ofEpochSecond(1592523410, 590566943) );

-4
Date d = new Date(i * 1000 + TimeZone.getDefault().getRawOffset());

3
Không có thêm một số văn bản, không rõ tại sao câu trả lời này lại thích hợp hơn nhiều câu hỏi khác trong câu hỏi này. Bạn có thể vui lòng làm rõ?
Duncan Jones

Điều này sẽ sửa đổi ngày thay vì chuyển đổi nó!
dấu gạch chéo ngược
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.