web-dev-qa-db-ja.com

カスタムタイムゾーンの場合、Java(GMT + 00:00)にタイムゾーンオフセットがないSimpleDateFormat

SimpleDateFormatクラスを使用してJavaで日時をフォーマットし、日付の後に+0000を付けずに日付のタイムゾーン部分を指定することは可能ですか?.

編集

Java内のデフォルトのタイムゾーンを次のように変更します:

SimpleTimeZone tz = new SimpleTimeZone(0, "Out Timezone");        
TimeZone.setDefault(tz);

残念ながら、私はこのコードを削除する立場にありません。システム全体が機能しなくなると推測するのは危険です。最初の作者は、いつか夏時間の問題を回避するためにこれを入れたと思います。

これを念頭に置いて、日付を次のようにフォーマットします。

2011-12-27 09:00 GMT

または

2011-12-27 09:00 BST

SimpleDateFormatを次のように出力することしかできません。

2011-12-27 09:00:00 GMT + 00:00

これはフォーマット文字列を使用しますyyyy-MM-dd HH:mm:ss z

単純なタイムゾーンが冬時間(GMT)IDまたは夏時間ID(BST)を参照している場所はどこにも見当たりません。

13
Andez

エレガントなソリューションではありませんが、それは私たちにとってはうまくいきます。 DateFormat/SimpleDateFormatのカスタム実装を作成する必要がありました。これは次のようになります。

static {
    // this would be initialized like something as follows when the application starts
    // which causes the headaches of SimpleDateFormat not to work...
    SimpleTimeZone tz = new SimpleTimeZone(0, "Out Timezone");             
    TimeZone.setDefault(tz);  
}

// therefore this class will workaround the issue, 

public class OurOwnCustomDateFormat
    extends SimpleDateFormat {

    /** The pattern to use as the format string. */
    protected String pattern;

    public OurOwnCustomDateFormat(String pattern) {
         super(pattern);
         // store the pattern
         this.pattern = pattern;
    }

    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) {

         // custom implementation to format the date and time based on our TimeZone            
         toAppendTo.insert(pos.getBeginIndex(), "the date with our custom format calculated here");
         return toAppendTo; 
    }
2
Andez

この質問と回答は現在時代遅れです。それらは、Java 8以降に組み込まれたJava.timeフレームワークによって時代遅れになった古い日時クラスを使用します。古いクラスは、設計が不十分で、混乱し、面倒です;それらを避けてください

3〜4文字のゾーンコードは避けてください

BSTなどの3〜4文字のコードは避けてください。それらは標準化されておらず、一意でもありません。これらは実際にはタイムゾーンを表すものではありません。また、夏時間(DST)の問題にさらに混乱が生じます。

代わりに、 適切なタイムゾーン を使用してください。ほとんどは、 continent/region などのEurope/London形式です。

デフォルトのタイムゾーンの設定は避けてください

Java.util.TimeZone.setDefault の呼び出しは、最も極端な場合にのみ実行する必要があります。この呼び出しは、JVM内のすべてのアプリのすべてのスレッドで実行されているすべてのコードにすぐに影響しますduringランタイム。

代わりに、すべての日時コードで、目的の/予想されるタイムゾーンを指定します。省略した場合、Javaは、JVMの現在のデフォルトのタイムゾーンに暗黙的に依存することでフォールバックします。上記のように、このデフォルトは実行時にいつでも変更できます!代わりに、明示的に指定してください。定期的に渡される引数として期待されるタイムゾーンの場合、現在のデフォルトのタイムゾーンは意味がなく、無関係です。

Java.time

Java.timeフレームワークはJava 8以降に組み込まれています。 チュートリアル を参照してください。JSR310によって定義されています。非常に成功したJoda-Timeライブラリに触発されています。

Instant

Instantは、UTCのタイムライン上の瞬間です。

次の例は、Java.timeクラスが、標準の ISO 8601 形式で、解析パターンを指定する必要がない場合に、デフォルトで文字列を解析/生成する方法を示しています。 DateTimeFormatterクラスを使用して、他の非標準パターンを指定します。

Instant instant = Instant.parse( "2011-12-27T09:00:00Z" );

ZonedDateTime

必要に応じてタイムゾーンを適用し、 ZonedDateTime を生成します。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );

文字列の生成

DateTimeFormatterを使用して、ZonedDateTimeオブジェクトのテキスト表現を作成できます。カスタムパターンを指定できます。または、私がお勧めするように、Java.timeをローカライズさせてください。

DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM );

タイムゾーンと同じ理由で、目的/期待値を指定するのが最適です Locale JVMの現在のデフォルトは、内で実行されているアプリの任意のスレッドの任意のコードによっていつでも変更できます。 JVM。 Localeは、(a)日と月の名前に使用される人間の言語、および(b)コンマとピリオドなどの文化的規範、および月、日、年などの部分の順序を決定します。

formatter = formatter.withLocale( Locale.CANADA_FRENCH );
String output = zdt.format( formatter );

Java.timeについて

Java.time フレームワークはJava 8以降に組み込まれています。これらのクラスは厄介な古いクラスに取って代わります- legacy 日時クラス Java.util.DateCalendar 、& SimpleDateFormat

Joda-Time プロジェクトは、現在 メンテナンスモード であり、 Java.timeへの移行をアドバイスします。 クラス。

詳細については、 Oracle Tutorial を参照してください。そして、StackOverflowで多くの例と説明を検索してください。仕様は JSR 31 です。

Java.timeオブジェクトをデータベースと直接交換できます。 JDBC driverJDBC 4.2 以降に準拠しています。文字列やJava.sql.*クラスは必要ありません。

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

ThreeTen-Extra プロジェクトは、追加のクラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性のある試験場です。 IntervalYearWeekYearQuarter などの便利なクラスがここにあります。 、および more

7
Basil Bourque

要件に合った正しいパターンを使用していると思いますが、JDKはタイムゾーンの名前を認識していないため、代わりに GMTオフセット値 を使用するように切り替えます。

パターンを使用して日付をフォーマットすると、タイムゾーン部分に「GMT」が表示されます。

TimeZone.getDefault().getDisplayName()はあなたに何を与えますか?私の場合、「グリニッジ標準時」を取得します。

4
sudocode

System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").format(new Date()));2011-11-22 13:42:16 GMTを返すだけなので、希望どおりに機能しているように見えます。他の場所で問題が発生しているようですが、独自のフォーマッタクラスを作成する必要はありません。

1
Michael Berry

この問題を自分のコンピューターで再現できないためです。これはローカリゼーションに関係していると思います。これを試して

System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z",Locale.US).format(new Date()));

お役に立てれば。

1