String
からJava.util.Date
を解析しましたが、ローカルタイムゾーンをdate
オブジェクトのタイムゾーンとして設定しています。
String
の解析元の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");
Java.util.Date
オブジェクトは、それ自体ではタイムゾーン情報を含まないことに注意してください - タイムゾーンをDate
オブジェクトに設定することはできません。 Date
オブジェクトに含まれる唯一のものは、 "Epoch"からのミリ秒数 - 1970年1月1日、UTC 00:00:00です。
ZZ Coderが示すように、DateFormat
オブジェクトにタイムゾーンを設定して、日付と時刻を表示したいタイムゾーンを指定します。
…解析した…文字列から…タイムゾーンが指定されていない…特定のタイムゾーンを設定したい
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.timeパッケージ を Java 8 にバンドルして使用してください。
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
タイムゾーン 、オフセットplus夏時間(DST) などの規則を適用することをお勧めします。 。
ZoneId
をInstant
に適用して ZonedDateTime
を取得します。常に 適切なタイムゾーン名 を指定してください。 EST
やIST
など、一意でも標準化されてもいない3〜4の略語は絶対に使用しないでください。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
LocalDateTime
入力文字列にオフセットまたはゾーンのインジケータがない場合は、 LocalDateTime
として解析します。
意図したタイムゾーンが確実な場合は、ZoneId
を割り当ててZonedDateTime
を生成します。上のtl; drセクションにある上記のコード例を参照してください。
これら3つのクラスのいずれかでtoString
メソッドを呼び出して、標準の ISO 8601 形式で日時値を表すStringを生成します。 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
などの厄介な古い レガシー 日時クラスに代わるものです。
Joda-Time プロジェクトは メンテナンスモード になっており、 Java.time に移行することをお勧めします。クラス。
詳細については、 Oracleチュートリアル を参照してください。そして多くの例と説明についてはStack Overflowを検索してください。指定は JSR 310 です。
あなたのデータベースとJava.timeオブジェクトを直接交換することができます。 JDBC 4.2 に準拠した JDBCドライバ を使用してください。文字列もJava.sql.*
クラスも必要ありません。
Java.timeクラスはどこで入手できますか?
ThreeTen-Extra プロジェクトは、追加クラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性があることを証明するものです。 Interval
、 YearWeek
、 YearQuarter
、 more など、便利なクラスがいくつかあります。
Joda-Time はまだ活発に維持されていますが、そのメーカーは都合がよいとすぐにJava.timeに移行するように私たちに言っています。このセクションは参照としてそのまま残しますが、代わりに上記のJava.time
セクションを使用することをお勧めします。
Joda-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に埋め込まれたタイムゾーンであり、いくつかの内部関数に使用されます(この回答のコメントを参照)。しかし、この内部タイムゾーンはプロパティとして公開されていないため、設定できません。この内部タイムゾーンは、not日時値の文字列表現を生成する際に toString
メソッドで使用されるものです。代わりに、JVMの現在のデフォルトタイムゾーンが即座に適用されます。そのため、簡単に言うと、「j.u.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
標準の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 には、役に立つかもしれない他の選択肢/ユーティリティがあります。 EditSpongのメモは、私が Joda-Time について本当に良いことを聞いたことを思い出させてくれました。自分では使っていません。
このコードは私が取り組んでいるアプリで役に立ちました:
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);
日付を文字列に変換して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