誰かがDate
とCalendar
型に関する現在の「ベストプラクティス」についてアドバイスしてもらえますか。
新しいコードを書くとき、常にCalendar
よりDate
を優先するのが最善ですか、それともDate
がより適切なデータ型である状況がありますか?
Dateはより単純なクラスであり、主に下位互換性の理由からそこにあります。特定の日付を設定したり日付計算をしたりする必要がある場合は、カレンダーを使用してください。カレンダーはローカライズも扱います。 Dateの以前の日付操作関数はそれ以来推奨されていません。
個人的には、選択肢がある場合は、ミリ秒単位の時間をロング(または適宜、ロング)またはカレンダーとして使用する傾向があります。
DateとCalendarはどちらも変更可能であり、APIで使用すると問題が発生する傾向があります。
新しいコードのための最善の方法は(あなたのポリシーがサードパーティのコードを許可している場合) Joda Time library を使うことです。
Date と Calendar のどちらにも、設計上の問題が非常に多いので、どちらも新しいコードに対する良い解決策ではありません。
Date
とCalendar
は、実際には同じ基本概念です(どちらも瞬間を表し、基礎となるlong
値のラッパーです)。
Calendar
は実際にはDate
よりもさらに壊れていると主張する人もいるでしょう。 timeZone
プロパティを変更すると、具象はblancmangeに変わります。このため、どちらのオブジェクトも年月日または時刻の保管場所としては実際には役に立ちません。
Calendar
はDate
およびTimeZone
オブジェクトが与えられたときに計算を行う計算機としてのみ使用してください。アプリケーションでのプロパティの入力には使用しないでください。
表示文字列を生成するには、SimpleDateFormat
とTimeZone
およびDate
を一緒に使用します。
不必要に複雑な私見であり、いずれにせよJSR-310日付APIに取って代わられることになっていますが、冒険的にJoda-Timeを使っているのであれば。
私は、日付計算のためにYearMonthDay
をフードの下で使用する独自のCalendar
クラスをロールバックすることは難しくないと以前に答えました。私はその提案に賛成しませんでしたが、 Joda-Time (および JSR-31 )はほとんどのユースケースで非常に複雑すぎるため、有効なものであると私は考えています。 。
日付は日付オブジェクトを格納するのに最適です。それは永続化されたもの、直列化されたものです...
カレンダーは日付を操作するのに最適です。
注:Dateは可変であり、スレッドセーフではないため、DateよりもJava.lang.Longを優先することもあります。 Dateオブジェクトでは、setTime()とgetTime()を使って両者を切り替えます。たとえば、アプリケーション内の定数Date(例:ゼロの1970/01/01、または2099/12/31に設定したアプリケーションのEND_OF_TIME。特に開始時刻と終了時刻としてNULL値を置き換える場合に非常に便利です) SQLはNULLで非常に独特であるため、データベースにそれらを保持する場合。
可能であれば、通常はDateを使用します。変更可能ですが、ミューテーターは実際には推奨されていません。最後にそれは基本的に日付/時刻を表すだろう長いをラップします。逆に、値を操作する必要がある場合は、カレンダーを使用します。
あなたはそれをこのように考えることができます:あなたがあなたが簡単に操作することができてそれからtoString()メソッドを使ってそれらをStringsに変換することができる必要があるときだけStringBufferを使います。同様に、テンポラルデータを操作する必要がある場合にのみカレンダーを使用します。
ベストプラクティスのために、私はドメインモデルの外側でできるだけ不変オブジェクトを使う傾向があります。これは、あらゆる副作用の可能性を大幅に減らし、JUnitテストではなく、コンパイラによって行われます。このテクニックは、クラス内にprivate finalフィールドを作成することによって使用します。
そしてStringBufferのアナロジーに戻りましょう。これは、カレンダーと日付の間の変換方法を示すコードです。
String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String
// immutable date with hard coded format. If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");
// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// mutate the value
cal.add(Calendar.YEAR, 1);
// convert back to Date
Date newDate = cal.getTime();
//
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);
Date
sは、不変の時点として使用する必要があります。 Calendar
sは変更可能で、最終日を出すために他のクラスと共同作業する必要がある場合は、受け渡して変更することができます。それらがString
とStringBuilder
に似ていると考えてください、そして私はそれらがどのように使われるべきであると考えるかを理解するでしょう。
(そして、確かに、Dateは実際には技術的に不変ではないことを知っていますが、意図は変更不可能であるべきではないということです。
Date
とCalendar
に関する現在の「ベストプラクティス」をアドバイスする常に
Calendar
よりDate
を優先するのが最善です。
これらの従来のクラスを完全に避けてください。代わりに Java.time クラスを使用してください。
Instant
を使用してください。Date
と現代の同等語)ZonedDateTime
を使用します。GregorianCalendar
と現代の同等語)OffsetDateTime
LocalDateTime
を使用します。Ortomalaによる回答 Lokniは、厄介な古い従来の日時クラス(Date
、Calendar
など)ではなく、最新の Java.time クラスを使用することをお勧めします。しかし、その答えは、間違ったクラスが同等であると示唆しています(その答えに対する私のコメントを参照してください)。
Java.timeクラスは、従来の日時クラスと比べて、 大幅な の改善、昼と夜の違いがあります。古いクラスは、デザインがよくなく、混乱しやすく、面倒です。可能な限り古いクラスを避けるべきです。しかし、古い/新しいから/に変換する必要があるときは、新しいメソッドadd//を追加して old クラスに変換することで変換できます。
変換に関するより多くの情報については、 私の答えと気の利いた図 を他の質問に、 Java.util.Dateを“ Java.time”型に変換する? を参照してください。
スタックオーバーフローを検索すると、Java.timeの使用に関する質問と回答の例が多数あります。しかし、これは簡単な概要です。
Instant
現在の瞬間をInstant
で取得します。 Instant
クラスは、 UTC の分解能で ナノ秒 (最大9桁の10進数)でタイムライン上の瞬間を表します分数)。
Instant instant = Instant.now();
ZonedDateTime
ある特定の地域のレンズを通して同じ同時モーメント壁時計時間 を見るには、タイムゾーン( ZoneId
)を適用します ZonedDateTime
を取得してください。
continent/region
、 America/Montreal
、またはAfrica/Casablanca
のように、 正しいタイムゾーン名 をPacific/Auckland
の形式で指定します。 EST
やIST
などの3〜4文字の省略形は、 not trueタイムゾーンであり、標準化されておらず、一意でもありません(!)。
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();
タイムゾーンは、その地域の offset-from-UTC の変更履歴です。しかし時々あなたはフルゾーンなしでオフセットだけを与えられる。その場合はOffsetDateTime
クラスを使用してください。
ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );
単なるオフセットの使用よりもタイムゾーンの使用の方が好ましいです。
LocalDateTime
Local…
クラスの“ Local”は any localityを意味し、特定のlocalityを意味しません。そのため、名前は直感的にわかりにくい場合があります。
LocalDateTime
、LocalDate
、およびLocalTime
には、オフセットまたはタイムゾーンに関する情報が意図的に欠けています。したがって、それらは実際の瞬間を表す not ではなく、タイムライン上の not ポイントです。疑わしい場合や混乱している場合は、ZonedDateTime
ではなくLocalDateTime
を使用してください。より多くの議論についてはスタックオーバーフローを検索してください。
日時オブジェクトをその値を表すストリングと混同しないでください。文字列を解析して日時オブジェクトを取得したり、日時オブジェクトから文字列を生成したりできます。しかし、文字列は日時そのものではありません。
Java.timeクラスでデフォルトで使用されている標準の ISO 8601 フォーマットについて学んでください。
Java.time フレームワークは、Java 8以降に組み込まれています。これらのクラスは、 Java.util.Date
、 Calendar
、& SimpleDateFormat
のような、面倒な古い レガシー 日時クラスに代わるものです。
Joda-Time プロジェクトは、現在 メンテナンスモード になっており、 Java.time クラスへの移行を推奨しています。
詳細は、 Oracle Tutorial を参照してください。そして多くの例と説明についてはStack Overflowを検索してください。指定は JSR 31 です。
JDBCドライバ に準拠した JDBC 4.2 以降を使用すると、 Java.time オブジェクトをデータベースと直接交換できます。文字列もJava.sql。*クラスも必要ありません。
Java.timeクラスはどこで入手できますか?
ThreeTen-Extra プロジェクトは、追加クラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性があることを証明するものです。 Interval
、 YearWeek
、 YearQuarter
、 more などの便利なクラスがあります。
Java 8では、新しい Java.timeパッケージ を使うべきです。
オブジェクトは不変であり、タイムゾーンと夏時間が考慮されます。
次のように、古い Java.util.Date
オブジェクトから ZonedDateTime
オブジェクトを作成できます。
Date date = new Date();
ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());
私はいつも擁護しています Joda-time 。これが理由です。
編集:あなたはJava 8に移行することができれば、Java 8で導入されたJavaの日付/時刻クラスは現在推奨されるソリューションです。
ちょっと遅くなりましたが、JavaにはJDK 8の新しいDate Time APIがあります。あなたのJDKバージョンをアップグレードしてその標準を受け入れることをお勧めします。これ以上面倒な日付やカレンダーはなく、サードパーティのjarもありません。
日付は再開発されるべきです。長い整数ではなく、年、月、日、時、分、秒を別々のフィールドとして保持する必要があります。この日付が関連付けられているカレンダーとタイムゾーンを保存するとさらに良いかもしれません。
私たちの自然な会話の中で、2013年11月1日午後1時NY時間に予定を設定している場合、これはDateTimeです。カレンダーではありません。したがって、Javaでもこのように会話できるはずです。
Dateが(1970年1月1日以降からミリ秒の)長整数として格納されている場合、現在の日付の計算はカレンダーによって異なります。カレンダーが異なると日付も異なります。これは絶対的な時間を与えるという見込みからのものです(例えばビッグバンの後1兆秒)。しかし、年や月などをカプセル化したオブジェクトのように、便利な会話方法も必要になることがよくあります。
これら2つの目的を両立させるために、Javaに新しい進歩があるのではないでしょうか。私のJavaの知識は古すぎるかもしれません。
私は私が私が私があなたの必要性を合わせるために日付をフォーマットする必要があるとき私が時間を動かすことのようなある特定の操作を必要とする時にカレンダーを使用する。私は今ロケールを使っています!
ところで、 "date"は通常 "廃止予定/非推奨"とタグ付けされています(正確には理由がわかりません) - それについて何か書かれています Java:Dateコンストラクタが推奨されないのはなぜですか?
new Date(int year、int month、int day)を介してのみコンストラクタの問題であるように見えます。方法はカレンダーを介してであり、別々にパラメータを設定します..(Calendar cal = Calendar.getInstance();)