วิธีการแปลง currentTimeMillis เป็นวันที่ใน Java?


140

ฉันมีมิลลิวินาทีในไฟล์บันทึกบางไฟล์ที่สร้างขึ้นในเซิร์ฟเวอร์ฉันรู้โลแคลจากที่ไฟล์บันทึกถูกสร้างขึ้นปัญหาของฉันคือการแปลงมิลลิวินาทีเป็นวันที่ในรูปแบบที่ระบุ การประมวลผลบันทึกนั้นเกิดขึ้นบนเซิร์ฟเวอร์ที่อยู่ในเขตเวลาที่แตกต่างกัน ในขณะที่กำลังแปลงเป็นโปรแกรม "SimpleDateFormat" กำลังรับวันที่ของเครื่องเนื่องจากวันที่จัดรูปแบบดังกล่าวไม่ได้แสดงเวลาที่ถูกต้องของเซิร์ฟเวอร์ มีวิธีจัดการกับสิ่งนี้อย่างสง่างามไหม?

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));

เอาท์พุท:

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

อย่าสับสนสถานที่กับเขตเวลา แยกจากกันโดยสิ้นเชิง สถานที่เกิดเหตุกำหนดภาษามนุษย์สำหรับชื่อของเดือนและวันและบรรทัดฐานทางวัฒนธรรมเช่นคำสั่งของชิ้นส่วนเช่นเดือนวัน ฯลฯ โซนเวลาถูกชดเชยจาก UTC รวมถึงกฎระเบียบสำหรับการจัดการความผิดปกติเช่นเวลาออมแสง
Basil Bourque

เป็นปัญหาที่จำนวนมิลลิวินาทีไม่นับจาก 1970-01-01T00: 00: 00Z แต่มาจากช่วงเวลาอื่นบ้างไหม?
Basil Bourque

FYI ทั้งคลาสวันเวลาเก่าที่แย่มาก ( GregorianCalendar, SimpleDateFormatฯลฯ ) และห้องสมุด Joda-Time ที่ยอดเยี่ยมตอนนี้ถูกแทนที่ด้วยคลาสjava.time ที่ทันสมัย
Basil Bourque

คำตอบ:


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);

ฉันต้องตั้งค่าปฏิทินเป็นครั้งสุดท้ายเพื่อให้มันใช้งานได้ final Calendar calendar = Calendar.getInstance();
Victor Augusto

4
โดยทั่วไปวัตถุในปฏิทินถือว่ามีขนาดค่อนข้างใหญ่ดังนั้นควรหลีกเลี่ยงเมื่อเป็นไปได้ วัตถุวันที่จะดีกว่าสมมติว่ามันมีฟังก์ชั่นที่คุณต้องการ "Date date = new Date (millis);" ให้ไว้ในคำตอบอื่น ๆ โดยผู้ใช้ AVD จะเป็นเส้นทางที่ดีที่สุด :)
ดิ๊กลูคัส

1
ยังไงก็เถอะสำหรับ1515436200000lฉันcalendar.get(Calendar.MONTH))เป็น0!
Sajib Acharya

FYI, ลำบากชะมัดเก่าชั้นเรียนวันที่เวลาเช่นjava.util.Date, java.util.Calendarและjava.text.SimpleDateFormatตอนนี้มรดกแทนที่โดยjava.timeชั้นเรียนที่สร้างขึ้นใน Java 8 และต่อมา ดูการสอนโดยออราเคิล
Basil Bourque

2
@SajibAcharya โปรดทราบว่าอินสแตนซ์สำหรับ Calendar.MONTH เริ่มต้นที่ 0; คุณต้องเพิ่มอีกหนึ่งเดือนเพื่อให้ได้ของจริง "" ที่เรารู้จัก ตัวอย่าง: 0 = มกราคม, 1 = กุมภาพันธ์, 2 = มีนาคม, ฯลฯ
shagberg

256

คุณอาจจะใช้java.util.Dateระดับและจากนั้นใช้ในการจัดรูปแบบSimpleDateFormatDate

Date date=new Date(millis);

เราสามารถใช้แพ็คเกจjava.time (บทช่วยสอน) - API DateTime ที่แนะนำใน 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
มีประสิทธิภาพมากขึ้น
Chad Bingham

2
Nope วิธีการทั้งหมดไม่ได้รับการjava.util.Dateคิดค่าเสื่อมราคา (มีการปรับปรุง Date & Time APIs ใน JDK8 java.time)
adatapost

1
@RafaelZeffa, '' 'Date (long long)' 'constructor ไม่ได้ถูกคัดค้าน
Gugelhupf

วัตถุวันที่มีไว้เพื่อความเข้ากันได้ย้อนหลัง ควรใช้ปฏิทินตามที่แนะนำไว้ข้างต้น
Ton Snoei

2
FYI, ลำบากชะมัดเก่าชั้นเรียนวันที่เวลาเช่นjava.util.Date, java.util.Calendarและjava.text.SimpleDateFormatตอนนี้มรดกแทนที่โดยjava.timeชั้นเรียนที่สร้างขึ้นใน Java 8 และต่อมา ดูการสอนโดยออราเคิล
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.

รายละเอียด

คำตอบอื่น ๆ ใช้คลาสที่ล้าสมัยหรือไม่ถูกต้อง

หลีกเลี่ยงคลาสวันที่เก่าเช่น java.util.Date/.Calendar พวกเขาได้พิสูจน์แล้วว่าได้รับการออกแบบไม่ดีสับสนและลำบาก

java.time

java.timeกรอบมาสร้างเป็น Java 8 และต่อมา มากของการทำงานเป็นbackported ชวา 6 & 7และต่อไปปรับให้เข้ากับ Android ทำโดยคนกลุ่มเดียวกันกับที่เคยทำJoda-Time Joda

Instantเป็นช่วงเวลาบนไทม์ไลน์ในส่วนUTCมีความละเอียดของนาโนวินาที ยุคของมันคือช่วงเวลาแรกของปี 1970 ใน UTC

สมมติว่าการป้อนข้อมูลของคุณนับมิลลิวินาทีจาก 1970-01-01T00 A: 00: 00Z (ไม่ชัดเจนในคำถาม) จากนั้นเราสามารถ instantiate ได้อย่างง่ายดายInstant

Instant instant = Instant.ofEpochMilli( 1_322_018_752_992L );

instant.toString (): 2011-11-23T03: 25: 52.992Z

Zในการที่มาตรฐานISO 8601สตริงที่จัดรูปแบบสั้นสำหรับZuluและวิธีการUTC UTC

สมัครโซนเวลาที่ใช้ชื่อโซนเวลาที่เหมาะสมZonedDateTimeที่จะได้รับ

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

ดูนี้ใช้รหัสสดที่ IdeOne.com

Asia/Kolkata เขตเวลา ?

ฉันคาดเดาว่าคุณมีเขตเวลาอินเดียที่มีผลต่อรหัสของคุณ เรามาดูกันที่นี่ที่ปรับลงในAsia/Kolkataเขตเวลาทำให้เวลาของวันเดียวกับที่คุณรายงานซึ่งเป็นห้าชั่วโมงครึ่งข้างหน้าของมูลค่า08:55 UTC ของเรา03:25

2011-11-23T08: 55: 52.992 + 05: 30 [เอเชีย / โกลกาตา]

โซนเริ่มต้น

คุณสามารถใช้โซนเวลาเริ่มต้นปัจจุบันของ JVM ระวังที่เริ่มต้นสามารถเปลี่ยนแปลงได้ในช่วงเวลาใดช่วงรันไทม์ รหัสใด ๆ ในเธรดของแอพใด ๆ ภายใน JVM สามารถเปลี่ยนค่าเริ่มต้นปัจจุบันได้ หากสำคัญให้ถามผู้ใช้สำหรับเขตเวลาที่ต้องการ / ที่คาดไว้

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

เกี่ยวกับjava.time

java.timeกรอบถูกสร้างขึ้นใน Java 8 และต่อมา ชั้นเรียนเหล่านี้แย่งลำบากเก่ามรดกเรียนวันที่เวลาเช่นjava.util.Date, และCalendarSimpleDateFormat

Joda เวลาโครงการขณะนี้อยู่ในโหมดการบำรุงรักษาให้คำแนะนำแก่การโยกย้ายไปยังjava.timeชั้นเรียน

ต้องการเรียนรู้เพิ่มเติมโปรดดูที่ออราเคิลกวดวิชา และค้นหา Stack Overflow สำหรับตัวอย่างและคำอธิบายมากมาย สเปกJSR 310

ด้วยไดรเวอร์ JDBC ที่สอดคล้องกับJDBC 4.2หรือใหม่กว่าคุณสามารถแลกเปลี่ยนออบเจ็กต์java.timeโดยตรงกับฐานข้อมูลของคุณ ไม่จำเป็นต้องใช้สตริงหรือคลาส java.sql. *

จะรับคลาส java.time ได้ที่ไหน?

  • Java SE 8 , Java SE 9และใหม่กว่า
    • Built-in
    • เป็นส่วนหนึ่งของ Java API มาตรฐานที่มีการใช้งานแบบรวม
    • Java 9 เพิ่มคุณสมบัติและการแก้ไขเล็กน้อย
  • Java SE 6และ Java SE 7
    • มากของการทำงาน java.time จะกลับรังเพลิง Java 6 และ 7 ในThreeTen-ย้ายกลับ
  • Android
    • การใช้งานชุดบันเดิล Android รุ่นต่อมาของคลาส java.time
    • สำหรับก่อนหน้านี้ของ Android ที่ThreeTenABPโครงการปรับThreeTen-ย้ายกลับ (ดังกล่าวข้างต้น) ดูวิธีการใช้ ThreeTenABP … .

The ThreeTen-Extraขยาย java.time ด้วยคลาสเพิ่มเติม โครงการนี้เป็นพื้นฐานที่พิสูจน์ได้สำหรับการเพิ่มเติมในอนาคตไปยัง java.time คุณอาจพบว่าการเรียนที่มีประโยชน์บางอย่างที่นี่เช่นInterval, YearWeek, YearQuarterและอื่น ๆ อีกมากมาย


การแปลงค้นหาทันใจที่คุณแนะนำด้านบนเป็นโซนเวลาท้องถิ่นที่เป็นค่าเริ่มต้นในอุปกรณ์ (ตัวอย่างเช่นสมาร์ทโฟน) หรือไม่
AJW

1
@AJW ใช่ โทรZoneId.systemDefault(). ดูหัวข้อใหม่ที่เพิ่มไว้ท้ายคำตอบของฉัน
โหระพา Bourque

เยี่ยมมากฉันจะลองดู
AJW

14

วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการใช้คลาส Joda DateTimeและระบุทั้งการประทับเวลาเป็นมิลลิวินาทีและ DateTimeZone ที่คุณต้องการ

ฉันขอแนะนำอย่างยิ่งให้หลีกเลี่ยงคลาส Java Date และ Calendar ในตัว พวกมันแย่มาก


GorgianCalender ไม่ทำงาน ... ไม่ว่าจะด้วยเหตุผลใดก็ตามระบบจะใช้เขตเวลาเริ่มต้น Joda ทำงานได้อย่างสมบูรณ์
Amit

แจ้งให้เราทราบดูรหัสตัวอย่างถ้าเราสามารถทำสิ่งที่แตกต่างกับเกรกอเรียน
Amit

1
FYI, โครงการJoda-Timeขณะนี้อยู่ในโหมดบำรุงรักษา , แนะนำการโยกย้ายไปยังคลาสjava.time ดูการสอนโดยออราเคิล
Basil Bourque

13

หากค่ามิลลิวินาทีเป็นจำนวนมิลลิวินาทีตั้งแต่วันที่ 1 มกราคม 1970 GMT เช่นเดียวกับมาตรฐานสำหรับ JVM แสดงว่าเป็นอิสระจากเขตเวลา หากคุณต้องการจัดรูปแบบด้วยเขตเวลาเฉพาะคุณสามารถแปลงเป็นวัตถุ GregorianCalendar และตั้งค่าเขตเวลา หลังจากนั้นมีวิธีการจัดรูปแบบมากมาย


1
นี่คือตัวอย่างโค้ดที่มี GregorianCalendar และ Joda ฉันได้รับผลลัพธ์ที่ถูกต้องกับ Joda แต่ไม่ใช่กับ Gregorian GregorianCalendar calendar = new GregorianCalendar (TimeZone.getTimeZone ("US / Central")); calendar.setTimeInMillis (yourmilliseconds); DateTime jodaTime = ใหม่ DateTime (yourmilliseconds, DateTimeZone.forTimeZone (TimeZone.getTimeZone ("US / Central")); DateTimeFormatter parser1 = DateTimeFormat.forPattern ("yyyy-MM-dd HH: mm: ss, SSS");
Amit

การตั้งค่าเขตเวลาในวัตถุปฏิทินไม่ทำงาน แต่การตั้งค่าในวัตถุตัวจัดรูปแบบวันที่ทำได้อย่างไร
Bill

DateTime และ DateTimeFormatter คืออะไร?
SweetWisher ツ

11

โซลูชันของฉัน

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

ฉันทำแบบนี้:

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

คุณยังสามารถใช้getDateInstance(int style)กับพารามิเตอร์ต่อไปนี้:

DateFormat.SHORT

DateFormat.MEDIUM

DateFormat.LONG

DateFormat.FULL

DateFormat.DEFAULT


5

คลาส SimpleDateFormat มีวิธีที่เรียกว่า SetTimeZone (TimeZone) ที่สืบทอดมาจากคลาส DateFormat http://docs.oracle.com/javase/6/docs/api/java/text/DateFormat.html


FYI, ชั้นเรียนที่น่ากลัวเหล่านี้จะถูกแทนที่ด้วยชั้นเรียนjava.time ที่ทันสมัยในขณะที่การยอมรับของ JSR 310.
Basil Bourque

5

วิธีที่ง่ายที่สุด:

private String millisToDate(long millis){

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

}

2

ด้านล่างนี้เป็นวิธีการแก้ปัญหาของฉันในการรับวันที่จาก miliseconds ไปเป็นรูปแบบวันที่ คุณต้องใช้ห้องสมุด Jodaเพื่อให้รหัสนี้ทำงาน

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));

   }
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.