web-dev-qa-db-ja.com

JavaでTimeZoneを使用して夏時間に取り組む方法

JavaアプリケーションでEST時間を出力する必要があります。タイムゾーンをESTに設定するには、次を使用しました。

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));

しかし、このタイムゾーンでサマータイムが行われているとき、私のコードは正しい時間を印刷しません(1時間少なく印刷されます)。

サマータイムが守られているかどうかに関係なく、常に正しい時刻を読み取るようにコードを機能させる方法は?

PS:タイムゾーンをEDTに設定しようとしましたが、問題は解決しません。

56
Surya Chandra

これが最初の問題です。

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));

TZDBゾーンIDを優先して、3文字の略語は心から避けるべきです。 ESTは東部標準時間-および標準時間はDSTを遵守しません。実際には完全なタイムゾーン名ではありません。タイムゾーンのpartに使用される名前です。 (残念ながら、この「ハーフタイムゾーン」の概念に適した用語は見つかりませんでした。)

fullタイムゾーン名が必要です。例えば、 America/New_Yorkは東部時間帯にあります。

TimeZone zone = TimeZone.getTimeZone("America/New_York");
DateFormat format = DateFormat.getDateTimeInstance();
format.setTimeZone(zone);

System.out.println(format.format(new Date()));
106
Jon Skeet

他の答えは、特に Jon Skeetによるもの ですが、時代遅れです。

Java.time

これらの古い日時クラスは、Java 8以降に組み込まれている Java.time フレームワークによって置き換えられました。

単にUTCの現在の時刻が必要な場合は、Instantクラスを使用します。

Instant now = Instant.now();

Jon Skeetによる正解 で説明されているように、ESTはタイムゾーンではありません。このような3〜4文字のコードは、標準化も一意化もされておらず、さらに夏時間(DST)をめぐる混乱を招いています。 「大陸/地域」形式の適切なタイムゾーン名を使用します。

おそらく、あなたは北アメリカの東海岸の東部標準時を意味していたのでしょうか?またはエジプト標準時?または欧州標準時?

ZoneId zoneId = ZoneId.of( "America/New_York" );
ZoneId zoneId = ZoneId.of( "Africa/Cairo" );
ZoneId zoneId = ZoneId.of( "Europe/Lisbon" );

そのようなZoneIdオブジェクトを使用して、特定のタイムゾーンに調整された現在の瞬間を取得し、 ZonedDateTime オブジェクトを生成します。

ZonedDateTime zdt = ZonedDateTime.now( zoneId ) ;

最初のZonedDateTimeオブジェクトを作成して、そのZonedDateTimeを別のタイムゾーンに調整します。 Java.timeフレームワークは、既存のオブジェクトを変更(変更)するのではなく、 不変オブジェクト を使用します。

ZonedDateTime zdtGuam = zdt.withZoneSameInstant( ZoneId.of( "Pacific/Guam" ) ) ;
16
Basil Bourque

タイムゾーンに「EST」と入力する代わりに、「EST5EDT」と入力できます。ご指摘のとおり、「EDT」だけでは機能しません。これは夏時間の問題を説明します。コード行は次のようになります。

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST5EDT"));
2
Brian N
private static Long DateTimeNowTicks(){
    long TICKS_AT_Epoch = 621355968000000000L;
    TimeZone timeZone = Calendar.getInstance().getTimeZone();
    int offs = timeZone.getRawOffset();
    if (timeZone.inDaylightTime(new Date()))
        offs += 60 * 60 * 1000;
    return (System.currentTimeMillis() + offs) * 10000 + TICKS_AT_Epoch;
}
0
fartwhif

このように answer

TimeZone tz = TimeZone.getTimeZone("EST");
boolean inDs = tz.inDaylightTime(new Date());
0
Daniil Shevelev
public static float calculateTimeZone(String deviceTimeZone) {
    float ONE_HOUR_MILLIS = 60 * 60 * 1000;

    // Current timezone and date
    TimeZone timeZone = TimeZone.getTimeZone(deviceTimeZone);
    Date nowDate = new Date();
    float offsetFromUtc = timeZone.getOffset(nowDate.getTime()) / ONE_HOUR_MILLIS;

    // Daylight Saving time
    if (timeZone.useDaylightTime()) {
        // DST is used
        // I'm saving this is preferences for later use

        // save the offset value to use it later
        float dstOffset = timeZone.getDSTSavings() / ONE_HOUR_MILLIS;
        // DstOffsetValue = dstOffset
        // I'm saving this is preferences for later use
        // save that now we are in DST mode
        if (timeZone.inDaylightTime(nowDate)) {
            Log.e(Utility.class.getName(), "in Daylight Time");
            return -(ONE_HOUR_MILLIS * dstOffset);
        } else {
            Log.e(Utility.class.getName(), "not in Daylight Time");
            return 0;
        }
    } else
        return 0;
}
0
Jayesh Kalkani