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
ในขณะที่เราจะล้น int
32
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 );