Java 8でZoneIdをZoneOffsetに変換する方法はありますか?


89

method1によってエポック秒とzoneIdがあります。システムのデフォルトのzoneIdを使用してLocalDateTimeに変換できますが、メソッド2によってエポック秒をLocalDateTimeに変換する方法が見つかりませんZoneOffset.systemDefault。これは、あいまいだと思います。

import java.time.{Instant, LocalDateTime, ZoneId, ZoneOffset}

val epochSecond = System.currentTimeMillis() / 1000

LocalDateTime.ofInstant(Instant.ofEpochSecond(epochSecond), ZoneId.systemDefault())//method1
LocalDateTime.ofEpochSecond(epochSecond, 0, ZoneOffset.MAX)//method2

一括インポートをimport java.time.{Instant, LocalDateTime, ZoneId, ZoneOffset}機能させるために使用している言語/方言は何ですか?これはunexpected token
Java11の

1
Scalaになることもできますが、ここでは
それほど

1
私は後ろに理論を議論してきたjava.timeここで詳細:stackoverflow.com/a/56508200/145989
Ondraジシュカ

回答:


113

これがあなたがZoneOffsetから得ることができる方法ですZoneId

Instant instant = Instant.now(); //can be LocalDateTime
ZoneId systemZone = ZoneId.systemDefault(); // my timezone
ZoneOffset currentOffsetForMyZone = systemZone.getRules().getOffset(instant);

注意:ZoneId特定の場所の時点と履歴に応じて、オフセットを変えることができます。したがって、異なるインスタントを選択すると、オフセットが異なります。

注意:。のようなタイムゾーンではなく、/ / etcが渡された場合の代わりにをZoneId.of()返すことができます。したがって、UTC / GMTオフセットが渡された場合、の履歴/地理/夏時間情報は考慮されません。指定されたオフセットで作業するだけです。ZoneOffsetZoneIdUTC+3GMT+2Africa/CairoInstant


現在のインスタントDSTである場合、これは間違った値が得られますが、計算の瞬間に、それはDSTなしだった
msangel

@msangel、それを再確認できますか?たぶんあなたはZoneId.systemDefault()あなたのコードで使用していて、それは異なるマシンで異なるタイムゾーンを返しますか?
StanislavBashkyrtsev20年

確認したところ、別の条件で動作します。それで答えを更新しました。
msangel

43

1対1のマッピングはありません。ZoneIdは、さまざまなZoneOffsetのセットが時間の経過とともに使用される地理的範囲を定義します。タイムゾーンが夏時間を使用する場合、そのZoneOffsetは夏と冬で異なります。

さらに、夏時間のルールは時間の経過とともに変更される可能性があるため、ZoneOffsetは、たとえば2015年10月13日と1980年10月13日では異なる可能性があります。

したがって、特定のインスタントでのみZoneIdのZoneOffsetを見つけることができます。

https://en.wikipedia.org/wiki/Tz_databaseも参照してください


10
私はそれを知っていますが、それはどのように行われますか?LocaDateを知っていてZoneIdを持っている場合、それをZoneOffsetに変換するにはどうすればよいですか?私のユースケースは、時間とゾーンを含む文字列です。ゾーン情報を削除せずに、文字列をOffsetTimeに解析したいと思います。
Kai Moritz 2015

35

tl; dr

ZonedDateTime.now( 
    ZoneId.of( "America/Montreal" ) 
)

…現在のデフォルトのタイムゾーンの…

ZonedDateTime.now( 
    ZoneId.systemDefault() 
)

詳細

スタニスラフBshkyrtsevによって回答が正しくて、直接あなたの質問に答えます。

しかし、Jon Skeetによる回答で示唆されているように、より大きな問題が関係しています。

LocalDateTime

エポック秒をLocalDateTimeに変換する方法が見つかりません

LocalDateTime意図的にタイムゾーンやUTCからのオフセットの概念はありません。おそらくあなたが望むものではありません。とLocal…特定の地域ではなく、任意の地域を意味します。このクラスは瞬間を表すのではなく、約26〜27時間の範囲(世界中のタイムゾーンの範囲)に沿った潜在的な瞬間のみを表します。

Instant

現在の時刻を取得しようとしている場合は、エポック秒から始める必要はありません。現在を取得しInstantます。このInstantクラスは、UTCのタイムライン上の瞬間をナノ秒の解像度(小数の最大9桁)で表します。

Instant instant = Instant.now();

その中にInstantは、エポックからのナノ秒のカウントがあります。しかし、私たちは本当に気にしません。

ZonedDateTime

特定の地域の実時間のレンズを通してその瞬間を見たい場合は、を適用してZoneIdを取得しZonedDateTimeます。

ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdt = instant.atZone( z );

ショートカットとして、に直接行うことができますZonedDateTime

ZonedDateTime zdt = ZonedDateTime.now( z );  

AZonedDateTimeはそのInstant中にあります。UTCのzdt.toInstant()基本値と同じ時刻を取得するために呼び出します。と同じナノ秒数-エポック以降、またはとして。ZonedDateTimeInstant

秒-エポックが与えられてから

エポック以降の秒数が与えられ、エポックがUTC1970-01-01T00:00:00Z)での1970年の最初の瞬間である場合は、その数値をにフィードしInstantます。

long secondsSinceEpoch = 1_484_063_246L ;
Instant instant = Instant.ofEpochSecond( secondsSinceEpoch ) ;

最新とレガシーの両方のJavaの日時タイプの表。


java.timeについて

java.timeフレームワークは、Java8以降に組み込まれています。これらのクラスは面倒古い取って代わるレガシーのような日付時刻クラスをjava.util.DateCalendar、& SimpleDateFormat

詳細については、Oracleチュートリアルを参照してください。そして、StackOverflowで多くの例と説明を検索してください。仕様はJSR310です。

ジョダタイムプロジェクトは、今でメンテナンスモードへの移行をアドバイスjava.timeのクラス。

java.timeオブジェクトをデータベースと直接交換できます。JDBC4.2以降に準拠したJDBCドライバーを使用してください。文字列もクラスも必要ありません。java.sql.*

java.timeクラスはどこで入手できますか?

ThreeTen-エクストラプロジェクトでは、追加のクラスでjava.timeを拡張します。このプロジェクトは、java.timeへの将来の追加の可能性の証明の場です。あなたはここにいくつかの有用なクラスのような見つけることがIntervalYearWeekYearQuarter、および多くを


10

ドキュメントは、言う「これは主に、低レベルの変換ではなく、一般的なアプリケーションの使用を目的としています。」

経由Instantすることは私には完全に理にかなっています-あなたのエポック秒は事実上、の異なる表現なInstantので、に変換してInstantからそれを特定のタイムゾーンに変換します。


9

以下の私のソリューションの最初の2行がお役に立てば幸いです。私の問題はLocalDateTime、とタイムゾーンの名前があったことでした。MongoDBが望んでいたので、をinstant作成できるようにする必要がありましたjava.util.Date。私のコードはScalaですが、ここではJavaに非常に近いので、問題なく理解できると思います。

val zid = ZoneId.of(tzName)                                // "America/Los_Angeles"
val zo: ZoneOffset = zid.getRules.getOffset(localDateTime) // ⇒ -07:00
                                         // 2017-03-16T18:03

val odt = OffsetDateTime.of(localDateTime, zo) // ⇒ 2017-03-16T18:03:00-07:00
val instant = odt.toInstant                    // ⇒ 2017-03-17T01:03:00Z
val issued = Date.from(instant)

1
私が最終的に理解したことを行う方法を探していたときに出てきたページだったので、この回答をここに投稿しました。
gknauth 2017年

2

以下は、このタイムゾーンの標準時間を取得するためにUTCに追加する時間をミリ秒単位で返します。

TimeZone.getTimeZone(ZoneId.of("Europe/Amsterdam")).getRawOffset()

0

エポック秒とzoneIdがあります。Java 8でZoneIdをZoneOffsetに変換する方法はありますか?

  1. ZonedDateTimeエポックセカンドとゾーンIDから取得
  2. ZoneOffsetから取得ZonedDateTime

デモ:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        // Get ZonedDateTime from epoch second and Zone Id
        ZonedDateTime zdt = Instant.ofEpochSecond(1597615462L).atZone(ZoneId.of("Europe/London"));

        // Get ZoneOffset from ZonedDateTime
        ZoneOffset offset = zdt.getOffset();

        System.out.println(offset);
    }
}

出力:

+01:00
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.