プロが教える店舗&オフィスのセキュリティ対策術

文字列を日付に変換するところで、「ParseException: Unparseable date: "2013/08/06" 
 at java.text.DateFormat.parse(DateFormat.java:335) 」とエラー表示されました。

実際のコーディングは
Date sgndate = new Date();
if(!StringUtil.isNull(rs.getString("sgnymd"))){
String lstdaysgn = rs.getString("sgnymd");
lstdaysgn = lstdaysgn.substring(0,4) + "/" + lstdaysgn.substring(5,7) + "/" +
                              lstdaysgn.substring(8,10);
sgndate = DateFormat.getDateInstance().parse(lstdaysgn); ・・・・・・・・・ここでエラー発生
}

どこが悪いのか解りません。
よろしくご教授ください。

A 回答 (3件)

どこが悪いって


DateFormat.getDateInstance().parse(lstdaysgn);
が悪い。実際エラーはそこで起こってるんだし。で、そこの部分について手直しよりも一つ提案があるので聞いてみてくれたまい。

仮にrsがデータベースからSELECT文でデータを取ってきた時のレコードセットであり、かつrs.getString("sgnymd")がyyyyMMdd形式の(スラッシュが付かない)8桁の数字文字列であり、かつ単純にその日付でDate型にしたいだけなのであればこうしたらいいんじゃないか。

Date sgndate = null; // new Date()しない。もちろん後続のルーチンでnullチェックは要るようになる。
if(!StringUtil.isNull(rs.getString("sgnymd"))){
String lstdaysgn = rs.getString("sgnymd");
// ↓これもしない。
// lstdaysgn = lstdaysgn.substring(0,4) + "/" + lstdaysgn.substring(5,7) + "/" +
//                              lstdaysgn.substring(8,10);
sgndate = new SimpleDateFormat("yyyyMMdd").parse(lstdaysgn); // スラッシュつけずに8桁のyyyyMMddでそのままDateにする。
}

以上の手直しにより、このルーチンを通る際にDate 1つとString 7つ、インスタンスの生成を回避する事ができる。これがループで処理されるならなおさら。
仮に、「new SimpleDateFormat("yyyyMMdd")だとパースのたびにSimpleDateFormatのインスタンスが作られちゃうジャン!」と思うならルーチン化していいと思うけど、その場合はスレッドセーフなルーチンにしないといけないのでそこらへん注意の事。

この回答への補足

実は、ParseExceptionが必ず起きるのではなく、2年ほど前から使っていて初めて起きました。
再現テストでも起きないので、質問させていただきました。
なぜ、いままで正常に処理されていたのでしょうか。お分かりになりましたら教えてください。

よろしくお願いします。

補足日時:2013/09/09 15:42
    • good
    • 1
この回答へのお礼

ご回答ありがとうございます。

正しい記述を教えていただき感謝します。
早速プログラムを修正します。

お礼日時:2013/09/09 15:23

> なぜ、いままで正常に処理されていたのでしょうか。

お分かりになりましたら教えてください。
分からん(笑)。

冗談はともかくとして、本当に僕には分からない。なぜかというとそのプログラムの前後、実行環境(OS、JavaVMの実装、コンテナ、ブートストラップ)が分からないからだ。
あなたもエラーになったりならなかったりすると言っているように、DateFormat.getInstance()で取得されるDateFormatインスタンスは状況や環境に大きく依存する。Windows 7(32bit)+Oracle JDK 1.7.0_25(32bit)で開発中はうまく動くのに、本番環境のLinux 2.6.32(64bit)+OpenJDK 1.7.0_25(64bit)だと動かないとかも当たり前にある。

今取得されたDateFormatインスタンスがどんな書式を受け付けるかを確認するにはformatでDateからStringにしてみればいい。それが
"09/10/13 19:19:25"
になっているかも知れないし、
"Tue Nov 10 19:19:25 JST 2013"
になっているかも知れない。この辺はリージョン(日本とか)、言語(日本語とか)、バリアント(日本には関係ない)が関わってくる。ja_JPというのは、日本語(ja=Japanese)、日本(JP=Japan)、バリアントなしというJavaのローカライゼーション識別子になる。日本では日本語以外の公用語はないし、日本語は日本以外では公用語にならないのでjaは普通JPと対だけど、英語(en)の場合はアメリカ英語(en_US)とイギリス英語(en_GB)があったり、カナダにはフランス語(fr_CA)と英語(en_CA)があったり、まぁそんなこんなを全部含めた「カルチャー」によって日付をあらわす文字列が変わるために、ロケールに引っ張られるDateFormat.getInstance().parse()は状況が変わるとエラーになったりならなかったりなんだ。

まぁ、結局何の回答にもなってないけど、とにかくDateFormatじゃなくって(特にデータベースにyyyyMMdd形式のvarchar(8)で保存している時など)形式を厳密に指定できるSimpleDateFormatを使う方が部品化も簡単になるし、トラブルも少なくなるわよという事。プログラマーならこんなところじゃなくってビジネスロジックの組み立てに時間を費やしたいわよね。
    • good
    • 2
この回答へのお礼

とても解りやすい解説をしてくださり、ありがとうございます。

胸のつかえが取れた感じです。

お礼日時:2013/09/10 20:07

たぶん


getDateInstance
の意味を分かって使っていないと思う

次の実装が確実と思うわ

Date result = new SimpleDateFormat("yyyy/MM/dd").parse(lstdaysgn);
    • good
    • 0
この回答へのお礼

早速のご回答ありがとうございます。

意味がよくわからず使っていました。

お礼日時:2013/09/09 15:21

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています