Làm cách nào để có được khoảnh khắc hiện tại ở định dạng ISO 8601 với ngày, giờ và phút?


323

Cách thanh lịch nhất để có được bản trình bày định dạng ISO 8601 của thời điểm hiện tại, UTC là gì? Nó sẽ trông giống như : 2010-10-12T08:50Z.

Thí dụ:

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


5
@marcolopes Hãy coi chừng, việc sử dụng a private static SimpleDateFormatkhông phải là chủ đề an toàn.
vegemite4me


Tương tự như Câu hỏi khác , nhưng câu hỏi này cắt ngắn toàn bộ giây trong khi Câu hỏi này cắt ngắn toàn bộ phút.
Basil Bourque

Câu trả lời:


292

Sử dụng SimpleDateFormatđể định dạng bất kỳ Dateđối tượng bạn muốn:

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

Sử dụng new Date()như hiển thị ở trên sẽ định dạng thời gian hiện tại.


8
@Joachim Mặt tiêu cực của phương pháp "tiêu chuẩn" này là tôi phải có nhiều phiên bản "yyyy-MM-dd'T'HH:mmZ"trong ứng dụng của mình, mỗi khi tôi cần một ngày được định dạng ISO-8601. Với JodaTime, như tôi thấy, tôi có thể sử dụng một trình định dạng được xác định trước ISODateTimeFormat, công việc này giúp tôi ..
yegor256

8
@Joachim, Zlà mẫu hợp lệ trong SimpleDateFormat, thay vì làm điều này : yyyy-MM-dd'T'HH:mm'Z'.
Buhake Sindi

33
-1 Điều này cung cấp cho bạn ngày / giờ trong múi giờ hiện tại - không phải UTC. Câu trả lời của Carlos bao gồm mã UTC cần thiết.
Scott Rippey

16
Tôi chỉ sửa lỗi múi giờ - vì đó là câu trả lời được chấp nhận nên tôi nghĩ đó là điều đúng đắn.
BoD

2
Chữ Z cần được trích dẫn như "yyyy-MM-dd'T'HH: mm'Z '"
Kimball Robinson

224

Đối với các hệ thống có Múi giờ mặc định không phải là 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());

Các SimpleDateFormatví dụ có thể được khai báo là một hằng số toàn cầu nếu cần thiết thường xuyên, nhưng hãy cẩn thận rằng lớp này không phải là thread-safe. Nó phải được đồng bộ hóa nếu được truy cập đồng thời bởi nhiều luồng.

EDIT: Tôi thích Joda Time hơn nếu thực hiện nhiều thao tác Thời gian / Ngày khác nhau ...
EDIT2: đã sửa: setTimeZonekhông chấp nhận Chuỗi (được sửa bởi Paul)


9
Định dạng này không phải là bất cứ nơi nào trong một số thư viện được xây dựng?
Daniel Kaplan

Có hai gói khác nhau cho 'DateFormat', hãy nhớ sử dụng 'nhập java.text.DateFormat'
oabarca

3
Nếu bạn muốn múi giờ hiện tại sử dụng TimeZone tz = TimeZone.getDefault (); thay vào đó
oabarca

Bạn không nên trích dẫn 'Z' theo định dạng vì điều đó làm cho nó không đáng kể về mặt logic. Nếu TimeZone là UTC như trong ví dụ ở trên thì Z không được trích dẫn sẽ chỉ dẫn đến Z ở đầu ra ... tuy nhiên nếu TimeZone không phải là UTC thì Z vẫn sẽ được xuất ra dưới dạng UTC theo nghĩa đen khi thời gian có thể không là. Nếu một hệ thống tiêu thụ đọc Z là UTC nhưng thời gian không phải là thời gian sẽ được thay đổi. Ngược lại, nếu trình phân tích cú pháp sử dụng Z được trích dẫn mà không đặt TimeZone, nó sẽ phân tích thời gian UTC thành giờ địa phương (lại dịch chuyển). Báo giá này không cần thiết nếu TZ được đặt nhưng nguy hiểm nếu không.
Matt Whoop

@MattWhipple - nhưng nếu bạn sử dụng Z không được trích dẫn, kết quả sẽ giống như 2016-06-14T13:56+0000- câu hỏi là yêu cầu một cái gì đó giống như2016-06-14T13:56Z
user85421

184

Bản địa Java 8

java.time làm cho nó đơn giản kể từ Java 8. Và luồng an toàn.

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

Kết quả: 2015-04-14T11:07:36.639Z

Bạn có thể bị cám dỗ để sử dụng nhẹ Temporalnhư Instanthay LocalDateTime, nhưng họ thiếu định dạng hỗ trợ hoặc dữ liệu thời gian khu vực. Chỉ ZonedDateTimehoạt động ra khỏi hộp.

Bằng cách điều chỉnh hoặc xâu chuỗi các tùy chọn / hoạt động của ZencedDateTimeDateTimeFormatter , bạn có thể dễ dàng kiểm soát múi giờđộ chính xác , ở một mức độ nhất định:

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

Kết quả: 2015-04-14T11:07:00+01:00[Europe/Paris]

Các yêu cầu được tinh chỉnh, chẳng hạn như loại bỏ phần giây, vẫn phải được phục vụ bởi các định dạng tùy chỉnh hoặc quy trình bài tùy chỉnh.

.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

Đối với Java 6 & 7, bạn có thể xem xét các cổng sau của java.time, chẳng hạn như ThreeTen-Backport , cũng có cổng Android . Cả hai đều nhẹ hơn Joda, và đã học được từ kinh nghiệm của Joda - đặc biệt. xem xét rằng java.time được thiết kế bởi tác giả của Joda.


9
Câu trả lời tốt. Lưu ý thói quen tốt là chỉ định rõ ràng múi giờ thay vì dựa hoàn toàn vào múi giờ mặc định hiện tại của JVM. Bạn có thể chỉ định một múi giờ cụ thể nếu muốn, chẳng hạn như ZoneId.of( "America/Montreal" ).
Basil Bourque

1
Instant cho phép định dạng nó theo định dạng ISO 8601 chỉ bằng cách gọi phương thức return DateTimeFormatter.ISO_INSTANT.format(this);
.toString

Điều này là tốt nhất bởi vì bạn tránh mặc định.
Barshe Roussy

6
Cảnh báo: Giải pháp cho Java 8 bằng cách sử dụng ISO_INSTANT có một cách giải quyết khó chịu. Khi mili giây xảy ra bằng 0, chúng không được bao gồm trong đầu ra. Điều này được cho phép theo tiêu chuẩn ISO 8601 nhưng nhiều thư viện và trình phân tích cú pháp trong các ngôn ngữ khác không được tha thứ. Nếu cần phải luôn luôn bao gồm các số 0, hãy sử dụng số này thay vào đó: DateTimeFormatter ISO_8601 = ofPotype ("yyyy-MM-dd'T'HH: mm: ss.SSSX"). WithZone (UTC);
jurgen

Sau khi chuyển từ Java 8 sang 11, tôi thấy DateTimeFormatter.ISO_INSTANTDateTimeFormatter.ISO_DATE_TIMEsử dụng 6 chữ số sau các giây, trái ngược với 3, không còn được Spring's chọn @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME).
Daniel

126

Java 8:

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

Trước Java 8:

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

Từ các tài liệu :

'R'    Thời gian được định dạng cho đồng hồ 24 giờ là "% tH:% tM"
'F'    Ngày hoàn thành ISO 8601 được định dạng là "% tY-% tm-% td".


26
Chà, bạn bao gồm một thư viện bên thứ ba bổ sung như là một phụ thuộc cho dự án của bạn (mà bạn có thể muốn cập nhật và gửi cùng với ứng dụng của mình, này, đó chỉ là thêm 3,2 megabyte) và DateTime dt = new DateTime(); DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); String str = fmt.print(dt);bạn sẽ đóng gói return String.format("%tFT%<tRZ", new Date());vào một lớp học, và làm str = Iso8601Time.now(), bất cứ khi nào bạn cần nó. (Không giống như định dạng ISO sẽ thay đổi.) Nếu hóa ra bạn cần nhiều hơn là ngày hiện tại ở định dạng ISO, hãy sử dụng lib.
aioobe

2
Hoàn toàn đồng ý với điều này.
yegor256

3
Lưu ý rằng có thể thay đổi câu trả lời nào được đánh dấu là chấp nhận ;-)
aioobe

8
%tFT%<tTZsẽ bao gồm giây; %tFT%<tTZ.%<tLsẽ bao gồm mili giây.
Patrick Linskey

2
Một giải pháp rất gọn gàng, nên là câu trả lời được chấp nhận ngay bây giờ :)
AbdelHady

94

Kể từ Java 8, bạn có thể chỉ cần làm:

Instant.now().toString();

Từ các java.time.Instanttài liệu:

hiện nay

public static Instant now()

Có được tức thời hiện tại từ đồng hồ hệ thống.

Điều này sẽ truy vấn đồng hồ UTC hệ thống để có được tức thời hiện tại.

 


public String toString()

Một đại diện chuỗi của tức thời này bằng cách sử dụng đại diện ISO-8601.

Các định dạng được sử dụng là giống như DateTimeFormatter.ISO_INSTANT.


11
Đây là câu trả lời đúng, và nó là một vụ bê bối mà nó đã không được nâng cao hơn tất cả những điều này được pha chế SimpleDateFormats.
David Moles

Vui mừng tôi đọc thêm câu trả lời. Tôi đồng ý, đây sẽ là câu trả lời ngay bây giờ.
Xan-Kun Clark-Davis

Và bởi vì toString, trong nhiều trường hợp, bạn thậm chí sẽ không cần gọi nó một cách rõ ràng.
kaya3

1
Cảnh báo trong một nhận xét về câu trả lời trước cũng áp dụng ở đây: "Cảnh báo: Giải pháp cho Java 8 sử dụng ISO_INSTANT có một sự giải quyết khó chịu. Khi mili giây xảy ra là 0, chúng không được bao gồm trong đầu ra. Điều này được cho phép theo ISO 8601 tiêu chuẩn nhưng nhiều thư viện và trình phân tích cú pháp trong các ngôn ngữ khác không phải là thứ tha thứ. "
Dave L.

27

sử dụng JodaTime

Hệ thống lịch ISO 8601 là cài đặt mặc định trong Joda-Time

Đây là tài liệu cho JodaTime Formatter

Biên tập:

Nếu bạn không muốn thêm hoặc nếu bạn không thấy giá trị của việc thêm thư viện ở trên, bạn chỉ có thể sử dụng trong xây dựng SimpleDateFormat lớp để định dạng định dạng Ngày theo yêu cầu ISO

theo đề xuất của @Joachim Sauer

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

3
Và làm thế nào bạn có thể tạo ra một Chuỗi được hình thành như trong câu hỏi?
Joachim Sauer

4
Tôi muốn nói đừng thêm phụ thuộc vào thư viện cho một cái gì đó đơn giản như thế này (có thể đạt được bằng hai dòng mã java). (Chắc chắn, nếu các yêu cầu tăng lên, đó là một câu chuyện khác.)
aioobe

1
@aioobe, nếu nó chỉ được sử dụng trong một số phần của ứng dụng thì bạn có thể sử dụng mặc định, trong trường hợp còn lại thì jodatime sẽ tốt hơn.
Jigar Joshi

5
@aioobe jodatime tốt hơn trong mọi trường hợp, bởi vì nó có ISODateTimeFormat- một định dạng được xác định trước của ISO-8601.
yegor256

3
@ org.life.java: chỉ liên quan khi bạn có thể chuyển sang thời gian Jode đúng cách. Bạn sẽ không có chúng, khi bạn chỉ sử dụng chức năng này của thời gian Joda.
Joachim Sauer

20

DateFormatUtils từ Apache commons-lang3có các hằng số hữu ích, ví dụ:DateFormatUtils.ISO_DATETIME_FORMAT


3
Chính xác hơn, thời điểm hiện tại trong UTC: DateFormatUtils.format(new Date(), "yyyy-MM-dd'T'HH:mm'Z'", TimeZone.getTimeZone("UTC"));thời điểm hiện tại theo múi giờ mặc định : DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(new Date()); @ yegor256 cảm ơn bạn đã đề cập DateFormatUtils, có trên tàu apache commons-lang thật đáng để sử dụng định dạng ngày.
babinik

19

Nếu bạn không muốn bao gồm Jodatime (cũng tốt như vậy)

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

trong đó trả về một chuỗi:

2012-07-10T16:02:48.440Z

khác một chút so với yêu cầu ban đầu nhưng vẫn là ISO-8601.



10

Joda-Thời gian

Cập nhật: Các Joda thời gian dự án hiện đang trong chế độ bảo trì , với đội ngũ tư vấn chuyển đổi sang các java.time lớp. Đối với Java 6 & 7, hãy xem dự án ThreeTen-Backport , được điều chỉnh thêm cho Android trong dự án ThreeTenABP .

Sử dụng thư viện Joda-Time

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

Đây là chủ đề an toàn. Joda-Time tạo ra các đối tượng bất biến mới thay vì thay đổi các đối tượng hiện có.

Nếu bạn thực sự có ý định yêu cầu một định dạng không có giây, giải quyết trong vài phút, thì hãy sử dụng một trong nhiều trình định dạng tích hợp sẵn khác trong Joda-Time.

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

java.time

Đối với Java 8 trở lên, Joda-Time tiếp tục hoạt động. Nhưng java.time tích hợp sẵn khung công tác thay thế Joda-Time. Vì vậy, di chuyển mã của bạn từ Joda-Time sang java.time ngay khi thuận tiện.

Xem câu trả lời khác của tôi cho một giải pháp hiện đại.


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 .

Bạn có thể trao đổi các đối tượng java.time trực tiếp với cơ sở dữ liệu của bạn. Sử dụng trình điều khiển JDBC tương thích với JDBC 4.2 trở lên. Không cần chuỗi, không cần java.sql.*lớp.

Nơi để có được các lớp java.time?

  • Java SE 8 , Java SE 9 , Java SE 10 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 đó (<26), cá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 .


7

Đối với phiên bản Java 7

Bạn có thể làm theo tài liệu của Oracle: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

X - được sử dụng cho múi giờ 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

Bạn có thể sử dụng SimpleDateFormat của Java với mẫu sau yyyy-MM-dd'T'HH:mm:ssXXXcho ISO 8601.

Mã mẫu: (liệt kê ra cho tất cả các múi giờ khả dụng)

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

Bạn đã có thể sử dụng:

TimeZone.getDefault ()

cho múi giờ vm mặc định. Thêm ở đây

Bạn có thể nhận thấy thời gian ngày cho một vài múi giờ kết thúc bằng 'Z'. Các múi giờ này có độ lệch '0'từ GMT.

Thêm thông tin có thể được tìm thấy ở đây .


5

Tôi tin rằng cách dễ nhất là trước tiên hãy truy cập tức thì và sau đó là chuỗi như:

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

Điều này sẽ dẫn đến:

2017-09-08T12:56:45.331Z


4
Nếu bạn muốn thời điểm hiện tại, không cần phải đi qua một Dateđối tượng lỗi thời . Cứ làm đi Instant.now().toString(). Nếu bạn có một DateAPI kế thừa, phương pháp của bạn là phương pháp tốt nhất.
Ole VV

Như Ole VV nhận xét, các lớp học ngày thời gian cũ 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

5

tl; dr

Một số Câu trả lời khác là chính xác khi đề xuất các lớp java.time nhưng sử dụng các độ dài không cần thiết cho các nhu cầu cụ thể của bạn.

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

Các jav.time.Instantlớp đại diện cho một thời điểm trong UTC, luôn UTC.

Instant instant = Instant.now() ;

tức thì.toString (): 2018-01-23T12: 34: 56.123456Z

Phần Zcuối của chuỗi ví dụ của bạn 2010-10-12T08:50Zđược phát âm là Z Zulu và có nghĩa là UTC .

Định dạng mong muốn của bạn xảy ra để tuân thủ tiêu chuẩn ISO 8601 . Các lớp java.time sử dụng các định dạng tiêu chuẩn này theo mặc định khi phân tích cú pháp / tạo chuỗi. Vì vậy, không cần chỉ định một mẫu định dạng. Chỉ cần gọiInstant::toString như đã thấy ở trên.

Nếu bạn đặc biệt muốn cả phút mà không có giây hoặc giây, thì cắt ngắn. Chỉ định một đơn vị thời gian thông qua ChronoUnitlớp học.

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

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 .

Bạn có thể trao đổi các đối tượng java.time trực tiếp với cơ sở dữ liệu của bạn. Sử dụng trình điều khiển JDBC tương thích với JDBC 4.2 trở lên. Không cần chuỗi, không cần java.sql.*lớp.

Nơi để có được các lớp java.time?

  • Java SE 8 , Java SE 9 , Java SE 10 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 đó (<26), cá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 .


2

Đây là cả một lớp được tối ưu hóa để gọi "now ()" không làm gì thêm mà nó phải làm.

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
Làm cho nó tĩnh có thể gây rắc rối vì SimpleDateFormat không an toàn cho luồng: "Định dạng ngày không được đồng bộ hóa. Nên tạo các phiên bản định dạng riêng cho mỗi luồng. Nếu nhiều luồng truy cập đồng thời một định dạng, nó phải được đồng bộ hóa bên ngoài." docs.oracle.com/javase/7/docs/api/java/text/áp
Juha Palomäki

2
Như @Juha Palomäki đã đề cập, đây không phải là chủ đề an toàn. Nếu bạn đang sử dụng Java 8 trở lên, ThreadLocal.withInitial có thể khắc phục điều đó. Nếu bạn đang sử dụng Java 7 trở xuống, hãy tạo một ThreadLocal mới và cung cấp một giá trị ban đầu bằng cách ghi đè ThreadLocal.initialValue
user393274

@ user393274 - nếu bạn đang sử dụng Java 8 bạn nên sử dụng Instant, DateTimeFormatvà các chủ đề hiện đại thay thế an toàn khác

Tôi hơi bối rối vì vấn đề với SimpleDateFormat là không an toàn. Nếu hai luồng thực thi trình khởi tạo tĩnh cùng một lúc, tôi không thể thấy điều gì tồi tệ hơn trình xây dựng SimpleDateFormat được gọi hai lần nhưng chỉ một khoảnh khắc của nó (lần cuối cùng kết thúc) được ghi là "df".
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

Tuy nhiên, joda-time chỉ hỗ trợ định dạng mở rộng: "2015-12-09T00: 22: 42.930Z" không phải là cơ bản: "20151209T002242.930Z" ... chúng tôi có thể tốt hơn nên thử nghiệm danh sách các định dạng với java SimpleDateFormat.


1

Tôi đã làm điều đó trong Android bằng Lịch và SimpleDateFormat. Phương thức sau đây trả về Lịch có múi giờ "GMT" (Đây là múi giờ phổ quát). Sau đó, bạn có thể sử dụng lớp Lịch để đặt giờ giữa các múi giờ khác nhau, sử dụng phương thức setTimeZone () của lớp Lịch.

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

HÃY NHỚ: Lớp Date không biết về sự tồn tại của TimeZone. Vì lý do này, nếu bạn gỡ lỗi một ngày, bạn luôn thấy ngày cho múi giờ hiện tại của mình.


1

Nếu bạn quan tâm đến hiệu năng, tôi đã tạo một thư viện vượt trội so với trình phân tích cú pháp và trình định dạng Java tiêu chuẩn để thao tác với các ngày có định dạng ISO8601. Việc triển khai DatetimeProcessor là an toàn luồng và có thể được lưu trữ trong một bản đồ đồng thời hoặc các trường tĩnh.

<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

Đáng lẽ họ nên thêm một số cách đơn giản để đi từ Date sang Instant và cũng là một phương thức được gọi toISO8601, đó là điều mà rất nhiều người đang tìm kiếm. Để bổ sung cho các câu trả lời khác, từ định dạng java.util.Date đến ISO 8601:

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

Nó không thực sự hiển thị khi sử dụng tự động hoàn thành nhưng java.time.Instant.toString()::

Một đại diện chuỗi của tức thời này bằng cách sử dụng ISO-8601


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

Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do và / hoặc cách mã này trả lời câu hỏi cải thiện giá trị lâu dài của nó.
Vishal Chhodwani

-2

Thử cái này,

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

Nó dành cho định dạng ISO 8601


2
Điều này sẽ sử dụng ngày trong múi giờ sai, xem câu trả lời của Carlos.
Stian Soiland-Reyes
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.