文字列から「年月日 日時」だけを取り出したい。

解決


  2010-03-19 23:13:55  No: 38057

文字列の前後にある不要な文字列を除去し、
「年月日 日時」だけを取り出したいです。

元となる文字列の例:
  2010-03-15 00:00:00            //不要文字が無い状態
    2010-03-15 00:00:00          //前や後に全角空白
    2010-03-15 00:00:00          //前や後にタブ
  2010-03-15 00:00:00#10#13      //前や後に改行が何個もある場合がある。
  今は2010-03-15 00:00:00です。  //ある程度想定される文字列を含む。
  (2010-03-15 00:00:00)        //ある程度想定される文字列を含む。

今は、
  while RightStr(strClip, 3) = '#13' do
    s := LeftStr(strClip, Length(s) - 3);
というように文字切り出しを何パターンか作っていますが、
あまりスマートでないように思います。

何か、スマートに記述する方法がありましたら、
ぜひ教えていただきたく思います。

どうぞよろしくお願いします。


manbon  2010-03-20 01:51:48  No: 38058

0〜9、−、:以外は全てStringReplaceで除去し、最後に
日付と時刻の間にスペースを入れるというのはどうでしょう?


tor  2010-03-20 02:09:22  No: 38059

頭とお尻からそれぞれ数字が現れるまで削っていくという方針で
例えばこんなのはどうでしょう。

function trim_date(const str: String): String;
var stpos, edpos: Integer;
begin
  stpos := 1;
  while (stpos <= Length(str)) and not (str[stpos] in ['0'..'9']) do Inc(stpos);
  edpos := Length(str);
  while (edpos > stpos) and not (str[edpos] in ['0'..'9']) do Dec(edpos);
  Result := Copy(str, stpos, edpos - stpos + 1);
end;

「あと15分で2010-03-15 00:00:00になります」みたいに余計な数字が入っていると駄目ですけど。


Ru  2010-03-20 02:25:56  No: 38060

できれば正規表現で処理が望ましいかと思います(BRegExp.pas)
http://www2.big.or.jp/~osamu/Delphi/MyLibrary.htm
http://oraclesqlpuzzle.hp.infoseek.co.jp/regex/

今サンプル組もうとしましたが、
久しぶり過ぎてやり方忘れてます。。。
参考として見てください。


あなたな〜ら、どうする♪  2010-03-20 03:32:25  No: 38061

必要な文字列のみ残すのも一考ですが、torさんの言われるように
「あと15分で・・・」などとなったらだめですね。
ならば、判定用の関数を作っておいて、頭から一文字づつ判定して
いく力技。

手続き上では・・・
(1)頭から一文字づつ調べて、まず数値文字か判定する。
(2)数値文字なら後19文字以上文字列が残っているか判定する。
(3)残っていた場合、19文字分切り出して判定する。
(4)日付文字列なら文字分飛ばしてから、また一文字づつ調べて・・・

(3)の判定関数(めくら打ち)
function XXXXX(切り出した文字列:String):Boolean;
var
 i :Integer;
begin
 Result := False;
 for i = 1 to 19 do
 begin
   case i of
     1..4,6,7,9,10,12,13,15,16,18,19 : 
             if (切り出した文字列[i] in ['0'..'9']) = False then Breake;
     5,8   : if 切り出した文字列[i] <> '-' then Breake;
     11    : if 切り出した文字列[i] <> ' ' then Breake;
     14,17 : if 切り出した文字列[i] <> ':' then Breake;
   end;
 end;
 Result := True;
end;


  2010-03-20 03:57:20  No: 38062

perl互換じゃない,思いっきりべたな正規表現で書くとすれば,

ここから→[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]←ここまで

を正規表現で検索すればよいのでは?
コードエディタに
2010-03-15 00:00:00
みたいなのをいくつか入力して,検索してみてください。
正規表現を使いたければ,そこらのエディタでもできるし,正規表現検索
コンポーネントも使いやすいのがいくつか見つかるはずです。


3K  2010-03-20 18:48:32  No: 38063

時間表示が  YYYY-MM-DD HH:MM:SS の固定なら
私だったらPos関数で '-' or ':' を探し、そこから前に必要な文字数、後ろに必要な文字数をcopy関数で取り出します。
必要があれば、取り出したい文字列に'-' and ':'が入っているか、取り出した文字数が必要文字数になっているかの
チェックもしますが。


TS  2010-03-21 03:27:34  No: 38064

澗 さんが発言されないのて、何が望みなのか分かりませんが、
最初のお題からいけば
copy(st,pos('-',st)-4,19);で答えが出ます、最初に-が出るとこけますが。


  2010-03-23 19:00:03  No: 38065

皆さま、多くのアドバイスをありがとうございました。
そして返信が遅くなり申し訳ありません。

>manbonさん
「0〜9、-、:以外は全て」という識別方法がわかりませんでした(^^;)

>torさん
そうなんですよね、「削る」方法だと余計な文字の混入が怖いです。

>Ruさん
正規表現。
その手法はどうもイメージが付きにくく、避けてしまいます(^^;
習得すべきなんでしょうね...。

>あなたな〜ら、どうする♪さん
なるほど...順に判定していけば良いのですね。
一筋の光が見えてきました。

>あさん
も、もしかして、、、正規表現の答えはそんな簡単なんですか(@@

>3Kさん  TSさん
pos関数で場所を見つけて処理する、これは良いですね!

皆さまから頂いたアドバイスを元に、作ってみました。
ひとまず動く事を確認できました。
正規表現については、これから勉強しようと思います。
ありがとうございました。


  2010-03-23 19:04:18  No: 38066

function TForm1.GetDateTime(sText:string; var sDate , sTime : string):string;
var
  sTemp : string;
  iTemp,i : integer;
begin
  //(0)値の初期化
  sDate:='';
  sTime:='';
  //(1)日付の切り出し
  iTemp := pos('-',sText);
  if (iTemp>4) and (copy(sText,iTemp+3,1)='-') then   //日付と判定
  begin
    sDate:=copy(sText,iTemp-4,10);
  end;
  //(2)時刻の切り出し
  iTemp := pos(':',sText);
  if (iTemp>3) and (copy(sText,iTemp+3,1)=':') then  //時刻と判定
  begin
    sTime:=copy(sText,iTemp-2,8);
  end;
  //(3)戻り値の生成
  if (length(sDate)=0)and(length(sTime)=0) then result:='';
  if (length(sDate)=0)and(length(sTime)>0) then result:=sTime;
  if (length(sDate)>0)and(length(sTime)=0) then result:=sDate;
  if (length(sDate)>0)and(length(sTime)>0) then result:=sDate+' '+sTime;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  sDate , sTime : string;
begin
  ShowMessage(GetDateTime(Edit1.Text,sDate , sTime));
  ShowMessage(sDate);
  ShowMessage(sTime);
end;


  2010-03-23 19:53:37  No: 38067

取り出したい文字列よりも前に  -や:があると取り出せませんね。
そうなってくると、もう、正規表現の世界なんでしょうかね・・・

ひとまず解決とさせていただきます。
皆さま、ありがとうございました。


DEKO  2010-03-23 21:01:52  No: 38068

> その手法はどうもイメージが付きにくく、避けてしまいます(^^;
まぁ、そう言わず... (^^;A

SKRegExp (http://komish.com/softlib/skregexp.htm) でのサンプルです。

uses
  ..., SKRegExpW;

function ExtractDateTimeStr(const AInputString: String): String;
var
  RegExp: TSkRegExp;
begin
  result := '';
  RegExp := TSkRegExp.Create;
  try
    RegExp.Expression := '\d{4}[-/][0-1]\d[-/][0-3]\d +[0-2]\d(:[0-5]\d){2}';
    if RegExp.Exec(AInputString) then
      result := RegExp.Match[0];
  finally
    RegExp.Free;
  end;
end;

※正規表現文字列の解説
\d{4}         // 年 (4 桁の数字。数字の 4 回の繰り返し)
[-/]          // 日付区切文字 ('-' または '/')
[0-1]\d       // 月 (1 桁目は '0' か '1'、2 桁目は数字)
[-/]          // 日付区切文字 ('-' または '/')
[0-3]\d       // 日 (1 桁目は '0'〜'3'、2 桁目は数字)
 +            // 空白の 1 文字以上の繰り返し
[0-2]\d       // 時  (1 桁目は '0'〜'2'、2 桁目は数字)
(:[0-5]\d){2} // 分/秒 (時刻区切文字 ':' に続く 1 桁目は '0'〜'5'、2 桁目は数字)
              // 分と秒は同じ条件なので 2 回繰り返し

もっといい正規表現があると思われます。イロイロと試してみて下さい。


  2010-03-24 00:26:11  No: 38069

>DEKOさん
ありがとうございます!(^^)
DEKOさんのお陰で重い腰が上がりました(笑)

この方法で次の2パターンであれば抜き出しできるのですね。
  2010/01/01 12:34:56
  2010-01-01 12:34:56
これは身につけると強い味方になりますね。

例えば、二桁表示でなく1桁表示の場合、
  2010/1/1 1:3:04
こういう時でも正規表現で抜き出せるんですよね?
ヤル気が起きてきました(^-^)

1桁版でも抜き出せるように頑張ってみます。
もし挫折したら、、、その時はまたよろしくお願いします(ペコ

ありがとうございました!!


  2010-03-24 00:26:35  No: 38070

ひとまず解決処理。


DEKO  2010-03-24 03:51:14  No: 38071

RegExp.Expression := '\d{4}[-/][0-1]?\d[-/][0-3]?\d +[0-2]?\d(:[0-5]?\d){2}';

これで "2010/1/2 3:4:5" も抜き出せるようになります。

※正規表現文字列の解説 (同じトコロは割愛)
[0-1]?\d       // 月 (1 桁目は '0' か '1' または 'なし'、2 桁目は数字)
[0-3]?\d       // 日 (1 桁目は '0'〜'3' または 'なし'、2 桁目は数字)
[0-2]?\d       // 時  (1 桁目は '0'〜'2' または 'なし'、2 桁目は数字)
(:[0-5]?\d){2} // 分/秒 (時刻区切文字 ':' に続く 1 桁目は '0'〜'5' または 'なし'、2 桁目は数字)
              // 分と秒は同じ条件なので 2 回繰り返し

# '?' は 0 または、1 回の繰り返しにマッチします。

暫定的な対応ですので、もし適合しないルールがありましたら、適宜追加してお使い下さい。

ヘルプにもあるように、"SKRegExp は Perl 互換" なので、
構文をうろ覚えでも、殆ど Perl の正規表現サンプルのコピペで済むから楽ですよ。

# URL 抜き出しですとか、Mail アドレス抜き出しですとか...。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加