回答:
ZonedDateTimeをインスタントに変換できます。これは、Dateで直接使用できます。
Date.from(java.time.ZonedDateTime.now().toInstant());
Date
はエポックからのミリ秒数です-そのため、UTCに関連しています。あなたがいる場合、印刷、それを、デフォルトのタイムゾーンが使用されますが、Dateクラスは、ユーザーのタイムゾーンの知識を持たない...を参照してくださいたとえばで「マッピング」セクションdocs.oracle.com/javase/tutorial/datetime/iso/legacy .htmlそしてLocalDateTimeは明示的にタイムゾーンを参照せずにいます-これは混乱を招くように見える
ZonedDateTime
ます。このjava.time.Instant
クラスはの直接の置き換えでありjava.util.Date
、どちらもUTCの瞬間を表しますInstant
が、ミリ秒ではなくナノ秒のより細かい分解能を使用します。Date.from( Instant.now() )
あなたのソリューションでなければなりませんでした。あるいはnew Date()
、同じことをするだけで、UTCで現在の瞬間を捉えます。
java.util.Date.from( // Transfer the moment in UTC, truncating any microseconds or nanoseconds to milliseconds.
Instant.now() ; // Capture current moment in UTC, with resolution as fine as nanoseconds.
)
上記のコードには意味がありませんでしたが。とは両方ともUTCでの瞬間java.util.Date
をInstant
表し、常にUTCで表します。上記のコードは次と同じ効果があります。
new java.util.Date() // Capture current moment in UTC.
ここではを使用してもメリットはありませんZonedDateTime
。すでにがある場合は、ZonedDateTime
を抽出してUTCに調整しInstant
ます。
java.util.Date.from( // Truncates any micros/nanos.
myZonedDateTime.toInstant() // Adjust to UTC. Same moment, same point on the timeline, different wall-clock time.
)
回答によるssoltanidは正しく新しい学校のjava.timeオブジェクトを(変換する方法を、あなたの特定の質問に取り組むZonedDateTime
古い学校に)java.util.Date
オブジェクト。Instant
ZonedDateTimeからを抽出してに渡しjava.util.Date.from()
ます。
あなたがすることに注意してくださいデータの損失を被るよう、Instant
トラックナノ秒ので、エポック中java.util.Date
のトラックのミリ秒エポック。
あなたの質問とコメントは他の問題を引き起こします。
サーバーのホストOSは、一般的にベストプラクティスとしてUTCに設定する必要があります。JVMは、私が知っているJava実装で、このホストOS設定をデフォルトのタイムゾーンとしてピックアップします。
ただし、JVMの現在のデフォルトのタイムゾーンに依存することはできません。ホスト設定を取得するのではなく、JVMの起動時に渡されるフラグにより別のタイムゾーンを設定できます。さらに悪いことに、任意のアプリの任意のスレッドの任意のコードがいつでもを呼び出してjava.util.TimeZone::setDefault
、実行時にそのデフォルトを変更できます!
Timestamp
タイプ適切なデータベースとドライバーはすべて、渡された日時をUTCに合わせて格納するための調整を自動的に処理する必要があります。私はCassandraを使用していませんが、日付と時刻の基本的なサポートがあるようです。ドキュメントでは、そのTimestamp
型は同じエポック(UTCでの1970年の最初の瞬間)からのミリ秒のカウントであると述べています。
さらに、CassandraはISO 8601標準形式の文字列入力を受け入れます。さいわい、java.timeは、文字列の解析/生成のデフォルトとしてISO 8601形式を使用します。Instant
クラスのtoString
実装がうまく行います。
しかし、最初に、ZonedDateTimeのナノ秒の精度をミリ秒に減らす必要があります。1つの方法は、ミリ秒を使用して新しいインスタントを作成することです。幸い、java.timeには、ミリ秒単位の変換を行う便利なメソッドがいくつかあります。
以下は、Java 8 Update 60のコード例です。
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
…
Instant instant = zdt.toInstant();
Instant instantTruncatedToMilliseconds = Instant.ofEpochMilli( instant.toEpochMilli() );
String fodderForCassandra = instantTruncatedToMilliseconds.toString(); // Example: 2015-08-18T06:36:40.321Z
または、このCassandra Javaドライバーのドキュメントによれば、java.util.Date
インスタンスを渡すことができます(と混同しないでくださいjava.sqlDate
)。したがってinstantTruncatedToMilliseconds
、上のコードでそれからjuDateを作成できます。
java.util.Date dateForCassandra = java.util.Date.from( instantTruncatedToMilliseconds );
これを頻繁に行う場合は、ワンライナーを作成できます。
java.util.Date dateForCassandra = java.util.Date.from( zdt.toInstant() );
しかし、少しユーティリティメソッドを作成するほうがきれいです。
static public java.util.Date toJavaUtilDateFromZonedDateTime ( ZonedDateTime zdt ) {
Instant instant = zdt.toInstant();
// Data-loss, going from nanosecond resolution to milliseconds.
java.util.Date utilDate = java.util.Date.from( instant ) ;
return utilDate;
}
質問よりもこのすべてのコードの違いに注意してください。質問のコードは、ZonedDateTimeインスタンスのタイムゾーンをUTCに調整しようとしました。しかし、それは必要ではありません。概念的に:
ZonedDateTime = Instant + ZoneId
すでにUTCにあるインスタント部分を抽出するだけです(基本的にはUTCで、詳細についてはクラスのドキュメントをお読みください)。
java.timeのフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは面倒古い取って代わるレガシーのような日付時刻クラスをjava.util.Date
、Calendar
、& SimpleDateFormat
。
ジョダタイムプロジェクトは、今でメンテナンスモードへの移行をアドバイスjava.timeのクラス。
詳細については、Oracleチュートリアルを参照してください。スタックオーバーフローで多くの例と説明を検索してください。仕様はJSR 310です。
java.timeオブジェクトをデータベースと直接交換できます。JDBC 4.2以降に準拠したJDBCドライバーを使用します。文字列もクラスも必要ありません。java.sql.*
java.timeクラスはどこで入手できますか?
ThreeTen-エクストラプロジェクトでは、追加のクラスでjava.timeを拡張します。このプロジェクトは、java.timeに将来追加される可能性があることを証明する場です。あなたはここにいくつかの有用なクラスのような見つけることがInterval
、YearWeek
、YearQuarter
、および多くを。
現在のシステム時刻をUTCに変換する例を次に示します。これには、ZonedDateTimeを文字列としてフォーマットし、Stringオブジェクトをjava.text DateFormatを使用して日付オブジェクトに解析します。
ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC);
final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
final DateFormat FORMATTER_YYYYMMDD_HH_MM_SS = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
String dateStr = zdt.format(DATETIME_FORMATTER);
Date utcDate = null;
try {
utcDate = FORMATTER_YYYYMMDD_HH_MM_SS.parse(dateStr);
}catch (ParseException ex){
ex.printStackTrace();
}
Android のThreeTenバックポートを使用していて、新しいDate.from(Instant instant)
API(最低限のAPI 26が必要)を使用できない場合は、以下を使用できます。
ZonedDateTime zdt = ZonedDateTime.now();
Date date = new Date(zdt.toInstant().toEpochMilli());
または:
Date date = DateTimeUtils.toDate(zdt.toInstant());
バジル・ブルクの回答のアドバイスも読んでください
DateTimeUtils
変換メソッドを含むクラスが含まれているため、Date date = DateTimeUtils.toDate(zdt.toInstant()); `を使用します。それほど低レベルではありません。
これは、Java 8以降に組み込まれているjava.timeクラスを使用して行うことができます。
ZonedDateTime temporal = ...
long epochSecond = temporal.getLong(INSTANT_SECONDS);
int nanoOfSecond = temporal.get(NANO_OF_SECOND);
Date date = new Date(epochSecond * 1000 + nanoOfSecond / 1000000);
Instant
■秒とナノ秒を追跡します。 Date
sミリ秒を追跡します。この一方から他方への変換は正しいです。
これを使っています。
public class TimeTools {
public static Date getTaipeiNowDate() {
Instant now = Instant.now();
ZoneId zoneId = ZoneId.of("Asia/Taipei");
ZonedDateTime dateAndTimeInTai = ZonedDateTime.ofInstant(now, zoneId);
try {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateAndTimeInTai.toString().substring(0, 19).replace("T", " "));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
動か
Date.from(java.time.ZonedDateTime.ofInstant(now, zoneId).toInstant());
ないから!!! コンピューターでアプリケーションを実行する場合、問題はありません。ただし、AWS、Docker、またはGCPのいずれかのリージョンで実行すると、問題が発生します。コンピューターはクラウド上のタイムゾーンではないからです。コードでタイムゾーンを正しく設定する必要があります。たとえば、Asia / Taipeiです。その後、AWS、Docker、またはGCPで修正されます。
public class App {
public static void main(String[] args) {
Instant now = Instant.now();
ZoneId zoneId = ZoneId.of("Australia/Sydney");
ZonedDateTime dateAndTimeInLA = ZonedDateTime.ofInstant(now, zoneId);
try {
Date ans = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateAndTimeInLA.toString().substring(0, 19).replace("T", " "));
System.out.println("ans="+ans);
} catch (ParseException e) {
}
Date wrongAns = Date.from(java.time.ZonedDateTime.ofInstant(now, zoneId).toInstant());
System.out.println("wrongAns="+wrongAns);
}
}
ans=Mon Jun 18 01:07:56 CEST 2018
、不正解である、そしてwrongAns=Sun Jun 17 17:07:56 CEST 2018
正解が表示されました。
受け入れられた答えは私にとってうまくいきませんでした。返される日付は常にローカルの日付であり、元のタイムゾーンの日付ではありません。私はUTC + 2に住んでいます。
//This did not work for me
Date.from(java.time.ZonedDateTime.now().toInstant());
ZonedDateTimeから正しい日付を取得する2つの方法があります。
ハワイのこのZonedDateTimeがあるとします
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneId.of("US/Hawaii"); // UTC-10
またはもともと尋ねられたUTCの場合
Instant zulu = Instant.now(); // GMT, UTC+0
ZonedDateTime zdt = zulu.atZone(ZoneId.of("UTC"));
代替案1
java.sql.Timestampを使用できます。シンプルですが、プログラミングの整合性にも影響があります。
Date date1 = Timestamp.valueOf(zdt.toLocalDateTime());
代替案2
ミリ秒から日付を作成します(ここで前に回答しました)。ローカルZoneOffsetは必須であることに注意してください。
ZoneOffset localOffset = ZoneOffset.systemDefault().getRules().getOffset(LocalDateTime.now());
long zonedMillis = 1000L * zdt.toLocalDateTime().toEpochSecond(localOffset) + zdt.toLocalDateTime().getNano() / 1000000L;
Date date2 = new Date(zonedMillis);
beehuangのようなDockerアプリケーションについては、タイムゾーンを設定する必要があるとコメントしています。
あるいは、withZoneSameLocalを使用できます。例えば:
2014-07-01T00:00 + 02:00 [GMT + 02:00]は、
Date.from(zonedDateTime.withZoneSameLocal(ZoneId.systemDefault()).toInstant())
火7月1日午後12時00分00秒2014 CESTとによって、
Date.from(zonedDateTime.toInstant())
月6月30日夜09時00分00秒UTC 2014
今だけ興味がある場合は、次のように使用してください:
Date d = new Date();
java.util.Date
ありjava.sql.Date
ます。