java.time からの ZoneOffset および OffsetDateTime
日付と時刻の作業には、最新の Java 日付と時刻 API である java.time の使用を検討してください。航海 (または軍事) タイム ゾーンは、UTC からの 1 時間単位のオフセットにすぎないため、夏時間 (DST) やその他の異常を考慮した特別なタイム ゾーン ルールは必要ありません。プレーンZoneOffset
で十分です。
タイムゾーン名は組み込まれていません。自分で変換をコーディングする必要があります。これを行う 1 つの方法は、タイム ゾーン名を検索してオフセットを取得できる配列を使用することです。
private static final int[] offsetPerNauticalTimeZone = new int['Z' + 1];
private static final int invalid = -100;
static {
Arrays.fill(offsetPerNauticalTimeZone, invalid);
// The letter "Z" ("Zulu") indicates Coordinated Universal Time (UTC).
offsetPerNauticalTimeZone['Z'] = 0;
// A through M denote positive offsets, but J is skipped
for (int offset = 1; offset <= 9; offset++) {
offsetPerNauticalTimeZone['A' - 1 + offset] = offset;
}
for (int offset = 10; offset <= 12; offset++) {
offsetPerNauticalTimeZone['K' - 10 + offset] = offset;
}
// N through Y are the negative offsets
for (int negatatedOffset = 1; negatatedOffset <= 12; negatatedOffset++) {
offsetPerNauticalTimeZone['N' - 1 + negatatedOffset] = -negatatedOffset;
}
}
使用例:
char nauticalTimeZone = 'A'; // Set desired letter here
int offsetHours = offsetPerNauticalTimeZone[nauticalTimeZone];
if (offsetHours == invalid) {
System.out.println("Invalid nautical time zone " + nauticalTimeZone);
} else {
ZoneOffset offset = ZoneOffset.ofHours(offsetHours);
OffsetDateTime runDateTime = OffsetDateTime.now(offset);
System.out.println(runDateTime);
}
このスニペットを実行したところ、次のような出力が得られました。
2020-09-23T20:05:52.451+01:00
オフセットは航海時間帯 A に対応する +01:00 であることがわかります。他の時間帯も試してください。
ArrayIndexOutOfBounsException
コードがそのままの状態では、文字が大文字を超えている場合にスローされZ
ます。必要なチェックを組み込むのはあなたに任せます。
編集:
私が使用しているカレンダー コードはタイム ゾーン名を受け入れます。それらが何であるかの完全なリストが必要です。
それが私だったら、この機会に時代遅れのCalendar
クラスから java.time に切り替えるでしょう。また、私が指摘しようとしたように、旧式のTimeZone
クラスを使用すると、オフセットだけが必要な場合に、一般的なタイム ゾーンに必要なすべてのものを持ち運ぶことになるからです。Calendar
を使用してフィードすることを主張する場合TimeZone
、変換は十分に簡単です。ThreeTenABP を使用していると仮定します (以下を参照)。
TimeZone oldfashionedTimeZone = DateTimeUtils.toTimeZone(offset);
System.out.println(oldfashionedTimeZone.getID());
+01:00
これは、あなたが求めていたタイム ゾーン ID です。他のものも同様で、自分で構築できます。疑わしい場合は、そこから get them で私のコードを実行してください。にフィードするCalendar
場合、ID は必要ありません。もちろん、既にTimeZone
オブジェクトを取得しています。
レガシー コードに古風なコードが必要な場合でも、少し良くなりました (またはそれほど悪くはありません) 。混乱を招き、設計が不十分なクラスCalendar
に対処する必要はありません。次のコードからTimeZone
取得できます。Calendar
Calendar runDate = DateTimeUtils.toGregorianCalendar(
runDateTime.atZoneSameInstant(offset));
Java 8 を使用している場合 (脱糖によって Java 8 を使用している場合もあると思います)、変換はさらに少し短くなりTimeZone.getTimeZone(offset)
ますGregorianCalendar.from(runDateTime.atZoneSameInstant(offset))
。
質問: java.time は Android API レベル 26 を必要としませんか?
java.time は、古い Android デバイスでも新しい Android デバイスでもうまく機能します。少なくともJava 6が必要です。
- Java 8 以降および新しい Android デバイス (API レベル 26 以降) では、最新の API が組み込まれています。
- Android 以外の Java 6 および 7 では、最新のクラスのバックポートである ThreeTen Backport を取得します (JSR 310 用の ThreeTen。下部のリンクを参照してください)。
- 古い Android では、脱糖または ThreeTen Backport の Android 版を使用します。それは ThreeTenABP と呼ばれます。
org.threeten.bp
後者の場合、サブパッケージを使用して日付と時刻のクラスをインポートしてください。
リンク