47

実行時に Java Calendar インスタンスの TIMEZONE 値を変更したいと考えています。以下試してみました。ただし、出力は両方のインスタンスで同じです。

    Calendar cSchedStartCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    System.out.println(cSchedStartCal.getTime().getTime());
    cSchedStartCal.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
    System.out.println(cSchedStartCal.getTime().getTime());

出力:
1353402486773
1353402486773

これも試しましたが、出力は同じです:

    Calendar cSchedStartCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    System.out.println(cSchedStartCal.getTime());

    Calendar cSchedStartCal1 = Calendar.getInstance(TimeZone.getTimeZone("Asia/Calcutta"));
    cSchedStartCal1.setTime(cSchedStartCal.getTime());
    System.out.println(cSchedStartCal.getTime());

API で以下のコメントが表示されますが、その多くを理解できません。

     * calls: cal.setTimeZone(EST); cal.set(HOUR, 1); cal.setTimeZone(PST).
     * Is cal set to 1 o'clock EST or 1 o'clock PST?  Answer: PST.  More
     * generally, a call to setTimeZone() affects calls to set() BEFORE AND
     * AFTER it up to the next call to complete().

手伝っていただけませんか?

考えられる解決策の 1 つ:

    Calendar cSchedStartCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    long gmtTime = cSchedStartCal.getTime().getTime();

    long timezoneAlteredTime = gmtTime + TimeZone.getTimeZone("Asia/Calcutta").getRawOffset();
    Calendar cSchedStartCal1 = Calendar.getInstance(TimeZone.getTimeZone("Asia/Calcutta"));
    cSchedStartCal1.setTimeInMillis(timezoneAlteredTime);

この解決策は大丈夫ですか?

4

2 に答える 2

59

Java では、日付はエポック以降の UTC ミリ秒で内部的に表されます (したがって、タイムゾーンは考慮されませんgetTime()。そのため、前述のミリ秒と同じ結果が得られます)。
あなたのソリューションでは:

Calendar cSchedStartCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
long gmtTime = cSchedStartCal.getTime().getTime();

long timezoneAlteredTime = gmtTime + TimeZone.getTimeZone("Asia/Calcutta").getRawOffset();
Calendar cSchedStartCal1 = Calendar.getInstance(TimeZone.getTimeZone("Asia/Calcutta"));
cSchedStartCal1.setTimeInMillis(timezoneAlteredTime);

GMT から指定されたタイムゾーン (この例では "Asia/Calcutta") へのオフセットをミリ秒単位で追加するだけなので、これは正常に機能するはずです。

別の可能な解決策は、Calendarクラスの静的フィールドを利用することです。

//instantiates a calendar using the current time in the specified timezone
Calendar cSchedStartCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
//change the timezone
cSchedStartCal.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
//get the current hour of the day in the new timezone
cSchedStartCal.get(Calendar.HOUR_OF_DAY);

詳細な説明については、 stackoverflow.com /questions/7695859/ を参照してください。

于 2012-11-20T11:25:54.613 に答える
16
  1. このクラスDate/Timestampは、1970 年 1 月 1 日 00:00:00 GMT からの特定の瞬間をミリ秒の精度で表します。したがって、この時間差 (エポックから現在の時間まで) は、タイムゾーンに関係なく、世界中のすべてのコンピューターで同じになります。

  2. Date/Timestamp指定された時間がどのタイムゾーンにあるかはわかりません。

  3. タイムゾーンに基づいた時間が必要な場合は、Java の Calendar クラスまたは SimpleDateFormat クラスを使用する必要があります。

  4. を使用して Date/Timestamp オブジェクトを印刷しようtoString()とすると、時間が変換され、マシンのデフォルトのタイムゾーンで印刷されます。

  5. したがって、 (Date/Timestamp).getTime() オブジェクトは常に UTC (ミリ秒単位の時間) を持つと言えます。

  6. 結論 Date.getTime()として UTC 時刻が表示されますが、これtoString()は UTC ではなくロケール固有のタイムゾーンです。

指定したタイムゾーンで時間を作成/変更するにはどうすればよいですか?

以下のコードは、指定されたタイムゾーンで日付 (ミリ秒単位の時間) を提供します。ここでの唯一の問題は、日付を文字列形式で指定する必要があることです。

   DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
   dateFormatLocal.setTimeZone(timeZone);
   java.util.Date parsedDate = dateFormatLocal.parse(date);

dateFormat.format入力日付 (常に UTC)、タイムゾーン、および戻り日付を文字列として取得するために使用します。

UTC/GMT 時刻を DB に保存する方法:

オブジェクトを印刷するparsedDateと、時刻はデフォルトのタイムゾーンになります。ただし、以下のように UTC 時刻を DB に格納できます。

        Calendar calGMT = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        Timestamp tsSchedStartTime = new Timestamp (parsedDate.getTime());
        if (tsSchedStartTime != null) {
            stmt.setTimestamp(11, tsSchedStartTime, calGMT );
        } else {
            stmt.setNull(11, java.sql.Types.DATE);
        }
于 2012-12-22T11:20:40.830 に答える