この日付形式は何ですか?2011-08-12T20:17:46.384Z


384

次の日付があります: 2011-08-12T20:17:46.384Z。これはどのフォーマットですか?私はJava 1.4でそれを解析しようとしていますDateFormat.getDateInstance().parse(dateStr)、そして私は得ています

java.text.ParseException:解析できない日付:「2011-08-12T20:17:46.384Z」

解析にはSimpleDateFormatを使用する必要があると思いますが、最初にフォーマット文字列を知る必要があります。これまでのところ私が持っyyyy-MM-ddているのTは、この文字列の意味がわからないためです-タイムゾーンに関連した何か?この日付文字列はlcmis:downloadedOnファイルCMISダウンロード履歴メディアタイプに表示されるタグから取得されます



3
@TomaszNurkiewicz、そうではありません。ISO8601には、最後にZがありません。
t1gor

4
ISO8601は、最後にZを許可します。上記のリンクを参照して、UTCを探してください。
Jonathan Rosenne、2015年

2
@ t1gor Z最後のはUTCの略でZuluUTCを意味します。この形式は、最も確かにあるの一部ISO 8601標準の日時テキスト形式のコレクション。ちなみに、これらの標準形式は、デフォルトでjava.timeクラスで使用されます。
バジルブルク2018年

3
FYI、といった面倒な古い日付時刻クラスjava.util.Datejava.util.Calendarjava.text.SimpleDateFormat今のレガシーに取って代わられ、java.timeの Javaの8&9のJavaを参照してくださいに組み込まれたクラスOracleでのチュートリアル
バジルブルク

回答:


513

Tは日付と時刻を区切るための単なるリテラルであり、Zは「ゼロ時間オフセット」または「ズールー時間」(UTC)とも呼ばれます。文字列に常に「Z」がある場合は、次のように使用できます。

SimpleDateFormat format = new SimpleDateFormat(
    "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));

または、Joda Timeを使用して、使用できますISODateTimeFormat.dateTime()


7
なぜ私たちは周りの単一引用符が必要なのですかTZ
Maroun

7
@MarounMaroun:基本的に、これらのリテラル文字が必要です。T(SimpleDateFormatが不明な指定子をどのように処理するか覚えていない)必要はないかもしれませんがZ、 "UTCオフセット値"(たとえば "00")ではなく文字 'Z'にする必要があります。
Jon Skeet、2015年

2
@nyedidikeke:リンクしたウィキペディアのページに、UTCの「ズールータイムゾーン」が表示されます。あなたがあなたが修正しているとあなたが信じていることはわかりません。
Jon Skeet

9
@JonSkeet:不要な議論が生じる可能性があります。あなたの答えに異議を唱えないが、「ゼロUTCオフセット」からその文字の頭文字を取得したZに注意を引くことを意図した。Zの文字は、NATOの音声アルファベットでは「ズールー」と呼ばれます。次に、ゼロUTCオフセットを参照する軍事的アプローチは、Zuluとして識別される文字Zに固定され、コード化された名前であるZuluタイムゾーンを獲得します。Zの意味は失われておらず、Zuluタイムゾーン(Zからの)は単にそれを参照する継承されたコード化言語であるため、ゼロUTCオフセットのゾーン指定子であることに注意することが重要です。
nyedidikeke

2
@nyedidikeke:他の誰かが私の回答を参考にして区別を気にかけるかどうかについてはまだ同意しませんが、更新しました。歴史は答えとはあまり関係がないので、詳細には触れません。
Jon Skeet

86

tl; dr

入力文字列では、標準ISO 8601形式が使用されます。

Instant.parse ( "2011-08-12T20:17:46.384Z" ) 

ISO 8601

このフォーマットは、実用的な実用規格であるISO 8601によって定義されています。

T、日付部分と時刻部分を分離します。Z端の手段UTC(オフセットから-UTCゼロ時間-分-秒です)。Zされる「ズールー」と発音します

java.time

Javaの最も初期のバージョンにバンドルされている古い日時クラスは、設計が不十分で、混乱し、面倒であることが証明されています。それらを避けてください。

代わりに、Java 8以降に組み込まれているjava.timeフレームワークを使用してください。java.timeクラスは、古い日時クラスと非常に成功したJoda-Timeライブラリの両方を置き換えます。

java.timeクラスは、日時値のテキスト表現を解析/生成するときに、デフォルトでISO 8601を使用します。

このInstantクラスは、ナノ秒の分解能でUTCのタイムライン上の瞬間を表します。そのクラスは、フォーマットパターンを定義する手間をかけずに、入力文字列を直接解析できます。

Instant instant = Instant.parse ( "2011-08-12T20:17:46.384Z" ) ;

モダンとレガシーの両方のJavaの日時タイプの表


java.timeについて

java.timeのフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは面倒古い取って代わるレガシーのような日付時刻クラスをjava.util.DateCalendar、& SimpleDateFormat

ジョダタイムプロジェクトは、今でメンテナンスモードへの移行をアドバイスjava.timeのクラス。

詳細については、Oracleチュートリアルを参照してください。スタックオーバーフローで多くの例と説明を検索してください。仕様はJSR 310です。

java.timeクラスはどこで入手できますか?

  • Java SE 8 Java SE 9以降
    • ビルトイン。
    • 実装がバンドルされた標準Java APIの一部。
    • Java 9では、いくつかのマイナーな機能と修正が追加されています。
  • Java SE 6および Java SE 7
    • java.time機能の多くは、ThreeTen-BackportでJava 6および7にバックポートされています。
  • アンドロイド
    • それ以降のバージョンのAndroidには、java.timeクラスの実装がバンドルされています。
    • 以前のAndroidでは、ThreeTenABPプロジェクトはThreeTen-Backport(上記)を採用しています。ThreeTenABPの使用方法…を参照してください。

JavaまたはAndroidのどのバージョンで使用するjava.timeライブラリの表

ThreeTen-エクストラプロジェクトでは、追加のクラスでjava.timeを拡張します。このプロジェクトは、java.timeに将来追加される可能性があることを証明する場です。あなたはここにいくつかの有用なクラスのような見つけることがIntervalYearWeekYearQuarter、および多くを


3
@star「Zulu」は、軍事および航空の伝統に由来し、AZの25文字( "J"なし)は、発音可能な名前を持ち、タイムゾーンのバージョンを表します。「ズールー」ゾーンは、UTCから0時間オフセットされています。これこれを見てください。
バジルブルク2017年

27

Javaの解析については不明ですが、それはISO8601です。http//en.wikipedia.org/wiki/ISO_8601


これは「2016-01-27T17:44:55UTC」、ISO8601ですか。
user1997292

私はそうは思いません。近いですが、サフィックスとしてのUTCは許可されていません。Zまたはタイムゾーンオフセット(+0100など)である必要があります。ZとUTCはそう変更、しかし、同じ意味を持つUTCにするZ有効なISO 8601をもたらすであろう
smparkes

9

最初の回答ではなく、それを解析する他の方法があります。それを解析するには:

(1)日付と時刻に関する情報を取得したい場合は、ZonedDatetimeJava 8以降)またはDate(古い)オブジェクトに解析できます。

// ZonedDateTime's default format requires a zone ID(like [Australia/Sydney]) in the end.
// Here, we provide a format which can parse the string correctly.
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime zdt = ZonedDateTime.parse("2011-08-12T20:17:46.384Z", dtf);

または

// 'T' is a literal.
// 'X' is ISO Zone Offset[like +01, -08]; For UTC, it is interpreted as 'Z'(Zero) literal.
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX";

// since no built-in format, we provides pattern directly.
DateFormat df = new SimpleDateFormat(pattern);

Date myDate = df.parse("2011-08-12T20:17:46.384Z");

(2)日時を気にせず、単に情報をナノ秒単位の瞬間として扱いたい場合は、次のように使用できますInstant

// The ISO format without zone ID is Instant's default.
// There is no need to pass any format.
Instant ins = Instant.parse("2011-08-12T20:17:46.384Z");

1

Android向けのソリューションを探している場合は、次のコードを使用して、タイムスタンプ文字列からエポック秒を取得できます。

public static long timestampToEpochSeconds(String srcTimestamp) {
    long epoch = 0;

    try {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            Instant instant = Instant.parse(srcTimestamp);
            epoch = instant.getEpochSecond();
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSS'Z'", Locale.getDefault());
            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date date = sdf.parse(srcTimestamp);
            if (date != null) {
                epoch = date.getTime() / 1000;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return epoch;
}

入力例:2019-10-15T05:51:31.537979Z

出力例:1571128673


0

次の例を使用できます。

    String date = "2011-08-12T20:17:46.384Z";

    String inputPattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String outputPattern = "yyyy-MM-dd HH:mm:ss";

    LocalDateTime inputDate = null;
    String outputDate = null;


    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputPattern, Locale.ENGLISH);
    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputPattern, Locale.ENGLISH);

    inputDate = LocalDateTime.parse(date, inputFormatter);
    outputDate = outputFormatter.format(inputDate);

    System.out.println("inputDate: " + inputDate);
    System.out.println("outputDate: " + outputDate);

をアポストロフィで囲んではいけませんZ。それはその手紙を期待するが無視することを意味します。しかし、その手紙は無視されるべきではありません。その手紙は貴重な情報を提供します、ストリングがUTCのために意図されたという事実、ゼロのオフセット。あなたのフォーマットはこの重要な事実を破棄しています。さらに、このフォーマットパターンをわざわざ定義する必要さえありません。このパターンのフォーマッタを内蔵しています。
バジルボーク

-1

この手法は、java.util.DateをUTC形式(またはその他の形式)に変換し、再び戻します。

次のようにクラスを定義します。

import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class UtcUtility {

public static DateTimeFormatter UTC = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZoneUTC();


public static Date parse(DateTimeFormatter dateTimeFormatter, String date) {
    return dateTimeFormatter.parseDateTime(date).toDate();
}

public static String format(DateTimeFormatter dateTimeFormatter, Date date) {
    return format(dateTimeFormatter, date.getTime());
}

private static String format(DateTimeFormatter dateTimeFormatter, long timeInMillis) {
    DateTime dateTime = new DateTime(timeInMillis);
    String formattedString = dateTimeFormatter.print(dateTime);
    return formattedString;
}

}

次に、次のように使用します。

Date date = format(UTC, "2020-04-19T00:30:07.000Z")

または

String date = parse(UTC, new Date())

必要に応じて、UTCだけでなく他の日付形式も定義できます。


両方java.util.DateJoda -Timeプロジェクトは、何年も前にJSR 310で定義された最新のjava.timeクラスに取って代わられました。ここでのアドバイスは古くなっています。
バジルブルク

java.timeはJava 8で導入されました。この質問は特にJava 1.4を参照しているため、新しいクラスの使用は意図的に避けています。このソリューションは、古いコードベースに対応します。著者はコードベースをJava 8に移動できると思いますが、これは必ずしも簡単で効率的または必要なわけではありません。
Gapmeister66

-1

@ John-Skeetは私にこれに関する私の自身の問題を修正する手がかりを与えました。若いプログラマーとして、この小さな問題は見逃しやすく、診断が困難です。だから私はそれが誰かを助けることを期待してそれを共有しています。

私の問題は、影響のないJSONからのタイムスタンプを制約する次の文字列を解析し、より有用な変数に入れたかったことです。しかし、エラーが発生し続けました。

したがって、次のようになります(ofPattern()内の文字列パラメーターに注意してください)。

String str = "20190927T182730.000Z"

LocalDateTime fin;
fin = LocalDateTime.parse( str, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss.SSSZ") );

エラー:

Exception in thread "main" java.time.format.DateTimeParseException: Text 
'20190927T182730.000Z' could not be parsed at index 19

問題?パターンの最後のZは、「T」と同じように「Z」でラップする必要があります。に変更 "yyyyMMdd'T'HHmmss.SSSZ"する "yyyyMMdd'T'HHmmss.SSS'Z'"と機能します。

パターンからZを完全に削除すると、エラーも発生しました。

率直に言って、私はJavaクラスがこれを予期していたと思います。


1
これはすでにここここで質問され、回答さています。そして、あなたの解決策は間違っています。一方でT引用されるリテラルやニーズである、Z(ゼロの)オフセット、そのように解析される必要がある、またはあなたが間違った結果が得られますされています。それが予期されていなかったとはどういう意味かわかりませんが、予想されていたと思います。
Ole VV

1
いいえ、いいえ、いいえ、無視しないでくださいZ。貴重な情報を破棄しています。タイムゾーンまたはUTCからのオフセットを無視して日時値を処理することは、通貨を無視して金額を処理するようなものです。
バジルブルク

1
T単に時刻部分から日付部分を分離して、何の意味が追加されていません。Z確かに意味を加える一方で。
バジルブルク

オレ、リンクをありがとう。私は確かにそれらを読みます。そして、私は確かにヤングインとして間違っている可能性があることを受け入れます。Imが言っているのは、パターンのcharのようにZを一重引用符で囲むとエラーが解決するということです。私の批判は、クラスの「パターン」部分を設計した人なら誰でも、「Z」(またはdiffタイムゾーン?)の有無と「T」が「」にラップされているかどうかをコーディングした可能性があるということです。彼らはそのユニークではなかったので。Imが扱うフォーマットは、商用APIのJSONを文字列に解析したものです。しかし、それらすべてを日付時刻カレンダーなどに解析して、それらをより便利にする必要があります。
spencemw
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.