web-dev-qa-db-ja.com

Java:Dateコンストラクターが非推奨になったのはなぜですか?代わりに何を使用しますか?

私はC#の世界から来たので、Javaの経験はまだありません。 Dateは非推奨であるとEclipseから伝えられました。

Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));

どうして?そして、何を(特に上記のような場合に)代わりに使用すべきですか?

187
Svish

特定のDateコンストラクタは非推奨であり、代わりにCalendarを使用する必要があります。 Date のJavaDocは、廃止予定のコンストラクターと、カレンダーを使用してそれらを置き換える方法を説明しています。

91
Ruben

Java.util.Dateクラスは実際には非推奨ではなく、そのコンストラクターだけでなく、他のいくつかのコンストラクター/メソッドも非推奨です。そのような使用法は国際化ではうまく機能しないため、廃止されました。代わりにCalendarクラスを使用する必要があります。

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1988);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date dateRepresentation = cal.getTime();

日付Javadocを見てください。

http://download.Oracle.com/javase/6/docs/api/Java/util/Date.html

229
BuffaloBuffalo

tl; dr

LocalDate.of( 1985 , 1 , 1 )

…または…

LocalDate.of( 1985 , Month.JANUARY , 1 )

詳細

Java.util.DateJava.util.Calendar、およびJava.text.SimpleDateFormatクラスは、Javaが最初に起動および進化したときに非常に速く実行されました。クラスは適切に設計または実装されていませんでした。改善が試みられたため、廃止されたことがわかりました。残念ながら、改善の試みはほとんど失敗しました。 これらのクラスは避けてくださいを合わせてください。それらは、Java 8の新しいクラスに取って代わりました。

コードの問題

Java.util.Dateには、日付部分と時刻部分の両方があります。コードの時間部分を無視しました。したがって、Dateクラスは、JVMのデフォルトのタイムゾーンで定義された1日の始まりを取得し、その時間をDateオブジェクトに適用します。したがって、コードの結果は、実行するマシンまたは設定されているタイムゾーンによって異なります。おそらくあなたが望むものではありません。

生年月日など、時間部分を除いた日付だけが必要な場合は、Dateオブジェクトを使用したくない場合があります。日付の文字列のみを ISO 8601YYYY-MM-DDの形式で保存することができます。または、Joda-Timeの LocalDate オブジェクトを使用します(以下を参照)。

ジョーダタイム

Javaで最初に学ぶこと:悪名高い厄介なJava.util.DateおよびJava.util.Calendarクラスを避ける Javaにバンドル。

ser3277382による回答 に正しく記載されているように、Java 8では Joda-Time または新しい Java.time。*パッケージ を使用します。

Joda-Time 2.3のサンプルコード

DateTimeZone timeZoneNorway = DateTimeZone.forID( "Europe/Oslo" );
DateTime birthDateTime_InNorway = new DateTime( 1985, 1, 1, 3, 2, 1, timeZoneNorway );

DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );
DateTime birthDateTime_InNewYork = birthDateTime_InNorway.toDateTime( timeZoneNewYork ); 

DateTime birthDateTime_UtcGmt = birthDateTime_InNorway.toDateTime( DateTimeZone.UTC );

LocalDate birthDate = new LocalDate( 1985, 1, 1 );

コンソールにダンプ…

System.out.println( "birthDateTime_InNorway: " + birthDateTime_InNorway );
System.out.println( "birthDateTime_InNewYork: " + birthDateTime_InNewYork );
System.out.println( "birthDateTime_UtcGmt: " + birthDateTime_UtcGmt );
System.out.println( "birthDate: " + birthDate );

実行すると…

birthDateTime_InNorway: 1985-01-01T03:02:01.000+01:00
birthDateTime_InNewYork: 1984-12-31T21:02:01.000-05:00
birthDateTime_UtcGmt: 1985-01-01T02:02:01.000Z
birthDate: 1985-01-01

Java.time

この場合、 Java.time のコードは Joda-Time のコードとほぼ同じです。

タイムゾーンを取得し( ZoneId )、そのタイムゾーンに割り当てられた日時オブジェクトを構築します( ZonedDateTime )。次に、 Immutable Objects パターンを使用して、古いオブジェクトの同じ瞬間( Epoch からのナノ秒数)に基づいて新しい日時を作成しますが、他のタイムゾーンを割り当てます。最後に LocalDate を取得しますが、これは時刻もタイムゾーンもありませんが、その日付を決定するときにタイムゾーンが適用されることに注意してください(新しい日は Osloニューヨーク たとえば)。

ZoneId zoneId_Norway = ZoneId.of( "Europe/Oslo" );
ZonedDateTime zdt_Norway = ZonedDateTime.of( 1985 , 1 , 1 , 3 , 2 , 1 , 0 , zoneId_Norway );

ZoneId zoneId_NewYork = ZonedId.of( "America/New_York" );
ZonedDateTime zdt_NewYork = zdt_Norway.withZoneSameInstant( zoneId_NewYork );

ZonedDateTime zdt_Utc = zdt_Norway.withZoneSameInstant( ZoneOffset.UTC );  // Or, next line is similar.
Instant instant = zdt_Norway.toInstant();  // Instant is always in UTC.

LocalDate localDate_Norway = zdt_Norway.toLocalDate();

Java.timeについて

Java.time フレームワークは、Java 8以降に組み込まれています。これらのクラスは、厄介な古い legacyJava.util.DateCalendar 、& SimpleDateFormat などの日時クラスに取って代わります。

Joda-Time プロジェクトは、現在 メンテナンスモード であり、 Java.time への移行を推奨しています=クラス。

詳細については、 Oracle Tutorial を参照してください。また、Stack Overflowで多くの例と説明を検索してください。指定は JSR 31 です。

データベースとJava.timeオブジェクトを直接交換できます。 JDBC 4.2 以降に準拠する JDBCドライバー を使用します。文字列もJava.sql.*クラスも必要ありません。

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

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

ThreeTen-Extra プロジェクトは、追加のクラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性のある証明の場です。 IntervalYearWeekYearQuartermore などの便利なクラスがあります。

63
Basil Bourque

新しい質問 の複製としてこの質問に出くわしました。特定の年、月、日でDateを取得する非推奨の方法を尋ねました。

ここまでの答えは、これまでCalendarクラスを使用すると言っていましたが、Java 8が登場するまではそうでした。ただし、Java 8では、これを行う標準的な方法は次のとおりです。

LocalDate localDate = LocalDate.of(1985, 1, 1);

そして、本当に本当にJava.util.Dateが必要な場合は、 この質問 の提案を使用できます。

詳細については、Java 8の the API または the tutorials をご覧ください。

11
Kevin Workman

コンストラクターが非推奨になった理由の1つは、yearパラメーターの意味が期待したものではないことです。 javadocによると:

JDKバージョン1.1以降、Calendar.set(year + 1900, month, date)に置き換えられました。

年フィールドは1900以降の年数であることに注意してください。そのため、サンプルコードは期待どおりに動作しない可能性があります。それがポイントです。

一般に、Date APIは現代の西暦のみをサポートし、コンポーネントを特異的に指定し、フィールドを設定すると一貫性のない動作をします。

CalendarおよびGregorianCalendar APIはDateよりも優れており、一般にサードパーティのJoda-time APIが最適であると考えられていました。 Java 8では、Java.timeパッケージが導入されましたが、これらは現在推奨される代替手段です。

10
Stephen C

Calendar.getTime()は、day time部分がデフォルトで現在の時刻になるという意味で非決定的であることに注意してください。

再現するには、次のコードを数回実行してみてください。

Calendar c = Calendar.getInstance();
c.set(2010, 2, 7); // NB: 2 means March, not February!
System.err.println(c.getTime());

出力例:

Sun Mar 07 10:46:21 CET 2010

数分後にまったく同じコードを実行すると、次の結果が得られます。

Sun Mar 07 10:57:51 CET 2010

したがって、set()は対応するフィールドに値を強制的に強制しますが、他のフィールドのシステム時間をリークします。 (Sun jdk6およびjdk7で上記でテスト済み)

8
Tijn Porcelijn

Date自体は非推奨ではありません。その方法の多くはただです。 詳細はこちらを参照

代わりに Java.util.Calendar を使用してください。

6
Mike Thomsen

現在、ほとんどのJava開発者はサードパーティパッケージ Joda-Time を使用しています。はるかに優れた実装であると広く考えられています。

Java 8 ただし、新しい Java.time。*パッケージ が追加されます。この記事 JDK 8の新しい日時APIの紹介 を参照してください。

5
davesbrain

Calendarクラスを使用して、コード内でnew Date(year,month,date)のようなメソッドを作成できます。

private Date getDate(int year,int month,int date){
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.MONTH, month-1);
    cal.set(Calendar.DAY_OF_MONTH, day);
    return cal.getTime();
}

Dateの非推奨のコンストラクターと同じように機能します

1
Sudhanshu Dubey

Binnybが提案したものと同様に、新しいCalendar> GregorianCalendarメソッドの使用を検討できます。これらの最近のドキュメントを参照してください。

http://download.Oracle.com/javase/6/docs/api/Java/util/GregorianCalendar.html

1
Joshua
new GregorianCalendar(1985, Calendar.JANUARY, 1).getTime();

(Java 8以前の方法)

0
Curtis Yallop

Dateコンストラクターは、1900年からの年、ゼロから始まる月の形式の年を期待し、時間/分/秒/ミリ秒をゼロに設定します。

Date result = new Date(year, month, day);

したがって、廃止予定のDateコンストラクターにCalendarの置換(ゼロベースの年、ゼロベースの月、1ベースの日)を使用すると、次のようなものが必要になります。

Calendar calendar = Calendar.getInstance();
calendar.clear(); // Sets hours/minutes/seconds/milliseconds to zero
calendar.set(year + 1900, month, day);
Date result = calendar.getTime();

または、Java 1.8(ゼロベースの年と1ベースの月と日があります)を使用します:

Date result = Date.from(LocalDate.of(year + 1900, month + 1, day).atStartOfDay(ZoneId.systemDefault()).toInstant());

Date、Calendar、およびJava 1.8の同等のバージョンを次に示します。

int year = 1985; // 1985
int month = 1; // January
int day = 1; // 1st

// Original, 1900-based year, zero-based month, one-based day
Date date1 = new Date(year - 1900, month - 1, day);

// Calendar, zero-based year, zero-based month, one-based day
Calendar calendar = Calendar.getInstance();
calendar.clear(); // Sets hours/minutes/seconds/milliseconds to zero
calendar.set(year, month - 1, day);
Date date2 = calendar.getTime();

// Java-time back to Date, zero-based year, one-based month, one-based day
Date date3 = Date.from(LocalDate.of(year, month, day).atStartOfDay(ZoneId.systemDefault()).toInstant());

SimpleDateFormat format = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss.SSS");

// All 3 print "1985-Jan-01 00:00:00.000"
System.out.println(format.format(date1));
System.out.println(format.format(date2));
System.out.println(format.format(date3));
0