web-dev-qa-db-ja.com

Javaの「DateTimeFormatter」フォーマットパターンコードの「uuuu」と「yyyy」

DateTimeFormatterクラスのドキュメントには、その年のフォーマットコードについて記載されています。

u年2004年; 04

y 2004年の年。 04

年:文字の数は、それ以下でパディングが使用される最小フィールド幅を決定します。文字数が2の場合、2桁の短縮形が使用されます。印刷の場合、これは右端の2桁を出力します。解析の場合、これは2000のベース値を使用して解析し、2000〜2099の範囲内の年になります。文字数が4未満(2ではない)の場合、SignStyle.NORMALに従って負の年の記号のみが出力されます。それ以外の場合、SignStyle.EXCEEDS_PADに従って、パッド幅を超えると符号が出力されます。

「時代」に関する他の言及はありません。

これら2つのコードの違いは何ですか、uyyearyear-of-era

いつこのパターンのようなものを使うべきですかuuuu-MM-ddおよびyyyy-MM-dd Javaで日付を扱うときは?

知識のある人によって書かれたサンプルコードはuuuuを使用しているようですが、なぜですか?

従来の SimpleDateFormat などの他のフォーマットクラスにはyyyyしかありません。そのため、Java.timeがuuuuを「時代の年」にもたらす理由を混乱させています」。

26
Basil Bourque

Javadocセクション フォーマットと解析のパターンDateTimeFormatterには、次の3つの関連するシンボルがリストされています。

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
 d       day-of-month   number        10
 E       day-of-week    text          Tue; Tuesday; T

day-of-yearday-of-month、およびday-of-weekは、特定のスコープ(年、月、週)内のdayであることは明らかです。

したがって、year-of-eraは、指定されたスコープ(時代)内のyearを意味し、そのすぐ上にeraADの例の値と共に表示されます(もちろん、BCである他の値) 。

yearsigned年です。ここで、年01 BC、年-12 BCなどです。

例として: Julius Caesar暗殺

  • 紀元前44年3月15日(パターンMMMM d, y GGを使用)
  • 3月15日、-43(パターンMMMM d, uを使用)

もちろん、区別は年がゼロまたは負の場合にのみ重要であり、それはまれであるため、ほとんどの人はそうであっても気にしません。

結論:yを使用する場合は、Gも使用する必要があります。 Gはめったに使用されないため、正しい年記号はuではなくyです。そうでない場合、正でない年は正しく表示されません。

これは defensive programming として知られています:

防御的プログラミングは、ソフトウェアの一部の継続的な機能を保証する予期しない状況の下でを目的とした防御設計の形式です。


DateTimeFormatterSimpleDateFormat と一貫していることに注意してください。

Letter  Date or Time Component  Presentation  Examples
------  ----------------------  ------------  --------
G       Era designator          Text          AD
y       Year                    Year          1996; 96

負の年は常に問題でしたが、彼らはuを追加することでそれを修正しました。

17
Andreas

短編小説

  1. 99%の目的でコインを投げることができますが、yyyyを使用するか、uuuuを使用するか(または、2桁の年にyyまたはuuを使用するか)違いはありません。
  2. それは、1 CE(1 AD)より1年前に発生した場合に何をしたいかによって異なります。ポイントは、プログラムの99%でそのような年は決して発生しないということです。

uyがどのように機能するかについては、他に2つの回答がすでにありますが、まだ何かが足りないと感じたので、少し意見に基づいた回答を投稿しています。

フォーマット用

1 CEの1年前にフォーマットされることを想定していない場合、できる最善の方法は、この仮定を確認し、破損した場合に適切に対応することです。たとえば、状況と要件に応じて、エラーメッセージを出力したり、例外をスローしたりできます。非常にソフトな障害パスの1つは、この場合はy(元年)およびG(元号)のパターンを使用し、通常の現在の元号の場合はuまたはyのパターンを使用することです。現在の日付またはプログラムがコンパイルされた日付を印刷する場合、それが共通の時代にあることを確認でき、チェックをスキップすることを選択できることに注意してください。

解析用

多くの場合(ほとんどの場合)、解析は検証を意味します。つまり、入力文字列がどのように見えるかを保証しません。通常、ユーザーまたは別のシステムから取得されます。例:日付文字列は2018-09-29になります。ここで、uuuuyyyyの間の選択は、文字列に0または負の年が含まれている場合(たとえば、0000-08-17または-012-11-13)。これがエラーであると仮定すると、即時の答えは次のとおりです。この場合、例外をスローするにはyyyyを使用します。さらに細かい:uuuuを使用し、解析後に解析された日付の範囲チェックを実行します。後者のアプローチでは、検証エラーが発生した場合に、より詳細な検証とより良いエラーメッセージの両方が可能になります。

特別な場合(Meno Hochschildが既に言及):フォーマッターが厳密なリゾルバースタイルを使用し、yを含まないGを含む場合、厳密に言えば時代の年はあいまいであるため、解析はalways失敗します:1950は1950 CEを意味する可能性がありますまたは1950 BCE(1950 BC)。したがって、この場合はuが必要です(またはデフォルトの元号を指定すると、これはDateTimeFormatterBuilderを介して可能になります)。

再び長い話

日付、特に年の明示的な範囲チェックは、予期しない非常に早い年をキャッチするためにuuuuyyyyの選択に依存するよりも優れています。

2
Ole V.V.