a java.util.Date
からa を解析しましたString
が、ローカルタイムゾーンをdate
オブジェクトのタイムゾーンとして設定しています。
解析されるString
fromでタイムゾーンが指定されていませんDate
。date
オブジェクトの特定のタイムゾーンを設定したい。
どうやってやるの?
a java.util.Date
からa を解析しましたString
が、ローカルタイムゾーンをdate
オブジェクトのタイムゾーンとして設定しています。
解析されるString
fromでタイムゾーンが指定されていませんDate
。date
オブジェクトの特定のタイムゾーンを設定したい。
どうやってやるの?
回答:
DateFormatを使用します。例えば、
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = isoFormat.parse("2010-05-23T09:01:02");
TimeZone.setDefault()
呼び出す前にgetTime()
、新しい日付オブジェクトが必要なタイムゾーンになるようにする必要があります。JDK 1.8では、をCalendar.getTime()
呼び出しますreturn new Date(getTimeInMillis());
。
java.util.Date
オブジェクト自体にはタイムゾーン情報が含まれていないことに注意してくださいDate
。オブジェクトにタイムゾーンを設定することはできません。Date
オブジェクトに含まれる唯一のものは、「エポック」からのミリ秒数-1970年1月1日00:00:00 UTCです。
ZZ Coderが示すように、DateFormat
オブジェクトにタイムゾーンを設定して、日付と時刻を表示するタイムゾーンを伝えます。
long
と呼ばれるフィールドがほとんどありますfastTime
。Date.toString()
実際には、Calendar
このミリ秒の時間を解釈するためにa を使用します。したがって、aを出力Date
すると、(デフォルトの)タイムゾーンがあるように見え、そのタイムゾーンの設定方法について理解しやすい質問が表示されます。
…解析された…文字列から…時間帯が指定されていない…特定の時間帯を設定したい
LocalDateTime.parse( "2018-01-23T01:23:45.123456789" ) // Parse string, lacking an offset-from-UTC and lacking a time zone, as a `LocalDateTime`.
.atZone( ZoneId.of( "Africa/Tunis" ) ) // Assign the time zone for which you are certain this date-time was intended. Instantiates a `ZonedDateTime` object.
他の正解が述べたように、java.util.Dateにはタイムゾーンがありません†。UTC / GMTを表します(タイムゾーンオフセットなし)。toString
文字列表現を生成するときにそのメソッドがJVMのデフォルトのタイムゾーンを適用するため、非常に混乱します。
このため、他の多くの理由により、組み込みのjava.util.Date&.Calendar&java.text.SimpleDateFormatの使用は避けてください。彼らは悪名高いほど厄介です。
代わりに、Java 8にバンドルされているjava.timeパッケージを使用してください。
java.timeクラスは、3つの方法でタイムライン上の瞬間を表すことができます。
Instant
)OffsetDateTime
ありZoneOffset
)ZonedDateTime
ありZoneId
)Instant
でjava.time、基本的なビルディング・ブロックであるInstant
、UTCのタイムライン上の瞬間。Instant
ビジネスロジックのほとんどにオブジェクトを使用します。
Instant instant = Instant.now();
OffsetDateTime
UTCからのオフセットを適用して、地域の実時間に合わせます。
ZoneOffset
を取得するにはを適用しますOffsetDateTime
。
ZoneOffset zoneOffset = ZoneOffset.of( "-04:00" );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );
ZonedDateTime
ベターは適用することであるタイムゾーン、オフセットプラスなどの異常処理するためのルール夏時間(DST)を。
をに適用ZoneId
してInstant
を取得しZonedDateTime
ます。常に適切なタイムゾーン名を指定してください。など3-4略語は使用しないでくださいEST
またはIST
ユニークでも標準化でもありません。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
LocalDateTime
入力文字列にオフセットまたはゾーンのインジケーターがない場合は、として解析しますLocalDateTime
。
意図したタイムゾーンに確信がある場合は、を割り当ててZoneId
を生成しZonedDateTime
ます。上記のtl; drセクションのコード例を参照してください。
toString
これらの3つのクラスのいずれかでメソッドを呼び出して、標準のISO 8601形式で日時値を表す文字列を生成します。ZonedDateTime
クラスは、括弧内のタイムゾーンの名前を追加することによって、標準的なフォーマットを拡張しています。
String outputInstant = instant.toString(); // Ex: 2011-12-03T10:15:30Z
String outputOdt = odt.toString(); // Ex: 2007-12-03T10:15:30+01:00
String outputZdt = zdt.toString(); // Ex: 2007-12-03T10:15:30+01:00[Europe/Paris]
他のフォーマットについてはDateTimeFormatter
クラスを使用してください。一般に、そのクラスに、ユーザーの予想される人間の言語と文化的規範を使用してローカライズされたフォーマットを生成させるのが最善です。または、特定のフォーマットを指定できます。
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
、および多くを。
一方でジョダ時はまだ積極的に維持され、そのメーカーはすぐに便利なようjava.timeへの移行を私たちに語っています。このセクションは参照用としてそのまま残していますが、java.time
代わりに上記のセクションを使用することをお勧めします。
でジョダタイム、日付時刻オブジェクト(DateTime
)本当にその割り当てられたタイムゾーンを知っているん。これは、UTCからのオフセットと、そのタイムゾーンの夏時間(DST)の規則と履歴、およびその他のそのような異常を意味します。
String input = "2014-01-02T03:04:05";
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( input, timeZone );
DateTime dateTimeUtcGmt = dateTimeIndia.withZone( DateTimeZone.UTC );
toString
メソッドを呼び出して、文字列をISO 8601形式で生成します。
String output = dateTimeIndia.toString();
Joda-Timeは、他のあらゆる種類の文字列フォーマットを生成するための豊富な機能も提供します。
必要に応じて、Joda-Time DateTimeからjava.util.Dateに変換できます。
Java.util.Date date = dateTimeIndia.toDate();
StackOverflowで「joda date」を検索して、さらに詳細な例を見つけてください。
†実際には、java.util.Dateに埋め込まれたタイムゾーンがあり、一部の内部関数に使用されています(この回答のコメントを参照)。ただし、この内部タイムゾーンはプロパティとして公開されていないため、設定できません。この内部タイムゾーンは、日付時刻値の文字列表現を生成するときにメソッドが使用するものではありませんtoString
。代わりに、JVMの現在のデフォルトのタイムゾーンがオンザフライで適用されます。したがって、省略形として、「juDateにはタイムゾーンがない」とよく言います。混乱していますか?はい。これらの疲れた古いクラスを避けるもう一つの理由。
BaseCalendar.Date cdate
設定されている場合、そのプロパティに格納されているjuDateのタイムゾーン情報があります。ここでソースコードを見てください。を呼び出してJVMのデフォルトのタイムゾーンを変更しない限り、juDateオブジェクトのタイムゾーンを設定することはできませんTimeZone.setDefault(TimeZone.getTimeZone("NEW_TIME_ZONE"));
。したがって、タイムゾーンのオフセットがあり、非推奨のメソッドjuDate.getTimezoneOffset()を呼び出すことでオフセットを取得できます
toString
JVMの現在のデフォルトのタイムゾーンを適用するメソッドを除きます。埋もれた時間帯を再び無視します。したがって、簡潔にするために、java.util.Dateにはタイムゾーンがないと言います。アートのように、それは真実を語る嘘です。
TimeZone.setDefault
、あなたがされていない java.util.Dateオブジェクトのタイムゾーンを設定する- DateオブジェクトがまだUTCに効果的に作用して、その埋葬タイムゾーンを無視します。日付のtoString
方法に影響します。デフォルトを設定すると、通常はホストオペレーティングシステムのタイムゾーンに設定されるJVMのデフォルトタイムゾーンが変更されます。その呼び出しは、そのJVMで実行されているすべてのアプリのすべてのスレッドのすべてのコードに影響し、実行中にオンザフライで実行されるため、お勧めしません。失礼で危険なため、この電話は最後の手段と見なす必要があります。
equals
、hashcode
、getTime
...)あなたが見てみましょう場合equals
の方法、それが呼び出すgetTime()
どの呼び出しgetTimeImpl()
、その呼び出しnormalize()
た場合cdate
プロパティは正規化されていません。normalize()
方法、最後には、条件の時間帯があれば、その記憶されたタイムゾーン情報に基づいて1/1/70からのミリ秒を再計算する場合cdate
、それが実行されている現在のJVM環境のタイムゾーンとは異なるが。(ご覧くださいsun.util.calendar.AbstractCalendar getCalendarDate(long millis, CalendarDate date)
)
JVMレベルでタイムゾーンを設定することもできます
Date date1 = new Date();
System.out.println(date1);
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
// or pass in a command line arg: -Duser.timezone="UTC"
Date date2 = new Date();
System.out.println(date2);
出力:
Thu Sep 05 10:11:12 EDT 2013
Thu Sep 05 14:11:12 UTC 2013
TimeZone.setDefault
は、JVM全体に影響し、他のすべてのオブジェクトとスレッドに影響するため、かなり劇的です。参照してくださいこの回答あなたはSecurityManagerをして実行している場合でも、多くの合併症を含む詳細については、を。さらに複雑になる:この質問で説明されているように、この動作はさまざまなバージョンのJavaで変更されています。
標準のJDKクラスのみを使用する必要がある場合は、次のように使用できます。
/**
* Converts the given <code>date</code> from the <code>fromTimeZone</code> to the
* <code>toTimeZone</code>. Since java.util.Date has does not really store time zome
* information, this actually converts the date to the date that it would be in the
* other time zone.
* @param date
* @param fromTimeZone
* @param toTimeZone
* @return
*/
public static Date convertTimeZone(Date date, TimeZone fromTimeZone, TimeZone toTimeZone)
{
long fromTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, fromTimeZone);
long toTimeZoneOffset = getTimeZoneUTCAndDSTOffset(date, toTimeZone);
return new Date(date.getTime() + (toTimeZoneOffset - fromTimeZoneOffset));
}
/**
* Calculates the offset of the <code>timeZone</code> from UTC, factoring in any
* additional offset due to the time zone being in daylight savings time as of
* the given <code>date</code>.
* @param date
* @param timeZone
* @return
*/
private static long getTimeZoneUTCAndDSTOffset(Date date, TimeZone timeZone)
{
long timeZoneDSTOffset = 0;
if(timeZone.inDaylightTime(date))
{
timeZoneDSTOffset = timeZone.getDSTSavings();
}
return timeZone.getRawOffset() + timeZoneDSTOffset;
}
クレジットはこの投稿に行きます。
java.util.Calendar
JDKクラスだけを使用してタイムゾーンを処理する通常の方法です。Apache Commonsには、さらに役立つ可能性のある代替/ユーティリティがいくつかあります。Edit Spongのメモは、私がJoda-Timeについて本当に良いことを聞いたことを思い出させました(私自身はそれを使用していません)。
Period
、Duration
とInterval
。これらのスパンは、次のような比較方法を含むcontains
、abuts
、overlap
、およびgap
。そしてPeriodFormatterBuilder
、このような「15年と8ヶ月」などの記述的なフレーズを構築することができます。
日付を文字列に変換し、SimpleDateFormatでそれを行います。
SimpleDateFormat readFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
readFormat.setTimeZone(TimeZone.getTimeZone("GMT" + timezoneOffset));
String dateStr = readFormat.format(date);
SimpleDateFormat writeFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date date = writeFormat.parse(dateStr);
誰かがこれを必要とする場合、XMLGregorianCalendar
タイムゾーンをUTCから現在のタイムゾーンに変換する必要がある場合は、タイムゾーンを0
に設定し、次に呼び出すだけtoGregorianCalendar()
です。同じタイムゾーンのままですが、Date
変換方法はわかっています。そこからデータを取得できます。
XMLGregorianCalendar xmlStartTime = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(
((GregorianCalendar)GregorianCalendar.getInstance());
xmlStartTime.setTimezone(0);
GregorianCalendar startCalendar = xmlStartTime.toGregorianCalendar();
Date startDate = startCalendar.getTime();
XMLGregorianCalendar xmlStartTime = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(startCalendar);
xmlStartTime.setHour(startDate.getHours());
xmlStartTime.setDay(startDate.getDate());
xmlStartTime.setMinute(startDate.getMinutes());
xmlStartTime.setMonth(startDate.getMonth()+1);
xmlStartTime.setTimezone(-startDate.getTimezoneOffset());
xmlStartTime.setSecond(startDate.getSeconds());
xmlStartTime.setYear(startDate.getYear() + 1900);
System.out.println(xmlStartTime.toString());
結果:
2015-08-26T12:02:27.183Z
2015-08-26T14:02:27.183+02:00
このコードは、私が取り組んでいるアプリで役に立ちました:
Instant date = null;
Date sdf = null;
String formatTemplate = "EEE MMM dd yyyy HH:mm:ss";
try {
SimpleDateFormat isoFormat = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss");
isoFormat.setTimeZone(TimeZone.getTimeZone(ZoneId.of("US/Pacific")));
sdf = isoFormat.parse(timeAtWhichToMakeAvailable);
date = sdf.toInstant();
} catch (Exception e) {
System.out.println("did not parse: " + timeAtWhichToMakeAvailable);
}
LOGGER.info("timeAtWhichToMakeAvailable: " + timeAtWhichToMakeAvailable);
LOGGER.info("sdf: " + sdf);
LOGGER.info("parsed to: " + date);