DOBON.NET DOBON.NETプログラミング掲示板過去ログ

1S2は昭和?

環境/言語:[.NET4.0]
分類:[.NET]

CultureInfo("ja-JP")でDateTime.Parse("1S2")とやると1949/1/2と変換されてしまい頭を抱えています。Sを昭和のSと解釈しているようですが、私の会社の商品名に1S2というのがあって商品名と日付を自動判別できなくて困っています。このパターンだけでしたら回避するコードを書くのは簡単ですが、他にも思いもよらぬ文字列を日付と判定されてしまうのか分からないです。DateTime.TryParseが成功するすべてのパターンを知る方法はないでしょうか。
■No30809に返信(namsanさんの記事)

TryParseExactを使えば受け入れる書式を指定出来るのでかなり精度はあがるのではないでしょうか?

ただyyyyMMddを受け入れるようにした場合商品に20120808とかあったら結局日付が商品かはわかりません。
■No30810に返信(shuさんの記事)
> ■No30809に返信(namsanさんの記事)
>
> TryParseExactを使えば受け入れる書式を指定出来るのでかなり精度はあがるのではないでしょうか?
>
> ただyyyyMMddを受け入れるようにした場合商品に20120808とかあったら結局日付が商品かはわかりません。
>

ありがとうございます。
その後色々実験したところ
・DateTime.Parse("1S2")が1949年になるのは、今年が平成24年なんで24という年号が省略されているとみなして昭和24年と解釈してるらしい。同様に"1M2"は明治24年にParseされます。
・他にも"1 2S"、"1M2S"、"1昭2"も昭和24年とParseされます。つまり、元号の文字列は単なる区切り記号とみなしていて、どこに何回現れても構わないようです。
・ここまで分かれば私的には納得したのですが、気になるのは上記のような仕様が書いてある文書を見つけることができません。DateTimeFormat.GetAllDateTimePatterns()とやると日付パターン文字列が100個以上も出てきますが、"gg y/M/d"など元号ggはすべて冒頭につける形式になっていて上のようなParseをするとは想像できないです。
  • 題名: Re[1]: 1S2は昭和?
  • 著者: wwJww
  • 日時: 2012/08/05 15:43:25
  • ID: 30812
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
そもそも、商品名と日付が一緒くたになっているというシナリオが想定できないですねぇ。
ふつーフィールド分けているのだから、判別するひつようがないわけで。
  • 題名: Re[3]: 1S2は昭和?
  • 著者: shu
  • 日時: 2012/08/05 21:44:22
  • ID: 30813
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No30811に返信(namsanさんの記事)
> ・ここまで分かれば私的には納得したのですが、気になるのは上記のような仕様が書いてある文書を見つけることができません。DateTimeFormat.GetAllDateTimePatterns()とやると日付パターン文字列が100個以上も出てきますが、"gg y/M/d"など元号ggはすべて冒頭につける形式になっていて上のようなParseをするとは想像できないです。
>
想像できなくても実際そういう動きをするというのが分かっているのだから回避するにはどの書式が商品でどの書式が日付だということをシステムの仕様として決めないと駄目だと思います。どこにも書かれていないから今回のパースはFramework上の不具合だということを言うのならそれはフィードバックにでも投げると良いかと思います。ただ受け入れられたとしても修正されるのには時間がかかるでしょう。
  • 題名: Re[3]: 1S2は昭和?
  • 著者: Azulean
  • 日時: 2012/08/06 6:19:25
  • ID: 30814
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No30811に返信(namsanさんの記事)
> 上のようなParseをするとは想像できないです。

このスレッドの目的は、今回の遭遇している問題の回避、あるいは解決ではないのでしょうか?
想像できないパターンでも解釈されてしまう以上は、ブラックリスト方式ではなく、ホワイトリスト方式を考えるべきかな。

shu さんも書かれていますが、仮に不具合と認定されても今すぐ直りません。
今の問題の解決がその判断、修正完了まで待てるならそれでもよいかもしれませんが、現実的にはそこまで余裕があるわけではないでしょうから、回避策の方向に思考をスイッチしましょう。


■ブラックリスト方式
定義しておいたパターンに合致すれば日付とみなさない。
namsan さんが当初書かれていた「1S2」を日付とみなさず、Date.Parse しないというやり方。
この方式は、Date.Parse が受け入れるパターンを事前にすべて網羅しなければならないので、未知の動作をする可能性がある。

■ホワイトリスト方式
定義しておいたパターンに合致すれば日付とみなす。(念のため、Date.Parse で例外をスローすれば日付とみなさないロジックも入れる)
shu さんが No30810 で提案されていたやり方。
この方式は、商品名や日付が記録されている情報で、日付の入力パターンをあらかじめ定義しておく。商品情報の入力パターンが既知であることから、確度を上げられるはず。
  • 題名: Re[1]: 1S2は昭和?
  • 著者: オショウ
  • 日時: 2012/08/06 11:42:09
  • ID: 30815
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
流通業のソフトウェアもいろいろ製作したことありますし、バーコード読み取り
でも多数制作した経験から言いますと、なぜ、『1S2』を日付として解釈しない
といけないのか?その仕様が問題です。

一般的には、
YY/MM/DD か、YYYY/MM/DD は最低必要で、『/』をどう扱うか・・・くらいで、
日付の文字列と他の文字列を区別するべきで、そうなっていない場合、誤認する
可能性のある部位の仕様を改めるべきます。

どうしても同一の文字列が発生してしまう場合は、相対的に出現する順序で区別
するとか、無理にでも商品コードの方にでも頭文字を1文字以上付加してでも、
区別するべきだと思います。

バーコードを使っているなら、NW7 と、JAN とで区別するとか・・・

1S2 を、日付かもしれないからと言ってDateTime.Parseするのはナンセンスだと
思います。

以上。参考まで

DOBON.NET | プログラミング道 | プログラミング掲示板