このようにタイムスタンプを解析したい--"2016-03-16 01:14:21.6739"
。しかし、SimpleDateFormat
を使用して解析すると、誤った解析値が出力されることがわかりました。残り739ミリ秒で、6739ミリ秒から6秒になります。日付をこの形式に変換しました-Wed Mar 16 01:14:27 PDT 2016
。秒の部分が21秒から27秒に変更されたのはなぜですか(6秒の追加?)。以下は私のコードスニペットです:
final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSS");
String parsedate="2016-03-16 01:14:21.6739";
try {
Date outputdate = sf.parse(parsedate);
String newdate = outputdate.toString(); //==output date is: Wed Mar 16 01:14:27 PDT 2016
System.out.println(newdate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SimpleDateFormatを使用して、ミリ秒よりも細かい粒度で時間を表現することは不可能のようです。何が起こっているのかというと、6739を入力すると、Javaはそれを6739ミリ秒、つまり6秒と739ミリ秒として理解するため、6秒の違いが観察されます。
これらを確認してください。非常によく説明されています。 文字列-ナノ秒での日付変換マイクロ秒またはナノ秒の精度でのJava日付解析
SS
のSimpleDateFormat
はミリ秒です。 6739ミリ秒あります。これは、時間に6.7秒を追加することを意味します。おそらく、6739
を673
に切り捨てて(または、必要に応じて674
に丸めて)、ミリ秒単位で正しく解析できるようにすることができます。
LocalDateTime.parse(
"2016-03-16 01:14:21.6739".replace( " " , "T" ) // Comply with ISO 8601 standard format.
)
他の人が指摘したように、Java.util.Date
の分解能はミリ秒です。これは、秒の小数部の最大3桁を意味します。
入力文字列に4桁あり、1桁が多すぎます。入力値には、マイクロ秒やナノ秒などのより細かい解像度が必要です。
欠陥があり、紛らわしく、面倒なJava.util.Date/.Calendarクラスを使用する代わりに、それらの代わりに移動します。 Java.time フレームワークがJava 8以降。
Java.timeクラスの解像度は ナノ秒、最大nine秒の小数部の数字。例えば:
2016-03-17T05:19:24.123456789Z
文字列入力はほぼ標準です ISO 8601 Java.timeで、日時値のテキスト表現を解析/生成するときにデフォルトで使用される形式です。 ISO 8601に準拠するには、中央のスペースをT
に置き換えます。
String input = "2016-03-16 01:14:21.6739".replace( " " , "T" );
LocalDateTime
は、タイムゾーンコンテキストを含まない日時の概算です。 タイムライン上の瞬間ではありません。
LocalDateTime ldt = LocalDateTime.parse( input );
LocalDateTime
目的のタイムゾーンを適用して、タイムライン上の実際の瞬間にします。 UTC向けの場合は、Instant
を作成します。
Instant instant = ldt.toInstant( ZoneOffset.UTC );
特定のタイムゾーンを対象としている場合は、 ZoneId
を指定して ZoneDateTime
を取得します。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );
少しトピックから外れていますが、SimpleDateFormat
クラスはスレッドセーフではありません-ある程度理解できる解析だけでなく、フォーマットについてもです。ネット上にはこれに関する多くの情報があります、ここに一例があります: http://javarevisited.blogspot.co.il/2012/03/simpledateformat-in-Java-is- not-thread.html 。この問題は修正されません。 Java 8には、まったく新しいパッケージがありますJava.time
完全または部分的な日付と時刻で作業できる素晴らしい新機能を備えています。また、大幅に改善されたフォーマットおよび解析機能を提供する新しいクラス DateTimeFormatter があります。ただし、Java古いJava 8を使用する場合は、 Jodaタイムライブラリ またはApache FastDateFormat
上記のコメントで述べたように、あなたの質問にはすでに答えが含まれています。ミリ秒は3桁を超えてはなりません。そうでない場合は、すでに少なくとも1秒を表します。
コードが機能しているのは、Java.text.SimpleDateFormat
の非常に疑わしい機能であるlenientによるものです( ここ を参照) )オプション。デフォルトでは、SimpleDateFormat
のsetLenient
はtrue
に設定されています。これは、パーサーがパターンに100%一致しない文字列を解釈しようとし、それらを日付オブジェクトに変換することを意味します。いくつかのヒューリスティックの手段。たとえば、日付31.04.2016
を受け入れ、それを01.05.2016
に変換します。この機能は状況によっては優れている場合がありますが、ほとんどの場合、疑わしい結果が生成されます。
コードでlenientをfalse
に設定すると、日付文字列は解析されなくなります。パターンのエラーをより明確にする:
final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSS");
sf.setLenient(false);
String parsedate="2016-03-16 01:14:21.6739";
...
Java.util.Date
はミリ秒未満の精度を表すことができないため、日付を解析するための最良のオプションは、ドットの後の部分にそれ以上の数字がある場合は、入力日付の最後の桁を単純に取り除くことだと思います。 4桁より。コードは次のようになります。
final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sf.setLenient(false);
String parsedate="2016-03-16 01:14:21.6739";
try {
// 23 is the length of the date pattern
if (parsedate.length() > 23) {
parsedate = parsedate.substring(0, 23);
}
Date outputdate = sf.parse(parsedate);
String newdate = sf.format(outputdate); //==output date is: 2016-03-16 01:14:21.673
System.out.println(newdate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
4桁目のすべての情報を失わないようにするために、丸めロジックを追加することもできます...
String newdate = outputdate.toString();の代わりにString newdate = sf.format(outputdate);を使用できます。
最終出力として文字列を取得する必要がある場合は、format
の代わりにparse
を使用しないでください。
final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ");
sf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date curDate = new Date();
String outputdate = sf.format(curDate);
// 2016-03-17 09:45:28.658+0000
System.out.println(outputdate);
Date strToDate = new Date();
try {
strToDate = sf.parse(outputdate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Thu Mar 17 17:11:30 MYT 2016
System.out.println(strToDate);
"yyyy-MM-dd HH:mm:ss.SSSS"
の代わりに"yyyy-MM-dd HH:mm:ss.SSSZ"
を使用してここで確認してください https://docs.Oracle.com/javase/7/docs/api/Java/text/SimpleDateFormat.html
"yyyy-MM-dd'T'HH:mm:ss.SSSZ" 2001-07-04T12:08:56.235-0700