2017-02-01 2 views
3

に基づいて非常に異なる値をもたらします。小さなサンプルアプリケーションを作って、私が物事を見ていないか、値が後で私が捕まえていないところで操作されていないことを確認しました。SimpleDateFormat.parseは、私はしばらくの間、この上で、私の頭をバッシングされているAndroidのバージョン

問題は、私は、日付形式の文字列の日付を解析しようとすると、私は、デバイスAPIレベルに応じて、2つの非常に異なる結果を得ることです。ここで

DateFormat utcFormat; 
String utcDate = "2017-01-31 18:58:12.2334924Z"; 
utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSS'Z'"); 
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 
try{ 
    conversion.setText(utcFormat.parse(utcDate).toString()); 
} 
catch (ParseException e){ 
    conversion.setText("exception encountered: " + e.getMessage()); 
} 

は私の結果です:

On Android 4.4.2 device: Tue Jan 31 14:37:06 EST 2017 
On Android 6.0.1 device: Tue Jan 31 13:58:12 EST 2017 

あなたが見ることができるように、正確に同じ入力に基づいて約40分の違いがあります。デバイスのロケールは同じです(ロケールのハードコーディングも試みましたが)。デバイスの設定時間は同じです。

ここで何か問題がありますか?

+0

「SSS」のみを使用して試してみてのおインプットトリムミリ秒の精度。この場合もまだ異なる結果が表示されますか? –

+0

私はミリ秒のカウントとして「2334924」の解釈は40分(ほぼ)近く分のカウントを与えることに気づきました。たぶんアンドロイド6は、入力が正しく解釈になるというような解釈を変更しましたが、まだ公式ドキュメント内の任意のヒントが見つかりません(とあなたのコード例では、本当に間違ったパターンを使用しないので、間違った計算 - 14時37分06秒ESTは間違っています!)。 –

+0

この場合、ミリ秒をトリミングする簡単な方法はありますか? –

答えて

2

シンボルSの一般的な問題は次のとおりです。java.util.Datejava.text.SimpleDateFormatの精度は、最高でもミリ秒に制限されています。より高い精度はサポートされていません。したがって、3つ以上のパターンシンボルSSSを指定することは意味がありません。

さらに、私はいくつかの研究を行うことを試み、これを見つけた:pattern symbol table of official javadocは「ミリ秒」と「S」を指定

。つまり、入力のドットの後ろにある "2334924"の値は、絶対的なミリ秒数として解析され、約39分になります。これは、Android v4.4でテストした最初の例の解析時間を説明しています。

しかし、発表されたjavadocは、この詳細に少し時代遅れのようです。

<tr> <td>{@code S}</td> 
<td>fractional seconds</td>  
<td>(Number)</td>  
<td>978</td> </tr> 

しかし、小数秒は233ミリ秒(プラスより高精度の無視分数)として、すなわち、テキスト 「2334924」の全く異なる解釈を引き起こす:あなたはsource codeのためのgoogleなら、あなたはライン71で見つけます。これはAndroid v6の2番目のコード例を説明しています。私は両方のAndroidバージョンの間のどこかに、Googleがドキュメントなしで動作を変更することを決めたと思う。私が見つけた最高のものは、この行動の変化に関連するかもしれないissue 78859のようです。より新しいAndroidのバージョンにより統合されたように思わ

ICU4Jも小数第二としてのシンボル「S」を宣言します。

回避策や解決策:(高精度部品を無視して)S.が代わりに使う3つの以上のパターン記号を使用して

避けてください:

String input = "2017-01-31 18:58:12.2334924Z"; 
int dot = input.indexOf("."); 
String trimmed = input.substring(0, dot + 4) + "Z"; // 2017-01-31 18:58:12.233Z 
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS'Z'"); 
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 
java.util.Date d = utcFormat.parse(trimmed); 
関連する問題