60

コード:

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
    sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
    System.out.println(new Date());
    try {
        String d = sdf.format(new Date());
        System.out.println(d);
        System.out.println(sdf.parse(d));
    } catch (Exception e) {
        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
    }

出力:

Thu Aug 08 17:26:32 GMT+08:00 2013
2013.08.08 09:26:32 GMT
Thu Aug 08 17:26:32 GMT+08:00 2013

を GMT に正しくformat()フォーマットしますが、GMT の詳細が失われていることに注意してください。これを使用して回避できることはわかっていますが、この現象の根底にある理由は何ですか?Dateparse()substring()

これは、回答のない重複した質問です。

編集: 別の言い方をすれば、Date オブジェクトを取得して常に GMT にする方法は何ですか?

4

3 に答える 3

62

私が必要としたのはこれだけでした:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));

SimpleDateFormat sdfLocal = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");

try {
    String d = sdf.format(new Date());
    System.out.println(d);
    System.out.println(sdfLocal.parse(d));
} catch (Exception e) {
    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
}

出力 : 少し疑わしいですが、日付だけを一致させたい

2013.08.08 11:01:08
Thu Aug 08 11:01:08 GMT+08:00 2013
于 2013-08-08T11:04:07.497 に答える
8

彼が言うように、彼の問題に対するOPの解決策には、疑わしい出力があります。そのコードは、時間の表現についてまだ混乱を示しています。この混乱を解消し、間違った時間につながらないコードを作成するために、彼が行ったことの次の拡張を検討してください。

public static void _testDateFormatting() {
    SimpleDateFormat sdfGMT1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
    sdfGMT1.setTimeZone(TimeZone.getTimeZone("GMT"));
    SimpleDateFormat sdfGMT2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
    sdfGMT2.setTimeZone(TimeZone.getTimeZone("GMT"));

    SimpleDateFormat sdfLocal1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
    SimpleDateFormat sdfLocal2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");

    try {
        Date d = new Date();
        String s1 = d.toString();
        String s2 = sdfLocal1.format(d);
        // Store s3 or s4 in database.
        String s3 = sdfGMT1.format(d);
        String s4 = sdfGMT2.format(d);
        // Retrieve s3 or s4 from database, using LOCAL sdf.
        String s5 = sdfLocal1.parse(s3).toString();
        //EXCEPTION String s6 = sdfLocal2.parse(s3).toString();
        String s7 = sdfLocal1.parse(s4).toString();
        String s8 = sdfLocal2.parse(s4).toString();
        // Retrieve s3 from database, using GMT sdf.
        // Note that this is the SAME sdf that created s3.
        Date d2 = sdfGMT1.parse(s3);
        String s9 = d2.toString();
        String s10 = sdfGMT1.format(d2);
        String s11 = sdfLocal2.format(d2);
    } catch (Exception e) {
        e.printStackTrace();
    }       
}

デバッガーで値を調べる:

s1  "Mon Sep 07 06:11:53 EDT 2015" (id=831698113128)    
s2  "2015.09.07 06:11:53" (id=831698114048) 
s3  "2015.09.07 10:11:53" (id=831698114968) 
s4  "2015.09.07 10:11:53 GMT+00:00" (id=831698116112)   
s5  "Mon Sep 07 10:11:53 EDT 2015" (id=831698116944)    
s6  -- omitted, gave parse exception    
s7  "Mon Sep 07 10:11:53 EDT 2015" (id=831698118680)    
s8  "Mon Sep 07 06:11:53 EDT 2015" (id=831698119584)    
s9  "Mon Sep 07 06:11:53 EDT 2015" (id=831698120392)    
s10 "2015.09.07 10:11:53" (id=831698121312) 
s11 "2015.09.07 06:11:53 EDT" (id=831698122256) 

sdf2 と sdfLocal2 にはタイム ゾーンが含まれているため、実際に何が起こっているかを確認できます。s1 と s2 はゾーン EDT の 06:11:53 です。s3 と s4 はゾーン GMT の 10:11:53 にあり、元の EDT 時間に相当します。一貫性のために GMT を使用しているデータベースに s3 または s4 を保存すると想像してください。異なるタイム ゾーンを保存することなく、世界中のどこからでも時間を取得できます。

s5 は GMT 時間を解析しますが、現地時間として扱います。つまり、「10:11:53」(GMT 時間) と表示されますが、現地時間で 10:11:53 と見なされます。良くない。

s7 は GMT 時刻を解析しますが、文字列内の GMT を無視するため、ローカル時刻として扱います。

s8 が機能するのは、文字列に GMT が含まれるようになり、ローカル ゾーン パーサーがそれを使用してあるタイム ゾーンから別のタイム ゾーンに変換するためです。

ここで、ゾーンを保存するのではなく、s3 を解析できるようにしたいが、それを現地時間として表示したいとします。答えは、保存されたのと同じタイム ゾーンを使用して解析することです。そのため、作成されたのと同じ sdf、sdfGMT1 を使用します。s9、s10、および s11 はすべて元の時間の表現です。それらはすべて「正しい」です。つまり、d2 == d1 です。次に、それをどのように表示したいかだけの問題です。DB に格納されているもの (GMT 時間) を表示する場合は、GMT sdf を使用してフォーマットする必要があります。s10です。

したがって、文字列に " GMT" を明示的に格納したくない場合、および GMT 形式で表示する場合の最終的な解決策は次のとおりです。

public static void _testDateFormatting() {
    SimpleDateFormat sdfGMT1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
    sdfGMT1.setTimeZone(TimeZone.getTimeZone("GMT"));

    try {
        Date d = new Date();
        String s3 = sdfGMT1.format(d);
        // Store s3 in DB.
        // ...
        // Retrieve s3 from database, using GMT sdf.
        Date d2 = sdfGMT1.parse(s3);
        String s10 = sdfGMT1.format(d2);
    } catch (Exception e) {
        e.printStackTrace();
    }       
}
于 2015-09-07T10:44:59.057 に答える