1

ロジックの一部として、私のプログラムでは、長い Java タイムスタンプ (年、月などを含む) を「短い」Java 時間に変換する必要があります。これは、元の時間とまったく同じ時間、分、秒に対応する必要がありますが、1970 年 1 月 1 日から 1 日以内です (つまり、0 (00:00:00) から 86400000 (23:59:59) までの値)。例は、質問の変換です。

これを実行するには、以下のコードが機能すると考えました。

public int convertToTime(long fullTimeStamp) {
    Calendar c = Calendar.getInstance();
    c.setTimeInMillis(date);
    c.set(Calendar.DATE, 1);
    c.set(Calendar.MONTH, 0);
    c.set(Calendar.YEAR, 1970);
    return (int) c.getTimeInMillis();
}

私が抱えている問題は、タイムゾーンに関係しています。英国では、現在 BST にいます。関数ですべての値を設定した後、時間は同じ数字 (たとえば午前 8 時) のままですが、タイムゾーンが GMT に変更されます! もちろん、GMT の午前 8 時は、BST の午前 8 時と同じではなく、BST の午前 9 時と同じです。

関数にコンソール出力を追加すると、この問題が示されます。

public int convertToTime(long fullTimeStamp) {
    System.out.println(new Date(fullTimeStamp)); // correct

    Calendar c = Calendar.getInstance();
    c.setTimeInMillis(fullTimeStamp);

    System.out.println(c.getTime()); // correct

    c.set(Calendar.DATE, 1);
    c.set(Calendar.MONTH, 0);
    c.set(Calendar.YEAR, 1970);

    System.out.println(c.getTime()); // incorrect!

    return (int) c.getTimeInMillis();
}

プログラム出力:

Wed Jun 19 12:15:00 BST 2013 // ok
Wed Jun 19 12:15:00 BST 2013 // this makes sense
Thu Jan 01 12:15:00 GMT 1970 // Calendar, stahp!

望ましい動作は、最後の部分を読み取ることです。

Thu Jan 01 11:15:00 GMT 1970
or
Thu Jan 01 12:15:00 BST 1970

これはカレンダーの予想される動作ですか? 私の理解では、変更されていないすべての「数字」が同じままであるため、HOUR_OF_DAY の値が 8 の場合、タイムゾーンが変更されても 8 のままにする必要があります。

カレンダーのタイムゾーンを (値が設定される前に) BST と GMT に設定しようとしましたが、まったく同じ動作が発生します。また、うるう年を処理する必要があるため、1970 年以降のすべての年を削除するためにミリ秒を手動で追加または削除することもできません。

「Joda 時間 (または他の時間パッケージ) を使用する」以外に、この操作を実行するための他の提案はありますか? 可能であれば、他のパッケージを試す前に、簡単に修正する必要があります。

ありがとう!

4

2 に答える 2

5

あなたは、英国のタイム ゾーンに関するあまり知られていない事実に反していると思います。Unix 時代には、実際には UTC+1 でした。Java は正しい時刻(英国のタイム ゾーン内) を取得していますが、名前が間違っています。GMT ではなく BST を指定する必要があります。これは英国の夏時間のような BST ではありませ。英国標準時の BSTです。はい、それは怒っています。

関連するウィキペディアの記事から:

1959 年から 1960 年の冬の間、180 の国内組織に相談した調査では、通年 GMT+1 への変更をわずかに好むことが明らかになりましたが、サマータイムの長さは、国内での使用ではなく試験として延長されました。グリニッジ標準時廃止[8] 1966 年から 1967 年にかけてのさらなる調査により、ハロルド ウィルソンの政府は英国標準時の実験を導入し、英国は年間を通じて GMT+1 のままでした。これは 1968 年 10 月 27 日から 1971 年 10 月 31 日の間に行われ、以前の取り決めに戻されました。

元の問題ステートメントがややあいまいであることを心に留めておく価値がありますlong。Unix エポックからのミリ秒にすぎない a を取り込んでいますが、それを時間で解釈しようとしています。どのタイムゾーンでそれを解釈する必要があるかという疑問が生じます。その決定を下しましたか? その場合は、非常に慎重に文書化し、コードがそれに準拠していることを確認する必要があります。

最終的に、私の推奨事項は次のとおりです。

  • Joda Time を使用できる場合は、使用してください。それは何時間もの心痛を救うでしょう。
  • このようなカレンダー計算をしようとしている場合は、他のことを行う前に、カレンダーのタイム ゾーンを UTC に変更することを検討してください。それはあなたの心痛を救うでしょう
  • Date.toString()可能な場合は使用しないでくださいDateFormatter。タイムゾーンを UTC に設定して a を使用すると、期待どおりの結果が得られます。

user2340612 の回答が述べているように、「UTC 日のミリ秒」だけを取得するには、単純な算術演算を使用できますが、指定された値では完全ではありません。私は使うだろう:

long timeOfDay = millisecondsSinceUnixEpoch % TimeUnit.DAYS.toMillis(1);

...しかし、これは、特定の瞬間のUTC時刻に関心がある場合にのみ機能します。(負の入力に対しても負の結果が得られますが、気にする必要はありません。)

于 2013-06-19T09:12:10.360 に答える
0

0 ~ 86399999 (23:59:59.999) のタイムスタンプが必要な場合は、現在のタイムスタンプを取得し、それと 86400000 の間の除算の余りを計算できます。

desired_time = cur_time % 86400000

ただし、サマータイムがあれば見逃してしまいます。

于 2013-06-19T09:14:37.770 に答える