จะรับช่วงเวลาปัจจุบันในรูปแบบ ISO 8601 ด้วยวันที่ชั่วโมงและนาทีได้อย่างไร


323

วิธีที่ดีที่สุดในการรับการนำเสนอในรูปแบบISO 8601ของช่วงเวลาปัจจุบันคือ UTC คืออะไร? 2010-10-12T08:50Zมันควรมีลักษณะดังนี้:

ตัวอย่าง:

String iso8601 = DateFormat.getDateTimeInstance(DateFormat.ISO_8601).format(date);


5
@marcolopes ระวังการใช้ a private static SimpleDateFormatไม่ปลอดภัยเธรด
vegemite4me

สำเนาซ้ำที่เป็นไปได้ของการแปลงสตริงตามมาตรฐาน ISO 8601 เป็น java.util.Date
Antonio

คล้ายกับคำถามอื่น ๆ นี้แต่คำถามหนึ่งตัดให้ทั้งวินาทีในขณะที่คำถามนี้ตัดให้เต็มทั้งนาที
Basil Bourque

คำตอบ:


292

ใช้SimpleDateFormatเพื่อจัดรูปแบบDateวัตถุใด ๆ ที่คุณต้องการ:

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"); // Quoted "Z" to indicate UTC, no timezone offset
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

การใช้new Date()ตามที่แสดงด้านบนจะจัดรูปแบบเวลาปัจจุบัน


8
@ โจอาคิมด้านลบของวิธีการ "มาตรฐาน" นี้คือฉันต้องมีอินสแตนซ์จำนวนมาก"yyyy-MM-dd'T'HH:mmZ"ในแอปพลิเคชันของฉันทุกครั้งที่ฉันต้องการวันที่จัดรูปแบบ ISO-8601 ด้วย JodaTime อย่างที่ฉันเห็นฉันสามารถใช้ตัวจัดรูปแบบที่กำหนดไว้ล่วงหน้าISODateTimeFormatซึ่งทำหน้าที่นี้ให้กับฉัน ..
yegor256

8
@Joachim, Zเป็นรูปแบบที่ถูกต้องใน SimpleDateFormat yyyy-MM-dd'T'HH:mm'Z'แทนที่จะทำเช่นนี้:
Buhake Sindi

33
-1 สิ่งนี้จะให้วันที่ / เวลาในเขตเวลาปัจจุบันไม่ใช่ UTC คำตอบของ Carlos รวมถึงรหัส UTC ที่จำเป็น
Scott Rippey

16
ฉันเพิ่งแก้ไขข้อผิดพลาดของเขตเวลา - เนื่องจากเป็นคำตอบที่ยอมรับได้ฉันคิดว่ามันเป็นสิ่งที่ถูกต้องที่จะทำ
คณะกรรมการ บริษัท

2
The Z ต้องถูกยกมาเช่น "yyyy-MM-dd'T'HH: mm'Z '"
Kimball Robinson

224

สำหรับระบบที่เขตเวลาเริ่มต้นไม่ใช่ UTC:

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

SimpleDateFormatเช่นอาจมีการประกาศเป็นค่าคงที่ทั่วโลกถ้าจำเป็นบ่อย แต่ระวังว่าชั้นนี้ไม่ด้ายปลอดภัย จะต้องมีการซิงโครไนซ์หากมีการเข้าถึงหลายเธรดพร้อมกัน

แก้ไข: ฉันต้องการ Joda Time หากทำการปรับแต่งเวลา / วันที่แตกต่างกันมากมาย ...
แก้ไข 2: แก้ไขแล้ว: setTimeZoneไม่ยอมรับสตริง (แก้ไขโดย Paul)


9
รูปแบบนี้ไม่คงที่ในห้องสมุดบางแห่งในตัวใช่ไหม
Daniel Kaplan

มีสองแพ็คเกจที่แตกต่างกันสำหรับ 'DateFormat' อย่าลืมใช้ 'import java.text.DateFormat'
oabarca

3
หากคุณต้องการให้เขตเวลาปัจจุบันใช้ TimeZone tz = TimeZone.getDefault (); แทน
oabarca

คุณไม่ควรอ้างอิงเครื่องหมาย 'Z' ในรูปแบบเนื่องจากทำให้ไม่มีนัยสำคัญเชิงตรรกะ หาก TimeZone เป็น UTC ดังตัวอย่างข้างต้น Z ที่ไม่มีเครื่องหมายจะให้ผลลัพธ์เป็น Z ในผลลัพธ์ ... เป็น หากระบบการบริโภคอ่าน Z เป็น UTC แต่เวลาไม่ใช่เวลาจะเปลี่ยน ในทางกลับกันถ้า parser ใช้ Z ที่ยกมาโดยไม่ต้องตั้งค่า TimeZone มันจะแยกเวลา UTC เป็นเวลาท้องถิ่น (เปลี่ยนอีกครั้ง) คำพูดนี้ไม่จำเป็นถ้ามีการตั้งค่า TZ แต่เป็นอันตรายถ้ามันไม่ได้
Matt Whipple

@MattWhipple - แต่ถ้าคุณใช้ Z ที่ไม่ได้2016-06-14T13:56+0000ใส่เครื่องหมายคำถามผลลัพธ์จะเป็นเช่นนั้น- คำถามกำลังถามหาสิ่งที่คล้ายกัน2016-06-14T13:56Z
user85421

184

Java 8 Native

java.timeทำให้มันง่ายตั้งแต่ Java 8 และเธรดที่ปลอดภัย

ZonedDateTime.now( ZoneOffset.UTC ).format( DateTimeFormatter.ISO_INSTANT )

ผลลัพธ์: 2015-04-14T11:07:36.639Z

คุณอาจถูกล่อลวงให้ใช้ไฟแช็กTemporalเช่นInstantหรือLocalDateTimeแต่ขาดการสนับสนุนฟอร์แมตเตอร์หรือข้อมูลโซนเวลา ใช้ZonedDateTimeงานได้นอกกรอบเท่านั้น

ด้วยการปรับแต่งหรือผูกมัดตัวเลือก / การทำงานของZonedDateTimeและDateTimeFormatterคุณสามารถควบคุมเขตเวลาและความแม่นยำได้อย่างง่ายดายในระดับหนึ่ง:

ZonedDateTime.now( ZoneId.of( "Europe/Paris" ) )
             .truncatedTo( ChronoUnit.MINUTES )
             .format( DateTimeFormatter.ISO_DATE_TIME )

ผลลัพธ์: 2015-04-14T11:07:00+01:00[Europe/Paris]

ข้อกำหนดที่ผ่านการปรับแต่งแล้วเช่นการลบส่วนที่สองจะยังคงต้องแสดงตามรูปแบบที่กำหนดเองหรือกระบวนการโพสต์ที่กำหนดเอง

.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) // 2015-04-14T11:07:00
.format( DateTimeFormatter.ISO_LOCAL_DATE ) // 2015-04-14
.format( DateTimeFormatter.ISO_LOCAL_TIME ) // 11:07:00
.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm" ) ) // 2015-04-14 11:07

สำหรับ Java 6 & 7 คุณอาจพิจารณากลับพอร์ตของ java.time เช่นThreeTen-ย้ายกลับซึ่งยังมีพอร์ต Android ทั้งคู่เบากว่า Joda และเรียนรู้จากประสบการณ์ของ Joda - esp. พิจารณาว่า java.time นั้นออกแบบโดยผู้เขียนของ Joda


9
คำตอบที่ดี. สังเกตเห็นนิสัยที่ดีของการระบุเขตเวลาอย่างชัดเจนแทนที่จะพึ่งพาปริยายในเขตเวลาเริ่มต้นปัจจุบันของ JVM คุณอาจจะระบุโซนเวลาโดยเฉพาะอย่างยิ่งZoneId.of( "America/Montreal" )ถ้าต้องการเช่น
Basil Bourque

1
อนุญาตให้ฟอร์แมตในรูปแบบ ISO 8601 ได้ทันทีโดยเรียกวิธีการ. toString ():return DateTimeFormatter.ISO_INSTANT.format(this);
VadymVL

สิ่งนี้ดีที่สุดเพราะคุณหลีกเลี่ยงค่าเริ่มต้น
Christophe Roussy

6
คำเตือน: โซลูชันสำหรับ Java 8 ที่ใช้ ISO_INSTANT มีมุมที่น่ารำคาญ เมื่อมิลลิวินาทีเกิดเป็น 0 จะไม่รวมอยู่ในเอาต์พุต สิ่งนี้ได้รับอนุญาตตามมาตรฐาน ISO 8601 แต่ห้องสมุดและตัวแยกวิเคราะห์จำนวนมากในภาษาอื่น ๆ นั้นไม่ได้ให้อภัย หากจำเป็นต้องรวมศูนย์ให้ใช้สิ่งนี้แทน: DateTimeFormatter ISO_8601 = ofPattern ("yyyy-MM-dd'T'HH: mm: ss.SSSX") withZone (UTC);
jurgen

หลังจากที่เปลี่ยนจาก Java 8-11 ผมเห็นDateTimeFormatter.ISO_INSTANTและDateTimeFormatter.ISO_DATE_TIMEใช้ 6 หลักหลังจากวินาทีเมื่อเทียบกับ 3 @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)ซึ่งไม่ได้หยิบขึ้นมาจากฤดูใบไม้ผลิ
DanielM

126

Java 8:

thisMoment = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mmX")
                              .withZone(ZoneOffset.UTC)
                              .format(Instant.now());

Pre Java 8:

thisMoment = String.format("%tFT%<tRZ",
                           Calendar.getInstance(TimeZone.getTimeZone("Z")));

จากเอกสาร :

'R'    เวลาที่จัดรูปแบบสำหรับนาฬิกาแบบ 24 ชั่วโมงใน
'F'    รูปแบบ "% tH :% tM" ISO 8601 วันที่จัดรูปแบบเป็น "% tY-% tm-% td"


26
ไม่ว่าคุณจะมีห้องสมุดบุคคลที่สามเป็นพิเศษสำหรับการพึ่งพาโครงการของคุณ (ซึ่งคุณอาจต้องการติดตามและจัดส่งพร้อมกับใบสมัครของคุณเอาล่ะมันเป็นเพียง 3.2 เมกะไบต์) และทำ DateTime dt = new DateTime(); DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); String str = fmt.print(dt);หรือคุณแค็ปซูลreturn String.format("%tFT%<tRZ", new Date());เข้าชั้นเรียนและทำstr = Iso8601Time.now()ตามที่คุณต้องการ (ไม่ใช่ว่ารูปแบบ ISO จะเปลี่ยนไป) หากปรากฎว่าคุณต้องการวันที่มากกว่าปัจจุบันในรูปแบบ ISO ให้ใช้ lib
aioobe

2
เห็นด้วยกับสิ่งนี้โดยสิ้นเชิง
yegor256

3
โปรดทราบว่าเป็นไปได้ที่จะเปลี่ยนคำตอบที่ทำเครื่องหมายว่ายอมรับ ;-)
aioobe

8
%tFT%<tTZจะรวมถึงวินาที; %tFT%<tTZ.%<tLจะรวมมิลลิวินาที
Patrick Linskey

2
วิธีการแก้ปัญหาอย่างมากควรจะเป็นคำตอบที่ได้รับการยอมรับโดยขณะนี้ :)
AbdelHady

94

ในฐานะของ Java 8 คุณสามารถทำ:

Instant.now().toString();

จากjava.time.Instantเอกสาร:

ตอนนี้

public static Instant now()

รับทันทีปัจจุบันจากนาฬิการะบบ

สิ่งนี้จะทำการสืบค้นนาฬิกา UTC ของระบบเพื่อรับข้อมูลปัจจุบันทันที

 


public String toString()

การแทนค่าสตริงของ instant นี้โดยใช้การแทนค่า ISO-8601

DateTimeFormatter.ISO_INSTANTรูปแบบที่ใช้เป็นเช่นเดียวกับ


11
นี่คือคำตอบที่ถูกต้องและมันเป็นเรื่องอื้อฉาวว่ามันไม่ได้รับการ upvoted สูงกว่า SimpleDateFormatsconcocted
David Moles

ดีใจที่ได้อ่านคำตอบเพิ่มเติม ฉันเห็นด้วยนี่ควรเป็นคำตอบตอนนี้
Xan-Kun Clark-Davis

และเพราะtoStringในหลาย ๆ กรณีคุณไม่จำเป็นต้องเรียกมันอย่างชัดเจน
kaya3

1
คำเตือนในความคิดเห็นเกี่ยวกับคำตอบก่อนหน้านี้ที่นี่เช่นกัน: "คำเตือน: วิธีแก้ปัญหาสำหรับ Java 8 ที่ใช้ ISO_INSTANT มีมุมที่น่ารำคาญเมื่อมิลลิวินาทีเป็น 0 พวกเขาจะไม่รวมอยู่ในผลลัพธ์ซึ่งอนุญาตตาม ISO 8601 มาตรฐาน แต่มีไลบรารีและตัวแยกวิเคราะห์จำนวนมากในภาษาอื่น ๆ ที่ไม่ให้อภัย "
Dave L.

27

ใช้JodaTime

ระบบปฏิทิน ISO 8601 คือการใช้งานเริ่มต้นภายใน Joda-Time

นี่คือเอกสารสำหรับฟอร์แมต JodaTime

แก้ไข:

หากคุณไม่ต้องการเพิ่มหรือถ้าคุณไม่เห็นคุณค่าของการเพิ่มห้องสมุดด้านบนคุณสามารถใช้SimpleDateFormatคลาสที่สร้างขึ้นเพื่อจัดรูปแบบวันที่เป็นรูปแบบ ISO ที่ต้องการ

ตามที่แนะนำโดย @Joachim Sauer

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
String nowAsString = df.format(new Date());

3
และคุณจะสร้างรูปแบบของสตริงตามที่แสดงในคำถามได้อย่างไร
Joachim Sauer

4
ฉันว่าจะไม่เพิ่มการพึ่งพาไลบรารีสำหรับสิ่งที่ง่ายเช่นนี้ (ซึ่งสามารถทำได้ด้วยสองบรรทัดของรหัสจาวา) (แน่นอนว่าถ้าความต้องการเพิ่มขึ้นมันเป็นอีกเรื่องหนึ่ง)
aioobe

1
@aioobe ถ้ามันเพิ่งใช้ในหลาย ๆ ส่วนของแอปมันก็โอเคที่จะเริ่มต้นในกรณีที่เหลือ jodatime จะดีกว่า
Jigar Joshi

5
@aioobe jodatime ดีกว่าไม่ว่าในกรณีใดเพราะมีISODateTimeFormat- ฟอร์แมตที่กำหนดไว้ล่วงหน้าของ ISO-8601
yegor256

3
@ org.life.java: ซึ่งเกี่ยวข้องเฉพาะเมื่อคุณสามารถเปลี่ยนเป็นเวลา Jode ได้ คุณจะไม่มีพวกมันเมื่อคุณใช้ฟังก์ชั่นเวลาของ Joda เท่านั้น
Joachim Sauer

20

DateFormatUtilsจาก Apache commons-lang3มีค่าคงที่ที่มีประโยชน์เช่น:DateFormatUtils.ISO_DATETIME_FORMAT


3
แม่นยำยิ่งขึ้นช่วงเวลาปัจจุบันใน UTC: DateFormatUtils.format(new Date(), "yyyy-MM-dd'T'HH:mm'Z'", TimeZone.getTimeZone("UTC"));ช่วงเวลาปัจจุบันในโซนเวลาเริ่มต้น: DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(new Date()); @ yegor256 ขอบคุณที่กล่าวถึงการDateFormatUtilsมี apache ในคอมมอนส์-lang มันคุ้มค่าที่จะใช้รูปแบบวันที่
babinik

19

หากคุณไม่ต้องการรวม Jodatime (ดีเท่าที่เป็นอยู่)

javax.xml.bind.DatatypeConverter.printDateTime(
    Calendar.getInstance(TimeZone.getTimeZone("UTC"))
);

ซึ่งส่งคืนสตริงของ:

2012-07-10T16:02:48.440Z

ซึ่งแตกต่างจากคำขอเดิมเล็กน้อย แต่ยังคง ISO-8601



10

Joda เวลา

อัปเดต:โครงการJoda-Timeอยู่ในโหมดบำรุงรักษาโดยทีมงานให้คำแนะนำการย้ายถิ่นไปยังคลาสjava.time สำหรับ Java 6 & 7 ดูที่โครงการThreeTen-Backportดัดแปลงเพิ่มเติมสำหรับ Android ในโครงการThreeTenABP

กำลังใช้ห้องสมุดJoda-Time ...

String output = new DateTime( DateTimeZone.UTC ).toString() ;

นี่คือเธรดที่ปลอดภัย Joda-Time สร้างวัตถุที่เปลี่ยนไม่ได้ใหม่แทนที่จะเปลี่ยนวัตถุที่มีอยู่

หากคุณตั้งใจจะขอรูปแบบโดยไม่ต้องวินาทีให้แก้ไขเป็นนาทีจากนั้นใช้ตัวจัดรูปแบบในตัวอื่น ๆ อีกมากมายใน Joda-Time

DateTime now = new DateTime( DateTimeZone.UTC ) ;
String output = ISODateTimeFormat.dateHourMinute.print( now ) ;

java.time

สำหรับ Java 8 และใหม่กว่า Joda-Time ยังคงทำงานต่อไป แต่เฟรมเวิร์กjava.timeในตัวจะแทนที่ Joda-Time ดังนั้นโอนย้ายรหัสของคุณจาก Joda-Time เป็น java.time ทันทีที่สะดวก

ดูคำตอบอื่น ๆ ของฉันสำหรับวิธีการแก้ปัญหาที่ทันสมัย


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

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

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

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

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

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

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

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


7

สำหรับ Java เวอร์ชัน 7

คุณสามารถปฏิบัติตามเอกสารของ Oracle: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

X - ใช้สำหรับเขตเวลา ISO 8601

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

System.out.println(nowAsISO);

DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
//nowAsISO = "2013-05-31T00:00:00Z";
Date finalResult = df1.parse(nowAsISO);

System.out.println(finalResult);

5

คุณสามารถใช้SimpleDateFormatของ Java ด้วยรูปแบบต่อไปนี้yyyy-MM-dd'T'HH:mm:ssXXXสำหรับ ISO 8601

โค้ดตัวอย่าง: (แสดงรายการสำหรับเขตเวลาทั้งหมดที่มี)

for (String timeZone : TimeZone.getAvailableIDs())
{
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    dateFormat.setTimeZone(TimeZone.getTimeZone(timeZone));
    String formatted = dateFormat.format(new Date());
    System.out.print(formatted);

    if (formatted.endsWith("Z"))
    {
        // These time zone's have offset of '0' from GMT.
        System.out.print("\t(" + timeZone + ")");
    }

    System.out.println();
}

คุณสามารถใช้:

TimeZone.getDefault ()

สำหรับเขตเวลา vm เริ่มต้น เพิ่มเติมที่นี่

'Z'คุณอาจสังเกตเห็นวันเวลาสำหรับโซนเวลาไม่กี่ที่ลงท้ายด้วย เขตเวลาเหล่านี้ชดเชย'0'จาก GMT

ข้อมูลเพิ่มเติมสามารถพบได้ที่นี่


5

ฉันเชื่อว่าวิธีที่ง่ายที่สุดคือไปที่ทันทีและสตริงเช่น:

String d = new Date().toInstant().toString();

ซึ่งจะส่งผลให้:

2017-09-08T12:56:45.331Z


4
หากคุณต้องการเวลาปัจจุบันไม่จำเป็นต้องผ่านDateวัตถุที่ล้าสมัย Instant.now().toString()เพียงแค่ทำ หากคุณได้รับDateจาก API แบบดั้งเดิมวิธีการของคุณจะดีที่สุด
Ole VV

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

5

TL; DR

บางส่วนของคำตอบอื่น ๆ นั้นถูกต้องในการแนะนำคลาสjava.timeแต่ไปใช้ความยาวที่ไม่จำเป็นสำหรับความต้องการเฉพาะ

Instant.now()                               // Capture the current moment in UTC with a resolution as fines nanoseconds but usually in microseconds or milliseconds.
       .truncatedTo( ChronoUnit.MINUTES )   // Lop off any seconds or fractional second, to get a value in whole minutes.
       .toString()                          // Generate a String in standard ISO 8601 format where a `T` separates the year-month-day from the hour-minute-second, and the `Z` on the end for “Zulu” means UTC.

2018-01-23T12: 34Z

Instant::toString

jav.time.Instantชั้นหมายถึงช่วงเวลาใน UTC เสมอในเวลา UTC

Instant instant = Instant.now() ;

instant.toString (): 2018-01-23T12: 34: 56.123456Z

Zที่สิ้นสุดของสตริงตัวอย่างเช่นคุณ2010-10-12T08:50Zจะออกเสียง“ซูลู” และวิธีการUTC

รูปแบบที่คุณต้องการที่เกิดขึ้นเพื่อให้สอดคล้องกับมาตรฐาน ISO 8601มาตรฐาน java.timeเรียนใช้รูปแบบมาตรฐานเหล่านี้โดยค่าเริ่มต้นเมื่อแยกวิเคราะห์ / สร้างสตริง ไม่จำเป็นต้องระบุรูปแบบการจัดรูปแบบ เพียงโทรInstant::toStringตามที่เห็นด้านบน

หากคุณต้องการทั้งนาทีโดยเฉพาะโดยไม่มีวินาทีหรือเสี้ยววินาทีให้ตัดทอน ระบุหน่วยเวลาผ่านChronoUnitคลาส

Instant instant = Instant.now().truncatedTo( ChronoUnit.MINUTES ) ;
String output = instant.toString();  // Generate a `String` object in standard ISO 8601 format.

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

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

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

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

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

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

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

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


2

นี่คือคลาสทั้งหมดที่ได้รับการปรับเพื่อให้การเรียกใช้ "now ()" ไม่ได้ทำอะไรมากไปกว่านี้

public class Iso8601Util
{
    private static TimeZone tz = TimeZone.getTimeZone("UTC");
    private static DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");

    static
    {
        df.setTimeZone(tz);
    }

    public static String now()
    {
        return df.format(new Date());
    }
}

9
การทำให้เป็นแบบสแตติกอาจทำให้เกิดปัญหาเนื่องจาก SimpleDateFormat ไม่ปลอดภัยสำหรับเธรด: "รูปแบบวันที่ไม่ได้ถูกซิงโครไนซ์ขอแนะนำให้สร้างอินสแตนซ์รูปแบบแยกต่างหากสำหรับแต่ละเธรดหากหลายเธรดเข้าถึงรูปแบบพร้อมกัน docs.oracle.com/javase/7/docs/api/java/text/…
Juha Palomäki

2
ดังที่ @Juha Palomäkiพูดถึงสิ่งนี้ไม่ใช่ threadsafe หากคุณใช้ Java 8 หรือสูงกว่าThreadLocal.withInitialสามารถแก้ไขได้ หากคุณใช้ Java 7 หรือต่ำกว่าให้สร้าง ThreadLocal ใหม่และระบุค่าเริ่มต้นด้วยการแทนที่ThreadLocal.initialValue
user393274

@ user393274 - ถ้าคุณกำลังใช้ Java 8 คุณควรใช้Instant, DateTimeFormatและอื่น ๆ หัวข้อที่ทันสมัยทดแทนปลอดภัย

ฉันสับสนเล็กน้อยกับปัญหาที่เกิดขึ้นกับ SimpleDateFormat ที่ไม่ปลอดภัยสำหรับเธรด หากสองเธรดเรียกใช้งาน initializer แบบสแตติกในเวลาเดียวกันฉันไม่สามารถเห็นสิ่งที่เลวร้ายยิ่งกว่าตัวสร้าง SimpleDateFormat ที่ถูกเรียกสองครั้ง แต่มีเพียงหนึ่งอินสแตนซ์เดียวเท่านั้น
gilbertpilz

2
private static String getCurrentDateIso()
{
    // Returns the current date with the same format as Javascript's new Date().toJSON(), ISO 8601
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    return dateFormat.format(new Date());
}

1

ถึงกระนั้น joda-time จะรองรับรูปแบบเพิ่มเติมเท่านั้น: "2015-12-09T00: 22: 42.930Z" ไม่ใช่พื้นฐาน: "20151209T002242.930Z" ... เราอาจจะดีกว่าที่จะทดสอบรายการรูปแบบด้วย java SimpleDateFormat


1

ฉันทำใน Android โดยใช้ปฏิทินและ SimpleDateFormat วิธีการต่อไปนี้จะคืนค่าปฏิทินด้วยเขตเวลา "GMT" (นี่คือเขตเวลาสากล) จากนั้นคุณสามารถใช้คลาส Calendar เพื่อตั้งค่าชั่วโมงระหว่างเขตเวลา differents โดยใช้เมธอด setTimeZone () ของคลาส Calendar

private static final String GMT = "GMT";
private static final String DATE_FORMAT_ISO = "yyyyMMdd'T'HHmmss";

public static Calendar isoToCalendar(final String inputDate) {
    Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(GMT));
    try {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_ISO, Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone(GMT));
        Date date = dateFormat.parse(inputDate);
        calendar.setTime(date);
    } catch (ParseException e) {
        Log.e("TAG",e.getMessage());
    }
    return calendar;
}

โปรดจำไว้: คลาส Date ไม่ทราบเกี่ยวกับการมีอยู่ของ TimeZone ด้วยเหตุผลนี้หากคุณทำการดีบักวันที่หนึ่งคุณจะเห็นวันที่สำหรับเขตเวลาปัจจุบันของคุณ


1

หากคุณสนใจเกี่ยวกับประสิทธิภาพฉันสร้างห้องสมุดที่มีประสิทธิภาพสูงกว่าตัวแยกวิเคราะห์ Java มาตรฐานและตัวจัดรูปแบบในการจัดการกับวันที่จัดรูปแบบ ISO8601 การใช้งาน DatetimeProcessor เป็น thread-safe และสามารถแคชในแผนที่พร้อมกันหรือเขตข้อมูลแบบคงที่

<dependency>
  <groupId>com.axibase</groupId>
  <artifactId>date-processor</artifactId>
  <version>1.0.3</version>
</dependency>
import com.axibase.date.DatetimeProcessor;
import com.axibase.date.PatternResolver;
import org.junit.Before;
import org.junit.Test;

import java.time.Clock;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class DateFormatTest {
    private Clock clock;

    @Before
    public void prepare() {
        clock = Clock.fixed(Instant.ofEpochMilli(1571285405300L), ZoneId.of("Europe/Berlin"));
    }

    @Test
    public void testIsoMillis(){
        final DatetimeProcessor formatter = PatternResolver.createNewFormatter("iso");
        assertThat(formatter.print(clock.millis(), ZoneOffset.UTC), is("2019-10-17T04:10:05.300Z"));
    }

    @Test
    public void testIsoMillisLocalZone(){
        final DatetimeProcessor formatter = PatternResolver.createNewFormatter("iso");
        assertThat(formatter.print(clock.millis(), clock.getZone()), is("2019-10-17T06:10:05.300+02:00"));
    }

    @Test
    public void testIsoMinutes(){
        final DatetimeProcessor formatter = PatternResolver.createNewFormatter("yyyy-MM-ddTHH:mmXXX");
        assertThat(formatter.print(clock.millis(), ZoneOffset.UTC), is("2019-10-17T04:10Z"));
    }
}

0

พวกเขาควรเพิ่มวิธีง่าย ๆ ในการเปลี่ยนจาก Date เป็น Instant และวิธีที่เรียกว่าtoISO8601ซึ่งเป็นสิ่งที่ผู้คนจำนวนมากกำลังมองหา เป็นส่วนเสริมของคำตอบอื่น ๆ จากรูปแบบ java.util.Date ถึง ISO 8601:

Instant.ofEpochMilli(date.getTime()).toString();

ไม่สามารถมองเห็นได้จริงเมื่อใช้การทำให้สมบูรณ์อัตโนมัติ แต่ java.time.Instant.toString()::

การแทนค่าสตริงของ instant นี้โดยใช้ ISO-8601


0
DateTimeFormatter.ISO_DATE_TIME
        .withZone(ZoneOffset.UTC)
        .format(yourDateObject.toInstant())

ในขณะที่รหัสนี้อาจตอบคำถาม แต่มีบริบทเพิ่มเติมเกี่ยวกับสาเหตุและ / หรือวิธีการที่รหัสนี้ตอบคำถามช่วยปรับปรุงมูลค่าระยะยาว
Vishal Chhodwani

-2

ลองนี้

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSZ");
        String date=sdf.format (new Date() );

มันสำหรับรูปแบบ ISO 8601


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