การแปลง Long เป็น Date ใน Java จะคืนค่า 1970


119

ฉันมีรายการที่มีค่ายาว (เช่น 1220227200, 1220832000, 1221436800 ... ) ซึ่งฉันดาวน์โหลดจากบริการเว็บ ฉันต้องแปลงเป็นวันที่ น่าเสียดายที่วิธีนี้ตัวอย่างเช่น:

Date d = new Date(1220227200);

คืน 1 ม.ค. 2513 ใครทราบวิธีแปลงอื่นให้ถูกต้อง


คุณบอกได้ไหมว่าคุณคาดหวังคุณค่าอะไร คำถามของวินาที / มิลลิวินาทีอาจเป็นคำถามที่ถูกต้อง แต่ 1220227200 ไม่ใช่ 1/1/1970 ดูเหมือนว่าคุณกำลังส่ง 0 ไปยังตัวสร้าง รหัสเพิ่มเติมบางอย่างอาจช่วยได้
SJuan76

1
@mmmiki - คุณควรยอมรับคำตอบ
Stewart

ส่งคืนวันที่ 15 มกราคม 1970 ที่นี่ไม่ใช่วันที่ 1 มกราคม
njzk2

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

คำตอบ:


161

Dateคอนสตรัค (คลิกที่ลิงค์!) ยอมรับเวลาเป็นlongในมิลลิวินาทีไม่กี่วินาที คุณจำเป็นต้องคูณด้วย 1000 longและให้แน่ใจว่าคุณได้ให้มันเป็น

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

นี่แสดงที่นี่

อา. 31 ส.ค. 20:00:00 GMT-04: 00 2008


22
หรือหรือใช้Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));สำหรับทำความสะอาดและน้อยเวทมนตร์ numberesqueวิธีการแก้ปัญหา
Priidu Neemre

56

TL; DR

java.time.Instant                    // Represent a moment as seen in UTC. Internally, a count of nanoseconds since 1970-01-01T00:00Z.
.ofEpochSecond( 1_220_227_200L )     // Pass a count of whole seconds since the same epoch reference of 1970-01-01T00:00Z.

รู้ข้อมูลของคุณ

ผู้คนใช้ความแม่นยำต่างๆในการติดตามเวลาเป็นตัวเลขตั้งแต่ยุคหนึ่ง ดังนั้นเมื่อคุณได้รับตัวเลขบางส่วนที่จะตีความเป็นจำนวนนับตั้งแต่ยุคหนึ่งคุณต้องกำหนด:

  • ยุคไหน? มีการใช้
    วันที่หลายยุคในระบบต่างๆ ที่ใช้กันทั่วไปคือเวลา POSIX / Unixโดยที่ epoch เป็นช่วงเวลาแรกของปี 1970 ใน UTC แต่คุณไม่ควรถือว่ายุคนี้
  • ความแม่นยำอะไร
    เรากำลังพูดถึงวินาทีมิลลิวินาที , ไมโครหรือนาโนวินาทีตั้งแต่ยุค?
  • เขตเวลาอะไร?
    โดยปกติจะนับเนื่องจาก epoch อยู่ในเขตเวลาUTC / GMT นั่นคือไม่มีการชดเชยเขตเวลาเลย แต่ในบางครั้งเมื่อเกี่ยวข้องกับโปรแกรมเมอร์ที่ไม่มีประสบการณ์หรือวัน - เวลาที่ไม่รู้อาจมีเขตเวลาโดยนัย

ในกรณีของคุณตามที่คนอื่น ๆ กล่าวไว้ดูเหมือนว่าคุณจะได้รับไม่กี่วินาทีนับตั้งแต่ยุค Unix แต่คุณกำลังผ่านวินาทีเหล่านั้นไปยังตัวสร้างที่คาดว่าจะเป็นมิลลิวินาที วิธีแก้ก็คือคูณด้วย 1,000

บทเรียนที่ได้รับ:

  • กำหนดไม่ถือว่าความหมายของข้อมูลที่ได้รับ
  • อ่านเอกสาร

กราฟแสดงรายละเอียดต่างๆของความละเอียดในระบบวันที่ - เวลารวมทั้งวินาทีมิลลิวินาทีไมโครวินาทีและนาโนวินาที

ข้อมูลของคุณ

ข้อมูลของคุณดูเหมือนจะเป็นเวลาทั้งวินาที ถ้าเราสมมติว่าเป็นช่วงต้นของปี 1970 และถ้าเราใช้เขตเวลา UTC 1,220,227,200นั่นคือช่วงเวลาแรกของวันแรกของเดือนกันยายน 2008

Joda เวลา

คลาส java.util.Date และ. ปฏิทินที่มาพร้อมกับ Java นั้นเป็นปัญหาอย่างมาก หลีกเลี่ยงพวกเขา ใช้แทนไลบรารีJoda-Timeหรือแพ็คเกจ java.timeใหม่ที่รวมอยู่ใน Java 8 (และได้รับแรงบันดาลใจจาก Joda-Time)

หมายเหตุที่แตกต่าง juDate เป็นDateTimeใน Joda เวลารู้อย่างแท้จริงของตัวเองที่ได้รับมอบหมายโซนเวลา ดังนั้นในตัวอย่างโค้ด Joda-Time 2.4 ที่เห็นด้านล่างโปรดทราบว่าก่อนอื่นเราจะแยกวิเคราะห์มิลลิวินาทีโดยใช้สมมติฐานเริ่มต้นของ UTC จากนั้นประการที่สองเรากำหนดเขตเวลาของปารีสเพื่อปรับเปลี่ยน ขณะเดียวกันในระยะเวลาของจักรวาล แต่ที่แตกต่างกันเวลาผนังนาฬิกา สำหรับการสาธิตเราปรับอีกครั้งเป็น UTC เกือบจะดีกว่าเสมอในการระบุเขตเวลาที่คุณต้องการ / ที่คาดไว้อย่างชัดเจนแทนที่จะพึ่งพาค่าเริ่มต้นโดยปริยาย (มักเป็นสาเหตุของปัญหาในการทำงานวันที่และเวลา)

เราต้องการมิลลิวินาทีในการสร้าง DateTime ลองป้อนข้อมูลเป็นวินาทีแล้วคูณด้วยหนึ่งพัน โปรดทราบว่าผลที่ได้จะต้องเป็น 64 บิตlongในขณะที่เราจะล้น int32

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

ป้อนจำนวนมิลลิวินาทีให้กับตัวสร้าง ผู้สร้างรายนั้นถือว่าการนับมาจากยุค Unix ของปี 1970 ดังนั้นปรับไทม์โซนตามต้องการหลังจากการก่อสร้าง

ใช้ชื่อเขตเวลาที่ถูกต้องโดยผสมระหว่างทวีปและเมือง / ภูมิภาค อย่าใช้รหัสตัวอักษร 3 หรือ 4 ตัวเช่นรหัสESTที่ไม่เป็นมาตรฐานไม่ซ้ำกัน

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

สำหรับการสาธิตให้ปรับโซนเวลาอีกครั้ง

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

ถ่ายโอนไปยังคอนโซล สังเกตว่าวันที่ในมอนทรีออลแตกต่างกันอย่างไรเนื่องจากวันใหม่ได้เริ่มขึ้นในยุโรป แต่ยังไม่ได้อยู่ในอเมริกา

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

เมื่อเรียกใช้.

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

ผู้ผลิต Joda-Time ได้ขอให้เราย้ายไปใช้กรอบjava.timeแทนทันทีที่สะดวก แม้ว่า Joda-Time จะยังคงได้รับการสนับสนุนอย่างต่อเนื่อง แต่การพัฒนาในอนาคตทั้งหมดจะทำในคลาส java.time และส่วนขยายในโครงการ ThreeTen-Extra

java-time framework ถูกกำหนดโดยJSR 310และสร้างใน Java 8 และใหม่กว่า คลาส java.time ถูกแบ็คพอร์ตไปที่ Java 6 & 7 บนโปรเจ็กต์ ThreeTen-Backportและไปยัง Android ในโปรเจ็กต์ ThreeTenABP

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

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

ใช้offset-from-UTC ZoneOffsetเพื่อรับOffsetDateTimeไฟล์.

ยังดีกว่าถ้าทราบให้ใช้เขตเวลาZoneIdเพื่อรับไฟล์ZonedDateTime.

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

ตารางประเภทวันที่ - เวลาทั้งหมดใน Java ทั้งแบบสมัยใหม่และแบบดั้งเดิม


1
ไชโยเพื่อน คำอธิบายที่ยอดเยี่ยม ฉันได้รับ DateTime ใหม่ (<หมายเลขยาว>) จากปี 1970 เมื่อฉันรู้ว่าฉันให้มันในไม่กี่วินาทีและต้องการเป็นมิลลิวินาที
Suyash Dixit

40

ดูเหมือนความยาวของคุณจะเป็นวินาทีไม่ใช่มิลลิวินาที ตัวสร้างวันที่ใช้เวลาเป็นมิลลิวินาทีดังนั้น

Date d = new Date(timeInSeconds * 1000);

4
@ f1sh: ฉันไม่ได้ลงคะแนน แต่คำตอบเดิมนั้นต่างออกไป เขาแก้ไขภายในระยะเวลาผ่อนผัน 5 นาที
BalusC

ขอขอบคุณสำหรับการชี้แจง. นั่นเป็นข้อเสียของตัวเอง SO มี ... : - /
f1sh

10

กำหนดเวลาเป็นมิลล์บนวัตถุปฏิทินเท่านั้น

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

9

สิ่งเหล่านี้อาจเป็นการประทับเวลาเป็นวินาทีและไม่ใช่ในหน่วยมิลลิวินาทีซึ่งจำเป็นสำหรับตัวสร้างวันที่ (ยาว) ของ java ใหม่ แค่คูณมันด้วย 1,000 คุณก็น่าจะถูกต้อง


23
อย่างถูกต้องมากขึ้น 30000 มิลลิวินาทีช้าเกินไป
SJuan76

5

ค่าแบบยาวส่วนใหญ่จะสอดคล้องกับการประทับเวลาของEpochและค่าคือ:

1220227200 = จันทร์, 01 ก.ย. 2008 00:00:00 GMT

1220832000 = จันทร์, 08 ก.ย. 2551 00:00:00 GMT

1221436800 = จันทร์, 15 ก.ย. 2551 00:00:00 GMT

เราสามารถแปลงค่ายาวเหล่านี้เป็นjava.util.Dateโดยคำนึงถึงความเป็นจริง java.util.Date ใช้มิลลิวินาที - ตามที่บอกไว้ก่อนหน้านี้ แต่มีข้อบกพร่องบางประการเช่นนี้:

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

ตอนนี้เพื่อแสดงวันที่อย่างถูกต้องเราสามารถใช้ java.text.DateFormat ดังภาพประกอบต่อไปนี้:

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

ด้านล่างนี้เป็นผลลัพธ์ของการแสดงค่า long ที่แปลงเป็น java.util.Date โดยไม่ต้องใช้และใช้ 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


3

ลองใช้วิธีนี้ด้วยการปรับรูปแบบวันที่

long longtime = 1212580300;
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddyyHHmm");
Date date = (Date) dateFormat.parseObject(longtime + "");
System.out.println(date);

หมายเหตุ: ตรวจสอบรอบ 24 ชั่วโมงหรือ 12 ชั่วโมง


2

1220227200 ตรงกับ 15 ม.ค. 2523 (และวันที่ใหม่ (1220227200) .toString () ส่งคืน "พฤ. 15 ม.ค. 03:57:07 น. CET 1970") หากคุณส่งค่า long ไปยังวันที่นั่นคือก่อนวันที่ 01/01/1970 ในความเป็นจริงมันจะส่งคืนวันที่ 01/01/1970 ตรวจสอบให้แน่ใจว่าค่าของคุณไม่อยู่ในสถานการณ์นี้ (ต่ำกว่า 82800000)


0

วันที่ใหม่ (ตัวเลข) จะแสดงวันที่ที่เป็นnumberมิลลิวินาทีหลังวันที่ 1 มกราคม 1970 รูปแบบวันที่คุณไม่ได้แสดงชั่วโมงนาทีและวินาทีเพื่อให้คุณเห็นว่ามันเป็นเพียงเล็กน้อยหลังจากวันที่ 1 มกราคม 1970

คุณต้องแยกวิเคราะห์วันที่ตามการกำหนดเส้นทางการแยกวิเคราะห์ที่ถูกต้อง ฉันไม่รู้ว่า 1220227200 คืออะไร แต่ถ้าเป็นวินาทีหลังจากวันที่ 1 ม.ค. 1970 ให้คูณด้วยเพื่อให้ได้มิลลิวินาที หากไม่เป็นเช่นนั้นให้แปลงเป็นมิลลิวินาทีหลังจากปี 1970 (หากคุณต้องการใช้ java.util.Date ต่อไป)


0

ใช้ได้ผลสำหรับฉัน คุณอาจต้องการคูณด้วย 1,000 เนื่องจากสิ่งที่คุณได้รับคือวินาทีจากปี 1970 และคุณต้องผ่านมิลลิวินาทีตั้งแต่ ม.ค. 1 1970

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