0

私の Android アプリでは、さまざまなタイム ゾーンでカレンダーを使用しています。このようにして、アプリの操作をローカルの条件に合わせて調整できます。

runDate = Calendar.getInstance(); // will display tides for this date/time
useThisTZ = TimeZone.getTimeZone("US/Pacific");
runDate.setTimeZone(useThisTZ);

航海や軍事のタイムゾーンに適応する必要があります。これらは、市民的ではなく地理的です。これを行うには、getTimeZone 関数に渡すことができる識別子を決定する必要があります。Alpha タイム ゾーン (UTC + 1) を識別するタイム ゾーン コード「A」を試しました。ただし、これにより、通常はズールーと呼ばれる GMT ゾーンにカレンダーが配置されました。

これらの識別子が利用可能かどうか、およびそれらが何であるかを知っている人はいますか?

4

3 に答える 3

1

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後者の場合、サブパッケージを使用して日付と時刻のクラスをインポートしてください。

リンク

于 2020-09-23T19:06:58.287 に答える