2017-11-27 22 views
0

私はタイマーを使用して特定の期間内に特定のタスクを実行しています。このメソッドは、その日付からタスクを開始し、すべての期間に繰り返す場合は、Date型が必要です。特定のタイムゾーンで日付を設定するには?

私は何時間も解決策を見出そうとしていましたが、何も思い付きませんでした。私はカレンダーを作成し、タイムゾーンを設定します。そして、そのカレンダーから日付を取得すると、この日付に私のローカル時刻が含まれます。 SimpleDataFormatを使用してDateからstringを取得しようとしましたが、SimpleDataFormatのタイムゾーンを個別に設定していたために機能しました。その後、その文字列を日付に解析しようとしても、それはまだ動作しませんでした。私はちょっとこの時点で絶望的です。カレンダーのタイムゾーンを設定できない場合はどうすればいいですか?私は現地時間を得ていない場合でも、何かをすることができましたが、代わりにUTCを取得していました。しかしそれはどちらの場合もそうではありません。私は、このアプリケーションをコンピュータの現地時間に基づいて実行させたくありません。それは地元の時間を得て、それを私が望む時間帯に変えることができるはずです。

コード:

TimeZone eu = TimeZone.getTimeZone("GMT+1"); 
    TimeZone america = TimeZone.getTimeZone("EST"); 
    TimeZone asia = TimeZone.getTimeZone("GMT+7"); 
    SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); 
    df.setTimeZone(eu); 
    Calendar euCal = Calendar.getInstance(eu); 
    Date dateEu = euCal.getTime(); 
    System.out.println(dateEu); //Prints local time date 
    euCal.setTimeZone(eu); 
    System.out.println(dateEu); //Still prints local time date 
    String formattedDateEu = df.format(dateEu); 
    System.out.println(formattedDateEu); //This one works fine but it is string 

    try { 
     dateEu = df.parse(formattedDateEu); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    System.out.println(dateEu); //Fun part. Although I don't get exception dateEu is still not in the time zone I want. 

サンプル出力:

Mon Nov 27 14:37:21 MSK 2017 
Mon Nov 27 14:37:21 MSK 2017 
27/11/2017 12:37:21 
Mon Nov 27 14:37:21 MSK 2017 
+0

古い「カレンダー」ではなく、 'Date'を初期化するための最新の' ZonedDateTime'をお勧めします(そして 'java.util.Timer'には' Date'が必要です)。 'ZonedDateTime'を表示すると、タイムゾーンが正しいことがわかります。 'Date'に変換するには' Date.from(yourZonedDateTime.toInstant()) 'を使います。 –

+1

'Date'クラスには多くの設計上の欠陥があります。その1つはJVMの現在のデフォルトタイムゾーンを適用してその値を表すStringを生成する' toString'メソッドです。このクラスは 'Calendar'と一緒になりましたので、避けて、java.timeクラスに置き換えてください。レガシークラスとモダンクラスを変換するには、古いクラスに追加された新しいメソッド、特に 'Date.from(instant)'を調べてください。 –

答えて

2

java.util.Dateオブジェクトはタイムゾーン情報が含まれていません。彼らは、今のところパリやニューヨークにいるかどうかに関わらず、誰にとっても同じ瞬間である時間的連続性の瞬間を表します。

しかし、System.out.println()でDateオブジェクトを印刷しようとすると、それ自体を試して記述する必要があります。したがって、それが表す日時を記述する必要がありますが、その日時を表すタイムゾーンを最初に選択する必要があります。便宜上、ユーザーのシステムタイムゾーンを選択します。

あなたはSystem.out.println()を呼び出してDateを使用することはないので、System.out.println()が何をしているのか気にする必要はありません。

+0

いいえ私はsystem.out.println()でそれを使用しません。代わりにタイマーで使用します。そして、この日付をタイマーに送ると、タイマーは現地時間に応じて日付を取得します。それがここの問題です。例えば、私は22.00 UTC + 1で始まり、24時間ごとに繰り返すタイマーが必要です。 22:00 UTC + 7で始まり、24時間ごとに繰り返す別のタイマーが欲しい。 Dateが現地時間を取得している場合は、どうすればいいですか?私はUTC + 1とUTC + 7を取得したい。 – Vsky

+0

また、日付にはタイムゾーンがまったく表示されません。日付を使用するものはそうかもしれないし、そうでないかもしれない。日付を使用するためにタイムゾーンが必要かどうかによって異なります。あなたのタイマーはあなたの現地時間を使用すると言っていますが、典型的なタイマーは実行する必要がある瞬間を知りたいだけで、この瞬間を完全に記述しているため、タイムゾーンはまったく必要ありません。使用しているタイマーが非定型で、タイムゾーンを試して使用することをどのように知っていますか? – kumesana

+0

あなたは今私が見ている通りです。まあ、これは私が推測する睡眠の私のキューです。ご回答有難うございます。 – Vsky

1

私はあなたに、古い古くなったDateクラスから遠ざかるように教えてもらいたいと思います。今日は、java.time, the modern Java date and time APIの方がはるかに優れています。ただし、java.util.Timerには特定の日時にタスクをスケジューリングするためにDateが必要です。現代のAPIはそれほどで動作するように進歩しているので、まだ、私はあなたのDateを初期化するためにそれを使用することをお勧め:

ZoneOffset eu = ZoneOffset.ofHours(1); 
    ZoneOffset america = ZoneOffset.ofHours(-5); 
    ZoneOffset asia = ZoneOffset.ofHours(7); 

    OffsetDateTime euTime = OffsetDateTime.now(eu); 
    System.out.println(euTime); 
    Date dateEu = Date.from(euTime.toInstant()); 

    // schedule to start at the specified date-time and repeat weekly 
    myJavaUtilTimer.scheduleAtFixedRate(myTask, dateEu, TimeUnit.DAYS.toMillis(7)); 

私はあなたが本当にタイムゾーンを使用していない私には見える、ちょうどGMTからのオフセット(またはUTC)。だから、私はコードの中にZoneOffsetを入れました。 00予想通り:ちょうど今euTimeを印刷したものは、あなたがオフセットが01であることがわかります

2017-11-27T15:56:03.213+01:00 

ました。それで、kumesanaがすでにthe other answerで言ったように、結果としてDateを印刷しないで、OKだと信じてください。

あなたが本当のタイムゾーンを好む行う場合は、例えば使用:

ZoneId eu = ZoneId.of("Europe/Brussels"); 
    ZoneId america = ZoneId.of("America/Jamaica"); 
    ZoneId asia = ZoneId.of("Asia/Krasnoyarsk"); 

コードの残りの部分は同じです。つまり、OffsetDateTime.now()ZoneOffsetまたはZoneIdのいずれかを受け入れるため、両方のタイプを混在させることもできます。上記の時間帯のうち、ヨーロッパ/ブリュッセルでは夏時間(DST)を使用しているため、年間7ヶ月間に+02:00のオフセットが適用されます。

ESTのように3文字のタイムゾーンの略語は使用しないでください。彼らはしばしば曖昧です。自分のコードと同じように、地域/都市形式でタイムゾーンを指定することをお勧めします。

EDIT:ここでは私のコンピュータから実行する例を示します

2017-11-28T19:04:22.917+01:00 
myTask running @ 2017-11-28T19:04:23.156+01:00[Europe/Oslo] 

あなたが見ることができるように、myTaskは、スケジュールされたタスクのために指定されたfirstTime後に239ミリ秒を走りました。そのような待ち時間は予想されるべきです。 2回目の走行では、差は130ミリ秒にまで減少しました。

+0

あなたは、日付の印刷結果を無視するように教えてもいいですが、それは大丈夫ではありません。あなたはそのコードを実行しましたか?現時点ではEUでは開始されていません。とにかく、私はLocalTime、LocalDateTime、ZonedDateTimeの組み合わせで異なるアプローチをとった。私は今、エポック秒を取得し、それを初期遅延として使用します。私は今、タイマーの代わりにScheduledExecutorServiceを使用していますが、私はタイマーも(初期の遅延と期間)とスケジューラの種類があると思う。 – Vsky

+0

はい、コードを実行しました。私も 'Date'を印刷しましたが、私のタイムゾーンは冬にはUTC + 1ですので、驚いたことに現在の時刻と同じオフセットを(+01:00)入れました(これはそうではありません他のタイムゾーンのJVM上)。 'SchedulesExecutorService'は良い選択肢ですが、あなたは' Timer 'に似ているが、より現代的で、より多くの可能性を持っていることは間違いありません。 –

関連する問題