プロジェクトであるタイムゾーンから別のタイムゾーンに変換する必要があります。
現在のタイムゾーンから別のタイムゾーンに変換することはできますが、別のタイムゾーンから別のタイムゾーンに変換することはできません。
たとえば、私はインドにいて、Date d=new Date();
を使用してインドから米国に変換し、カレンダーオブジェクトに割り当ててタイムゾーンを設定することができます。
ただし、異なるタイムゾーンから別のタイムゾーンにこれを行うことはできません。たとえば、私はインドにいますが、タイムゾーンを米国から英国に変換するのに問題があります。
ZonedDateTime.now( ZoneId.of( "Pacific/Auckland" )) // Current moment in a particular time zone.
.withZoneSameInstant( ZoneId.of( "Asia/Kolkata" )) // Same moment adjusted into another time zone.
Java.util.Dateクラスにはタイムゾーンが割り当てられていません†、それでもtoString
実装は紛らわしくJVMの現在のデフォルトのタイムゾーンを適用します。
これは、Javaにバンドルされている悪名高い厄介なJava.util.Date、.Calendar、およびSimpleDateFormatクラスを回避する多くの理由の1つです。それらを避けてください。代わりに次のいずれかを使用します。
Java 8以降には Java.timeパッケージ が組み込まれています。このパッケージは Joda-Time に触発されました。それらはいくつかの類似点とクラス名を共有していますが、異なっています。それぞれに、他にはない機能があります。注目すべき違いの1つは、Java.timeがコンストラクターを避け、代わりに静的インスタンス化メソッドを使用することです。両方のフレームワークは、同じ男性 Stephen Colbourne によって導かれています。
Java.time機能の多くは、 ThreeTen-Backport プロジェクトのJava 6&7にバックポートされています。さらに、Android ThreeTenABP プロジェクト。
この質問の場合、それらは同じ方法で機能します。タイムゾーンを指定し、 now
メソッドを呼び出して現在の瞬間を取得し、古い不変のインスタンスに基づいて新しいインスタンスを作成して、タイムゾーンを調整します。
2つの異なるタイムゾーンクラスに注意してください。 1つは、夏時間などのすべての規則に加えてUTCからのオフセットを含む名前付きタイムゾーンで、もう1つはオフセットのみです。
ZoneId zoneMontréal = ZoneId.of("America/Montreal");
ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal );
ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo");
ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo );
ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC );
Joda-Time 2.3のサンプルコードの一部を次に示します。 StackOveflowを検索して、さらに多くの例と多くの議論を探してください。
DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" );
DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );
DateTime nowLondon = DateTime.now( timeZoneLondon ); // Assign a time zone rather than rely on implicit default time zone.
DateTime nowKolkata = nowLondon.withZone( timeZoneKolkata );
DateTime nowNewYork = nowLondon.withZone( timeZoneNewYork );
DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC ); // Built-in constant for UTC.
宇宙のタイムラインには、同じ瞬間の4つの表現があります。
†実際、Java.util.Date
classdoesは、タイムゾーンを ソースコード に埋め込んでいます。しかし、クラスは最も実用的な目的のためにそのタイムゾーンを無視します。そのため、略記として、j.u.Dateにはタイムゾーンが割り当てられていないとよく言われます。紛らわしい?はい。 j.u.Dateである混乱を避け、Joda-TimeやJava.timeを使用してください。
いくつかの例
import Java.util.Calendar;
import Java.util.GregorianCalendar;
import Java.util.TimeZone;
public class TimeZoneExample {
public static void main(String[] args) {
// Create a calendar object and set it time based on the local
// time zone
Calendar localTime = Calendar.getInstance();
localTime.set(Calendar.HOUR, 17);
localTime.set(Calendar.MINUTE, 15);
localTime.set(Calendar.SECOND, 20);
int hour = localTime.get(Calendar.HOUR);
int minute = localTime.get(Calendar.MINUTE);
int second = localTime.get(Calendar.SECOND);
// Print the local time
System.out.printf("Local time : %02d:%02d:%02d\n", hour, minute, second);
// Create a calendar object for representing a Germany time zone. Then we
// wet the time of the calendar with the value of the local time
Calendar germanyTime = new GregorianCalendar(TimeZone.getTimeZone("Europe/Berlin"));
germanyTime.setTimeInMillis(localTime.getTimeInMillis());
hour = germanyTime.get(Calendar.HOUR);
minute = germanyTime.get(Calendar.MINUTE);
second = germanyTime.get(Calendar.SECOND);
// Print the local time in Germany time zone
System.out.printf("Germany time: %02d:%02d:%02d\n", hour, minute, second);
}
}
Date date = new Date();
String formatPattern = ....;
SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);
TimeZone T1;
TimeZone T2;
// set the Calendar of sdf to timezone T1
sdf.setTimeZone(T1);
System.out.println(sdf.format(date));
// set the Calendar of sdf to timezone T2
sdf.setTimeZone(T2);
System.out.println(sdf.format(date));
// Use the 'calOfT2' instance-methods to get specific info
// about the time-of-day for date 'date' in timezone T2.
Calendar calOfT2 = sdf.getCalendar();
「デフォルト」タイムゾーンは、Calendar
オブジェクトにタイムゾーンを適切に設定するだけで完全に回避できます。ただし、Javaでの日付と時刻の操作には、はるかに優れたAPIとして Joda Time を使用することを個人的にお勧めします。とりわけ、Jodaではタイムゾーンの変換は非常に簡単です。
現在のコードがどのようなものか、なぜデフォルトのタイムゾーンでしか変換できないのかは明確ではありませんが、Joda Timeでは DateTime
object、次にwithZone(DateTimeZone zone)
を使用します。
入力データの取得方法について詳しく説明できる場合は、より詳細な例を示します。
次のコードスニペットを使用できます
String dateString = "14 Jul 2014 00:11:04 CEST";
date = formatter.parse(dateString);
System.out.println(formatter.format(date));
// Set the formatter to use a different timezone - Indochina Time
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok"));
System.out.println("ICT time : "+formatter.format(date));
Jodaを使用したくない場合は、組み込みライブラリを使用した決定論的な方法があります。
まず、JVMを強制的にデフォルトのタイムゾーンにすることをお勧めします。これにより、異なるタイムゾーンに設定されているJVMをあるマシンから別のマシンに移動するときに発生する可能性のある問題に対処しますが、ソースデータは常に特定のタイムゾーンです。たとえば、データは常にPDT/PSTタイムゾーンですが、UTCタイムゾーンに設定されたボックスで実行するとします。
次のコードスニペットは、JVMのデフォルトのタイムゾーンを設定します。
//You can either pass the JVM a parameter that
//enforces a TZ: Java -Duser.timezone=UTC or you can do it
//programatically like this
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
TimeZone.setDefault(tz);
ここで、ソースの日付がPDT/PSTとして入ってくるが、UTCに変換する必要があるとしましょう。手順は次のとおりです。
DateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateStrInPDT = "2016-05-19 10:00:00";
Date dateInPDT = dateFormat.parse(dateStrInPDT);
String dateInUtc = dateFormatUtc.format(dateInPDT);
System.out.println("Date In UTC is " + dateInUtc);
出力は次のようになります。
Date In UTC is 2016-05-19 17:00:00
Java.time.ZoneDateTime#ofInstant()
メソッドを使用できます。
import Java.time.*;
public class TimeZonesConversion {
static ZonedDateTime convert(ZonedDateTime time, ZoneId newTimeZone) {
return ZonedDateTime.ofInstant(
time.toInstant(),
newTimeZone);
};
public static void main(String... args) {
ZonedDateTime mstTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("-07"));
ZonedDateTime localTime = convert(mstTime, Clock.systemDefaultZone().getZone());
System.out.println("MST(" + mstTime + ") = " + localTime);
}
}
このようなことをして、現在の時刻を別のタイムゾーンで取得できます。
Calendar japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan"));
japanCal.setTimeInMillis(local.getTimeInMillis());
これは答えではありませんが、同じタイムゾーンで日付を生成し、別のタイムゾーンのオフセットを適用しようとする人を助けることができます。アプリケーションサーバーが1つのタイムゾーンで実行され、データベースが別のタイムゾーンで実行されている場合に役立ちます。
public static Date toGreekTimezone (Date date) {
ZoneId greek = ZoneId.of(EUROPE_ATHENS);
ZonedDateTime greekDate = ZonedDateTime.ofInstant(date.toInstant(), greek);
ZoneId def = ZoneId.systemDefault();
ZonedDateTime defDate = greekDate.withZoneSameLocal(def);
return Date.from(defDate.toInstant());
}
「変換」の意味に依存します。
FORMATTERでタイムゾーンを設定するのと同じくらい簡単な場合があり、Calendarをまったく使用しません。
Calendar cal = Calendar.getInstance();
TimeZone tzUTC = TimeZone.getTimeZone( "UTC" );
TimeZone tzPST = TimeZone.getTimeZone( "PST8PDT" );
DateFormat dtfmt = new SimpleDateFormat( "EEE, yyyy-MM-dd KK:mm a z" );
dtfmt.setTimeZone( tzUTC );
System.out.println( "UTC: " + dtfmt.format( cal.getTime() ));
dtfmt.setTimeZone( tzPST );
System.out.println( "PST: " + dtfmt.format( cal.getTime() ));