たまたま_Java.util.Date
_である変数に対して_Java.sql.Date
_のtoInstant()
を使用すると、UnsupportedOperationException
が得られます。
_try {
Java.util.Date input = new Java.sql.Date(System.currentTimeMillis());
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
} catch (UnsupportedOperationException e) {
// grrr!
}
_
私が関わっている_Java.util.Date
_は、レガシーAPIを介してmysql DBのDATEフィールドから取得され、実際には_Java.sql.Date
_です。
現在、次の関連する質問はすべて非常に興味深いものです。
nsupportedOperationException-Java.sql.DateでtoInstant()を呼び出せないのはなぜですか?
Java.util.DateをJava.time.LocalDateに変換
LocalDateからJava.util.Dateへ、またはその逆の最も単純な変換?
ただし、時間コンポーネントを削除してJava 8 LocalDate
を取得するために、_Java.util.Date
_を切り捨てるエレガントな方法は提供されていません。
あるタイムゾーンの同じ瞬間が別のタイムゾーンの同じ瞬間とは異なる日付になる可能性があるという問題があることを認めます。
ソリューションにはJava.util.Calendarが含まれると思いますが、独自のソリューションを作成するのではなく、他の人が最初に行ったことを確立したいと思います。
私はこれより短いものを見つけたいと思います:
from Javaでタイムスタンプの時間部分をリセットする :
_Date date = new Date(); // timestamp now Calendar cal = Calendar.getInstance(); // get calendar instance cal.setTime(date); // set cal to date cal.set(Calendar.HOUR_OF_DAY, 0); // set hour to midnight cal.set(Calendar.MINUTE, 0); // set minute in hour cal.set(Calendar.SECOND, 0); // set second in minute cal.set(Calendar.MILLISECOND, 0); // set millis in second Date zeroedDate = cal.getTime(); // actually computes the new Date
_
多くの場合、最も単純な解決策を見つけるのが最も困難です。
public LocalDate convertDateObject(Java.util.Date suspectDate) {
try {
// Don't do this if there is the smallest chance
// it could be a Java.sql.Date!
return suspectDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
} catch (UnsupportedOperationException e) {
// BOOM!!
}
// do this first:
Java.util.Date safeDate = new Date(suspectDate.getTime());
return safeDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
input
変数が_Java.sql.Date
_であることがわかっている場合は、それをキャストしてtoLocalDate()
メソッドを呼び出すことができます。
_LocalDate date = ((Java.sql.Date) input).toLocalDate();
_
残念ながら、_Java.sql.Date
_でtoInstant()
を呼び出すことはできません。これは、 javadocによる であるため、常にUnsupportedOperationException
がスローされるためです。
タイプがわからない場合(_Java.util.Date
_または_Java.sql.Date
_のいずれか)、getTime()
メソッドによって返される値を使用してInstant
次に、それをタイムゾーンに変換し(以下では、JVMのデフォルトを使用しています)、最後にローカル日付を取得します。
_LocalDate date = Instant
// get the millis value to build the Instant
.ofEpochMilli(input.getTime())
// convert to JVM default timezone
.atZone(ZoneId.systemDefault())
// convert to LocalDate
.toLocalDate();
_
toLocalDate()
メソッドは、残りを無視して日付部分(日/月/年)を取得するため、切り捨てる必要はありません。時刻が深夜、午前10時、またはその他の時間であるかどうかは関係ありません。時刻の場合、toLocalDate()
はそれを無視し、日付部分のみを取得します。
ただし、本当に時間を真夜中に設定したい場合は、 with
メソッド を使用して LocalTime
を渡すことができます。
_LocalDate date = Instant
// get the millis value to build the Instant
.ofEpochMilli(input.getTime())
// convert to JVM default timezone
.atZone(ZoneId.systemDefault())
// set time to midnight
.with(LocalTime.MIDNIGHT)
// convert to LocalDate
.toLocalDate();
_
しかし、私が言ったように、toLocalDate()
メソッドは時間部分を無視するだけなので、この場合、時間を設定する必要はありません(LocalDate
は同じになります)。
次のように、日付のタイプを確認し、それに応じて適切なアクションを選択することもできます。
_if (input instanceof Java.sql.Date) {
date = ((Java.sql.Date) input).toLocalDate();
} else {
date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
_
JVMのデフォルトのタイムゾーン(ZoneId.systemDefault()
)を使用する代わりに、ZoneId.of("zoneName")
を呼び出すことで、必要に応じて他のタイムゾーンを使用できます。ゾーン名は有効な-のいずれかです。 IANAタイムゾーン名 (常に_Region/City
_の形式で、_America/New_York
_または_Europe/London
_のように)。 3文字の略語(CET
やPST
など)は あいまいで標準ではない であるため、使用しないでください。
ZoneId.getAvailableZoneIds()
を呼び出すことにより、使用可能なタイムゾーンのリストを取得できます(そしてシステムに最適なタイムゾーンを選択できます)。必要に応じて、JVMのデフォルトのタイムゾーンを引き続き使用することもできますが、それを忘れないでください 実行時でも予告なしに変更できます ので、使用しているタイムゾーンを常に明示することをお勧めします。
myResultSet.getObject( … , LocalDate.class )
Java.sql.Date
、Java.util.Date
、Calendar
などの従来の日時クラスを使用すると問題が発生しました。これらのクラスは完全に避けてください。それらは現在レガシーであり、Java.timeクラスに取って代わられています。
値は、タイプDATE
のMySQL列に格納された値として始まったとおっしゃいました。このタイプは日付のみで、時刻はありません。したがって、不必要に時刻値を導入しました間違ったクラスを使用します。
JDBC 4.2以降に準拠したJDBCドライバーを使用して、Java.timeクラスを使用してデータベースと値を交換します。
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
そして、PreparedStatement
に渡します。
myPstmt.setObject( … , myLocalDate ) ;
これを試して。
Java.util.Date input = new Java.sql.Date(System.currentTimeMillis());
Instant instant = Instant.ofEpochMilli(input.getTime());
LocalDate date = instant .atZone(ZoneId.systemDefault()).toLocalDate();
Java.sql.Date
とJava.util.Date
の間の乗換えの前提が正しくありません。
たまたまJava.sql.Dateである変数に対してJava.util.Dateを使用する場合
クラスのドキュメントに記載されている契約に違反しました。 Java.sql.Date
がJava.util.Date
のサブクラスであるという事実を無視するように言われました。
しかし、解決策は非常に単純かもしれません。
ZonedDateTime zdt = myJavaSqlDate.toLocalDate().atStartOfDay( ZoneId.of( "America/Montreal" ) ) ;
どうやらあなたはJava.sql.Date
を手にしています。そのクラスは、時刻やタイムゾーンのない日付のみの値を表します。少なくともそれがそのクラスの意図です。 Java.util.Date
からサブクラス化するために、悲劇的に貧弱な設計上の選択が行われました。これは、名前にもかかわらず、UTCの日付および時刻を表します。この継承関係は、内部の時刻を「00:00:00」に設定するハック、悪いハックです。ドキュメントでは、この継承関係を無視し、時刻コンポーネントがあるという事実を無視し、2つのDate
クラスが無関係であると偽ることを明確に指示しています。しかし、著者などの多くの人々は、そのドキュメントを注意深く読んでおらず、クラス名に基づいて大まかな仮定をしています。
両方のDate
クラスは、Javaの初期バージョンに付属している日時フレームワークであるひどい混乱の一部です。これらは、Java 8以降に組み込まれているJava.timeクラスに取って代わられました。
従来の日時オブジェクトに遭遇したときの最初のステップ:古いクラスに追加された新しいメソッドを使用してJava.timeに変換します。
偽の日付のみのオブジェクトJava.sql.Date
をタイプJava.util.LocalDate
の真の日付のみのオブジェクトに変換します。 「ローカル」ワードは、タイムゾーンまたはUTCからのオフセットがないことを示します。
LocalDate ld = myJavaSqlDate.toLocalDate() ;
どうやら、その日付のみの値を時刻のある日付に変換したいようです。おそらくあなたはその日の最初の瞬間が欲しいでしょう。最初の瞬間を決定するには、タイムゾーンが必要です。たとえば、新しい日はEurope/Paris
よりもAmerica/Montreal
の方が早く、Asia/Kolkata
の方がまだ早く始まります。
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
理由はわかりませんが、このコードは私のために機能します:)
LocalDate ld = new Java.util.Date(personEntity.getBirthday()。getTime())。toInstant()。atZone(ZoneId.systemDefault())。toLocalDate();
そしてこれは機能しません:
LocalDate ld = personEntity.getBirthday()。getTime()。toInstant()。atZone(ZoneId.systemDefault())。toLocalDate();
SimpleDateFormatを使用して支援しようとしましたか?
import Java.text.ParseException;
import Java.text.SimpleDateFormat;
import Java.time.LocalDate;
import Java.time.ZoneId;
import Java.util.Date;
public class Utils {
private static SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd" );
public static void main( String[] args ) {
LocalDate ld = sqlDateToLocalDate( new Java.sql.Date( System.currentTimeMillis() ) );
System.out.println( ld );
}
public static LocalDate sqlDateToLocalDate( Java.sql.Date sqlDate ) {
try {
Date d = sdf.parse( sdf.format( sqlDate ) );
return d.toInstant().atZone( ZoneId.systemDefault() ).toLocalDate();
} catch ( ParseException exc ) {
}
return null;
}
}