Làm cách nào để chuyển đổi currentTimeMillis thành một ngày trong Java?


140

Tôi có mili giây trong tệp nhật ký nhất định được tạo trong máy chủ, tôi cũng biết miền địa phương nơi tệp nhật ký được tạo, vấn đề của tôi là chuyển đổi mili giây thành ngày theo định dạng. Việc xử lý nhật ký đó đang diễn ra trên máy chủ nằm ở múi giờ khác nhau. Trong khi chuyển đổi sang chương trình "SimpleDateFormat" đang lấy ngày của máy vì ngày được định dạng như vậy không thể hiện đúng thời gian của máy chủ. Có cách nào để xử lý việc này một cách thanh lịch?

long yourmilliseconds = 1322018752992l;
        //1322018752992-Nov 22, 2011 9:25:52 PM 

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS",Locale.US);

GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("US/Central"));
calendar.setTimeInMillis(yourmilliseconds);

System.out.println("GregorianCalendar -"+sdf.format(calendar.getTime()));

DateTime jodaTime = new DateTime(yourmilliseconds, 
                    DateTimeZone.forTimeZone(TimeZone.getTimeZone("US/Central")));
DateTimeFormatter parser1 = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss,SSS");

System.out.println("jodaTime "+parser1.print(jodaTime));

Đầu ra:

Gregorian Calendar -2011-11-23 08:55:52,992
jodaTime 2011-11-22 21:25:52,992

Đừng nhầm lẫn Locale với múi giờ. Hoàn toàn riêng biệt. Ngôn ngữ xác định ngôn ngữ của con người để đặt tên cho tháng và ngày, và các chuẩn mực văn hóa như thứ tự các bộ phận như tháng, ngày, v.v. Múi giờ được bù trừ từ UTC cộng với các quy tắc để xử lý các bất thường như Giờ tiết kiệm ánh sáng ban ngày.
Basil Bourque

Có phải vấn đề là số mili giây không phải là từ 1970-01-01T00: 00: 00Z mà là từ một thời điểm khác?
Basil Bourque

FYI, cả các lớp thời gian cũ khủng khiếp ( GregorianCalendar, SimpleDateFormatv.v.) và thư viện Joda-Time tuyệt vời hiện được thay thế bởi các lớp java.time hiện đại .
Basil Bourque

Câu trả lời:


115
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeStamp);

int mYear = calendar.get(Calendar.YEAR);
int mMonth = calendar.get(Calendar.MONTH);
int mDay = calendar.get(Calendar.DAY_OF_MONTH);

Tôi đã phải đặt Lịch là cuối cùng để làm cho nó hoạt động. final Calendar calendar = Calendar.getInstance();
Victor Augusto

4
Các đối tượng lịch thường được coi là khá lớn, vì vậy nên tránh khi có thể. Một đối tượng Date sẽ tốt hơn khi giả sử nó có chức năng bạn cần. "Ngày ngày = Ngày mới (millis);" Người dùng AVD cung cấp trong câu trả lời khác sẽ là con đường tốt nhất :)
Dick Lucas

1
Bằng cách nào đó, cho 1515436200000l, tôi nhận được calendar.get(Calendar.MONTH))như 0!
Sajib Acharya

FYI, người già lớp ngày thời gian khủng khiếp 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

2
@SajibAcharya Lưu ý rằng các phiên bản cho Lịch.MONTH bắt đầu từ 0; bạn cần thêm một để có được tháng "thực" như chúng ta đã biết. Ví dụ: 0 = tháng 1, 1 = tháng 2, 2 = tháng 3, v.v.
shagberg

256

Bạn có thể sử dụng java.util.Datelớp và sau đó sử dụng SimpleDateFormatđể định dạng Date.

Date date=new Date(millis);

Chúng tôi có thể sử dụng gói java.time (hướng dẫn) - API DateTime được giới thiệu trong Java SE 8.

var instance = java.time.Instant.ofEpochMilli(millis);
var localDateTime = java.time.LocalDateTime
                        .ofInstant(instance, java.time.ZoneId.of("Asia/Kolkata"));
var zonedDateTime = java.time.ZonedDateTime
                            .ofInstant(instance,java.time.ZoneId.of("Asia/Kolkata"));

// Format the date

var formatter = java.time.format.DateTimeFormatter.ofPattern("u-M-d hh:mm:ss a O");
var string = zonedDateTime.format(formatter);

2
Hiệu quả hơn nhiều.
Chad Bingham

2
Không. Không phải tất cả các phương pháp java.util.Dateđều được khấu hao. (Có các API Ngày & Giờ được cải thiện trong JDK8 java.time)
adatapost

1
@RafaelZeffa, nhà xây dựng '' '(ngày dài)' '' không được phản đối
Gugelhupf

Đối tượng Date được cung cấp để tương thích ngược. Sử dụng tốt hơn Lịch như đề xuất ở trên.
Ton Snoei

2
FYI, người già lớp ngày thời gian khủng khiếp 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

24

tl; dr

Instant.ofEpochMilli( 1_322_018_752_992L )     // Parse count of milliseconds-since-start-of-1970-UTC into an `Instant`.
       .atZone( ZoneId.of( "Africa/Tunis" ) )  // Assign a time zone to the `Instant` to produce a `ZonedDateTime` object.

Chi tiết

Các câu trả lời khác sử dụng các lớp lỗi thời hoặc không chính xác.

Tránh các lớp thời gian cũ như java.util.Date/.CalWiki. Họ đã được chứng minh là thiết kế kém, khó hiểu và rắc rối.

java.time

Các java.time khuôn khổ đi kèm được xây dựng vào Java 8 và sau đó. Phần lớn chức năng được nhập vào Java 6 & 7 và tiếp tục thích nghi với Android . Được tạo ra bởi một số người giống như đã tạo ra Joda-Time .

An Instantlà một khoảnh khắc 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à khoảnh khắc đầu tiên của năm 1970 tại UTC.

Giả sử dữ liệu đầu vào của bạn là số mili giây từ 1970-01-01T00: 00: 00Z (không rõ ràng trong Câu hỏi), thì chúng ta có thể dễ dàng khởi tạo một Instant.

Instant instant = Instant.ofEpochMilli( 1_322_018_752_992L );

tức thì.toString (): 2011-11-23T03: 25: 52.992Z

Các Ztrong đó tiêu chuẩn ISO 8601 định dạng chuỗi là chữ viết tắt Zuluvà nghĩa UTC .

Áp dụng múi giờ bằng cách sử dụng tên múi giờ thích hợp , để có được a ZonedDateTime.

ZoneId zoneId = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( zoneId );

Xem này chạy trực tiếp tại IdeOne.com .

Asia/Kolkata Múi giờ ?

Tôi đoán bạn đang có múi giờ Ấn Độ ảnh hưởng đến mã của bạn. Chúng tôi thấy ở đây việc điều chỉnh theo Asia/Kolkatamúi giờ biểu hiện cùng thời gian trong ngày như bạn báo cáo, 08:55tức là trước năm giờ rưỡi so với giá trị UTC của chúng tôi 03:25.

2011-11-23T08: 55: 52.992 + 05: 30 [Châu Á / Kolkata]

Vùng mặc định

Bạn có thể áp dụng múi giờ mặc định hiện tại của JVM. Coi chừng mặc định có thể thay đổi bất cứ lúc nào trong thời gian chạy . Bất kỳ mã nào trong bất kỳ luồng nào của bất kỳ ứng dụng nào trong JVM đều có thể thay đổi mặc định hiện tại. Nếu quan trọng, hãy hỏi người dùng về múi giờ mong muốn / mong muốn của họ.

ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

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 .

Với trình điều khiển JDBC tuân thủ JDBC 4.2 trở lên, bạn có thể trao đổi trực tiếp các đối tượng java.time với cơ sở dữ liệu của mình. Không cần chuỗi hoặc 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 đó, 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 .


Bạn có thể dễ dàng chuyển đổi Instant mà bạn đề xuất ở trên thành múi giờ địa phương mặc định trên thiết bị (ví dụ: điện thoại thông minh) không?
AJW

1
@AJW Vâng. Gọi ZoneId.systemDefault(). Xem phần mới được thêm vào cuối Câu trả lời của tôi.
Basil Bourque

Tuyệt vời, tôi sẽ thử.
AJW

14

Cách dễ nhất để làm điều này là sử dụng lớp DateTime Joda và chỉ định cả dấu thời gian tính bằng mili giây và DateTimeZone bạn muốn.

Tôi thực sự khuyên bạn nên tránh các lớp Ngày và Lịch Java tích hợp; họ thật kinh khủng.


GorgianCalender không hoạt động ... vì bất kỳ lý do gì, nó lấy múi giờ mặc định của hệ thống. Joda đã làm việc hoàn hảo.
Amit

Hãy cho tôi biết nhìn vào mã mẫu nếu chúng ta có thể làm điều gì đó khác biệt với Gregorian
Amit

1
FYI, dự án Joda-Time hiện đang ở chế độ bảo trì , khuyên nên chuyển sang các lớp java.time . Xem Hướng dẫn của Oracle .
Basil Bourque

13

Nếu giá trị millis là số millis kể từ ngày 1 tháng 1 năm 1970 GMT, như là tiêu chuẩn cho JVM, thì đó là độc lập với múi giờ. Nếu bạn muốn định dạng nó theo múi giờ cụ thể, bạn chỉ cần chuyển đổi nó thành đối tượng GregorianCalWiki và đặt múi giờ. Sau đó, có rất nhiều cách để định dạng nó.


1
Đây là mã mẫu với GregorianCalWiki và Joda, tôi đang nhận được đầu ra chính xác với Joda nhưng không phải với lịch Gregorian GregorianCalWiki = new GregorianCalWiki (TimeZone.getTimeZone ("US / Central")); calendar.setTimeInMillis (yourmilliseconds); DateTime jodaTime = DateTime mới (yourmilliseconds, DateTimeZone.forTimeZone (TimeZone.getTimeZone ("US / Central"))); Trình phân tích cú pháp DateTimeFormatter1 = DateTimeFormat.forPotype ("yyyy-MM-dd HH: mm: ss, SSS");
Amit

Đặt múi giờ trong đối tượng lịch không hoạt động, nhưng đặt nó trong đối tượng định dạng ngày đã làm gì?
Hóa đơn

DateTime và DateTimeFormatter là gì ??
SweetWisher

11

Giải pháp của tôi

public class CalendarUtils {

    public static String dateFormat = "dd-MM-yyyy hh:mm";
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat);

    public static String ConvertMilliSecondsToFormattedDate(String milliSeconds){
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(Long.parseLong(milliSeconds));
        return simpleDateFormat.format(calendar.getTime());
    }
}

6

Tôi làm như thế này:

static String formatDate(long dateInMillis) {
    Date date = new Date(dateInMillis);
    return DateFormat.getDateInstance().format(date);
}

Bạn cũng có thể sử dụng getDateInstance(int style)với các tham số sau:

DateFormat.SHORT

DateFormat.MEDIUM

DateFormat.LONG

DateFormat.FULL

DateFormat.DEFAULT



5

Cách dễ nhất:

private String millisToDate(long millis){

    return DateFormat.getDateInstance(DateFormat.SHORT).format(millis);
    //You can use DateFormat.LONG instead of SHORT

}

2

Dưới đây là giải pháp của tôi để có được ngày từ định dạng milisecond đến định dạng ngày. Bạn phải sử dụng Thư viện Joda để chạy mã này.

import java.util.GregorianCalendar;
import java.util.TimeZone;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class time {

    public static void main(String args[]){

        String str = "1431601084000";
        long geTime= Long.parseLong(str);
        GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("US/Central"));
        calendar.setTimeInMillis(geTime);
        DateTime jodaTime = new DateTime(geTime, 
               DateTimeZone.forTimeZone(TimeZone.getTimeZone("US/Central")));
        DateTimeFormatter parser1 = DateTimeFormat.forPattern("yyyy-MM-dd");
        System.out.println("Get Time : "+parser1.print(jodaTime));

   }
}

1

Bạn có thể thử java.time api;

        Instant date = Instant.ofEpochMilli(1549362600000l);
        LocalDateTime utc = LocalDateTime.ofInstant(date, ZoneOffset.UTC);
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.