Java 8 では、日付と時刻を操作するための新しいjava.time API が追加されました ( JSR 310 )。
日付と時刻を文字列として持っています(例"2014-04-08 12:30"
)。LocalDateTime
指定された文字列からインスタンスを取得するにはどうすればよいですか?
オブジェクトの操作を終了した後、インスタンスを上記と同じ形式の文字列にLocalDateTime
変換するにはどうすればよいですか?LocalDateTime
Java 8 では、日付と時刻を操作するための新しいjava.time API が追加されました ( JSR 310 )。
日付と時刻を文字列として持っています(例"2014-04-08 12:30"
)。LocalDateTime
指定された文字列からインスタンスを取得するにはどうすればよいですか?
オブジェクトの操作を終了した後、インスタンスを上記と同じ形式の文字列にLocalDateTime
変換するにはどうすればよいですか?LocalDateTime
日付と時刻の解析
文字列からオブジェクトを作成するには、静的メソッドLocalDateTime
を使用できます。文字列とas パラメータLocalDateTime.parse()
を取ります。DateTimeFormatter
はDateTimeFormatter
、日付/時刻パターンを指定するために使用されます。
String str = "1986-04-08 12:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
日付と時刻のフォーマット
オブジェクトから書式設定された文字列を作成するにLocalDateTime
は、メソッドを使用できますformat()
。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.of(1986, Month.APRIL, 8, 12, 30);
String formattedDateTime = dateTime.format(formatter); // "1986-04-08 12:30"
で定数として事前定義された、一般的に使用される日付/時刻形式がいくつかあることに注意してくださいDateTimeFormatter
。例: を使用して上記のインスタンスDateTimeFormatter.ISO_DATE_TIME
をフォーマットすると、string になります。LocalDateTime
"1986-04-08T12:30:00"
parse()
およびformat()
メソッドは、日付/時刻関連のすべてのオブジェクトで使用できます (例:またはLocalDate
) ZonedDateTime
。
がISO-8601 形式の場合、パターンを指定せずにLocalDate.parse()
またはLocalDateTime.parse()
を使用することもできます。String
String
例えば、
String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
System.out.println("Date: " + aLD);
String strDatewithTime = "2015-08-04T10:11:30";
LocalDateTime aLDT = LocalDateTime.parse(strDatewithTime);
System.out.println("Date with Time: " + aLDT);
出力,
Date: 2015-08-04
Date with Time: 2015-08-04T10:11:30
DateTimeFormatter
他の日付パターンを処理する必要がある場合にのみ使用してください。
たとえば、次の例では、dd MMM uuuuは、月の日 (2 桁)、月の名前の 3 文字 (Jan、Feb、Mar、...)、および 4 桁の年を表します。
DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
String anotherDate = "04 Aug 2015";
LocalDate lds = LocalDate.parse(anotherDate, dTF);
System.out.println(anotherDate + " parses to " + lds);
出力
04 Aug 2015 parses to 2015-08-04
DateTimeFormatter
また、オブジェクトは双方向であることも覚えておいてください。入力の解析と出力のフォーマットの両方が可能です。
String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
DateTimeFormatter dTF = DateTimeFormatter.ofPattern("dd MMM uuuu");
System.out.println(aLD + " formats as " + dTF.format(aLD));
出力
2015-08-04 formats as 04 Aug 2015
( DateFormatter の書式設定と解析のパターンの完全なリストを参照してください)
Symbol Meaning Presentation Examples
------ ------- ------------ -------
G era text AD; Anno Domini; A
u year year 2004; 04
y year-of-era year 2004; 04
D day-of-year number 189
M/L month-of-year number/text 7; 07; Jul; July; J
d day-of-month number 10
Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter
Y week-based-year year 1996; 96
w week-of-week-based-year number 27
W week-of-month number 4
E day-of-week text Tue; Tuesday; T
e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T
F week-of-month number 3
a am-pm-of-day text PM
h clock-hour-of-am-pm (1-12) number 12
K hour-of-am-pm (0-11) number 0
k clock-hour-of-am-pm (1-24) number 0
H hour-of-day (0-23) number 0
m minute-of-hour number 30
s second-of-minute number 55
S fraction-of-second fraction 978
A milli-of-day number 1234
n nano-of-second number 987654321
N nano-of-day number 1234000000
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
z time-zone name zone-name Pacific Standard Time; PST
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;
p pad next pad modifier 1
' escape for text delimiter
'' single quote literal '
[ optional section start
] optional section end
# reserved for future use
{ reserved for future use
} reserved for future use
上記の両方の回答は、文字列パターンに関する質問を非常によく説明しています。ただし、ISO 8601DateTimeFormatter
を使用している場合は、LocalDateTime が既に用意されているため、適用する必要はありません。
LocalDateTime をタイム ゾーン ISO8601 文字列に変換する
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneOffset.UTC); //you might use a different zone
String iso8601 = zdt.toString();
ISO8601 文字列から LocalDateTime に戻す
String iso8601 = "2016-02-14T18:32:04.150Z";
ZonedDateTime zdt = ZonedDateTime.parse(iso8601);
LocalDateTime ldt = zdt.toLocalDateTime();
日付と時刻を含む文字列を特定の時点 (Java では " Instant
" と呼びます) に解析するのは非常に複雑です。Java はこれに何度か繰り返し取り組んできました。最新のものjava.time
とは、ほぼすべてのニーズをカバーしています (時間java.time.chrono
の遅れを除く:))。
ただし、その複雑さは多くの混乱をもたらします。
日付の解析を理解するための鍵は次のとおりです。
LocalDateTime
, ZonedDateTime
et al. とても複雑タイムゾーンがあります。タイムゾーンは基本的に地球の表面の「ストライプ」*[1]であり、その当局は、いつどのタイムオフセットがあるかという同じ規則に従います。これにはサマータイムのルールが含まれます。
タイムゾーンは、主に誰が誰を征服するかに基づいて、さまざまな地域で時間とともに変化します。また、1 つのタイム ゾーンのルールも時間の経過とともに変化します。
時間差があります。これはタイム ゾーンと同じではありません。タイム ゾーンは「プラハ」などですが、夏時間のオフセットと冬時間のオフセットがあるためです。
タイム ゾーンでタイムスタンプを取得する場合、オフセットは、その年のどの部分にあるかによって異なる場合があります。うるう時間の間、タイムスタンプは 2 つの異なる時刻を意味する可能性があるため、追加情報がなければ、信頼できるものではありません。変換された。
注:タイムスタンプとは、「日付および/または時刻を含み、オプションでタイム ゾーンおよび/または時間オフセットを含む文字列」を意味します。
いくつかのタイム ゾーンは、特定の期間の同じタイム オフセットを共有する場合があります。たとえば、夏時間オフセットが有効でない場合、GMT/UTC タイム ゾーンは「ロンドン」タイム ゾーンと同じです。
もう少し複雑にするには(ただし、ユースケースではそれほど重要ではありません):
2040-12-31 24:00:00
、有効な日時である可能性があります。)これには、システムが日付変換を正しく行うために使用するメタデータの定期的な更新が必要です。たとえば、Linux では、これらの新しいデータを含む Java パッケージの定期的な更新を取得します。更新は、過去のタイムスタンプと将来のタイムスタンプの両方について、常に以前の動作を維持するとは限りません。そのため、あるタイム ゾーンの変更前後の 2 つのタイムスタンプを解析してそれらを比較すると、異なるバージョンのソフトウェアで実行すると異なる結果が得られる場合があります。これは、影響を受けるタイム ゾーンと他のタイム ゾーンの比較にも当てはまります。
これによりソフトウェアにバグが発生する場合は、 UNIX のタイムスタンプなど、複雑な規則を持たないタイムスタンプを使用することを検討してください。
7 があるため、将来の日付については、確実に日付を正確に変換することはできません。したがって、たとえば、現在の解析は8524-02-17 12:00:00
、将来の解析から数秒ずれている可能性があります。
java.util.Date
では、年、月、日、および時刻のみを想定して、少し素朴なアプローチを採用していました。これはすぐに十分ではありませんでした。java.sql.Date
に導入されましたが、独自の制限がありました。Calendar
API が導入されました。java.time
タイムスタンプ文字列を使用する場合、含まれる情報を知る必要があります。これが重要なポイントです。これを正しく行わないと、「Can't create Instant」、「Zone offset missing」、「unknown zone id」などの不可解な例外が発生します。
日付と時刻が含まれていますか?
タイムオフセットはありますか?
時間オフセットは+hh:mm
一部です。場合によっては、「ズールー時間」、協定世界時、またはグリニッジ標準時+00:00
と置き換えられることがあります。これらはタイムゾーンも設定します。
これらのタイムスタンプには、.Z
UTC
GMT
OffsetDateTime
タイムゾーンはありますか?
これらのタイムスタンプには、ZonedDateTime
.
ゾーンは次のいずれかで指定されます
タイムゾーンのリストは、ICAAN が支援する「TZ データベース」によって編集されています。
ZoneId
の javadoc によると、ゾーン ID は何らかの形でZ
オフセットとして指定することもできます。これが実際のゾーンにどのようにマップされるかはわかりません。TZ のみを含むタイムスタンプが時間オフセット変更のうるう時間に該当する場合、それはあいまいであり、解釈は の対象となりResolverStyle
ます。以下を参照してください。
どちらでもない場合は、不足しているコンテキストが想定されるか、無視されます。そして、消費者は決定しなければなりません。したがって、不足している情報を追加して、次のように解析しLocalDateTime
て変換する必要があります。OffsetDateTime
Duration
)、またはわからない場合や、実際には問題にならない場合 (例: ローカル バスの時刻表) に役立ちます。パートタイム情報
LocalDate
、LocalTime
、OffsetTime
、MonthDay
、Year
、またはYearMonth
を取り出すことができます。完全な情報があれば、java.time.Instant
. OffsetDateTime
これは、との間の変換にも内部的に使用されZonedDateTime
ます。
DateTimeFormatter
タイムスタンプ文字列を解析し、文字列にフォーマットすることができる広範なドキュメントがあります。
事前に作成されたDateTimeFormatter
は、さらにすべての標準タイムスタンプ形式をカバーする必要があります。たとえば、ISO_INSTANT
を解析できます2011-12-03T10:15:30.123457Z
。
特別な形式がある場合は、独自の DateTimeFormatter (パーサーでもあります) を作成できます。
private static final DateTimeFormatter TIMESTAMP_PARSER = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SX"))
.toFormatter();
のソース コードを見てDateTimeFormatter
、DateTimeFormatterBuilder
. そこにいる間ResolverStyle
、パーサーがフォーマットとあいまいな情報に対してLENIENT、SMART、またはSTRICTのいずれであるかを制御することも確認してください。
さて、よくある間違いは の複雑さに入ることですTemporalAccessor
。これは、開発者が で作業していた方法に由来しますSimpleDateFormatter.parse(String)
。そうです、あなたにDateTimeFormatter.parse("...")
与えますTemporalAccessor
。
// No need for this!
TemporalAccessor ta = TIMESTAMP_PARSER.parse("2011-... etc");
ただし、前のセクションの知識があれば、必要な型に簡単に解析できます。
OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z", TIMESTAMP_PARSER);
実際にはどちらも必要ありませんDateTimeFormatter
。解析したい型にはparse(String)
メソッドがあります。
OffsetDateTime myTimestamp = OffsetDateTime.parse("2011-12-03T10:15:30.123457Z");
についてTemporalAccessor
は、文字列に含まれる情報が漠然としていて、実行時に決定したい場合に使用できます。
私はあなたの魂に理解の光を当てることを願っています:)
注: java.time
Java 6 および 7 へのバックポートがあります: ThreeTen-Backport。Android の場合、ThreeTenABPがあります。
[1]ストライプではないというだけでなく、いくつかの奇妙な極端なものもあります. たとえば、隣接する太平洋の島々には、+14:00 と -11:00 のタイム ゾーンがあります。つまり、ある島では 5 月 1 日午後 3 時ですが、それほど遠くない別の島では、まだ 4 月 30 日午後 12 時です (正しく数えれば :) )