プログラムの日時フィールドの形式を手動で入力できるようにしたい。Teditコンポーネントがあります。たとえば、ユーザーが「HH:nn」と入力した場合、これは有効な日時形式の文字列であり、すべての日時コンポーネントはformatプロパティをこれに変更する必要がありますが、「asd」と入力した場合は変更されません。自分の関数を書かずに、これをチェックする簡単な方法はありますか?
6 に答える
次の関数を使用できます。
TryStrToDate
TryStrToTime
TryStrToDateTime
文字列を日付/時刻に変換しようとし、変換が成功するとtrueを返します。したがって、例外は発生しません。
オプションのTFormatSettingsパラメーターを使用して、独自のフォーマットを定義できます。
すべての関数はSysUtilsで定義されています。
ただし、TDateTimePickerやTMonthCalendarなど、VCLで使用できる日付/時刻コントロールがいくつかあります。それらも使用できます。
問題は、「有効なフォーマット」をどのように定義するかということです。おそらく、あなたができる最善のことは、フォーマット文字列内の特定の文字の存在を検索することです。しかし、ユーザーが年を表示することを気にしない場合、または時刻を表示したくない場合はどうなりますか?
それらが「有効な形式」に入っていることを確認することについては、あまり強調しません。むしろ、現在の日時を使用して入力した形式のプレビューを提供するだけです。
編集:OPからの新しい情報の更新
質問には少し説明がありました:
実際には、データベースのTDateTimePickerフィールドとTDateTimeフィールドのFormatプロパティを指定する必要があります。そして、ユーザーがこれらの形式を変更できるようにしたいと思います。– Tofig Hasanov
それは重要な説明です、おそらくあなたはそれをあなたの質問に含めたいですか?
重要なことは、フォーマット文字列が表示フォーマットだけでなく編集フォーマットも示すことです。現在、ほとんどすべての文字列が有効ですが、すべてが特に役立つわけではありません(特に編集に)。例えば:
FDateTimeFormat := '"The day is "d" of this month of the year "yy';
これは、日付を適切にフォーマットできるという意味で完全に有効です。ただし、月の設定には特に役立ちません。
今私見ですが、ユーザーがフォーマット文字列に月のフィールドを含めないことで生活を困難にしたい場合は、大変です!ただし、問題は、フォーマットルールが少し技術的であり、ユーザーが数か月と数分を混同する可能性があることです。例:FTimeFormat := 'HH:MM:SS'
実際には<時間>:<月>:<秒>
それでも、私は元の提案を支持します(1つの小さな調整を加えます):むしろ、フォーマット文字列の「間違い」を強調する必要がある現在の日時を使用して、入力したフォーマットのプレビューを提供します。
ユーザーがこの設定を定義できるようにする構成ダイアログがあると仮定します。
- TComboBoxを追加します(ユーザーをガイドするためにサンプル文字列を「プリロード」できます。また、ユーザーはすでに適切なオプションの1つを選択するだけでもかまいません。
- 選択したフォーマット文字列の動作例を示すラベルを追加します。
- TComboBox.OnChangeを実装して、ユーザーの選択の効果を説明します。
次のコードでうまくいくはずです。
procedure TConfigDialog.DateTimeFormatChange(Sender: TObject);
var
LCheckDate: TDateTime;
LFormattedDate: String;
begin
LCheckDate := EncodeDate(1999, 12, 31) + EncodeTime(20, 45, 50, 123);
LFormattedDate := FormatDateTime(DateTimeFormat.Text, LCheckDate);
DateFormatSample.Caption := 'Fri 31 December 1999 at 8:45:50.123 would be displayed as: ' + LFormattedDate;
end;
警告
TDateTimeField
これをとの両方に使用したいとおっしゃいましたTDateTimePicker
。残念ながら、TDateTimePicker
FormatDateTimeを使用しない組み込みのWindowsコントロールをラップするだけなので、フォーマット文字列にも異なるルールがあります。
したがって、ユーザーが2つの異なる形式の文字列を構成できるようにする必要があります。:(
Gamecatの答えを拡張するには
If not tryStrToDateTime(Edit1.text,MyDateTimeVar) then
ShowMessage('You need to make your entry look like a date...how about yy/mm/dd');
MyDateTimeVar変数を設定せずにtryStrToDateTimeVarに渡すだけでチェックしたい場合は、例外処理を使用できます。
try
StrToDateTime(Edit1.Text);
except
ShowMessage('You need to make your entry look like a date...how about yy/mm/dd');
end;
ダグとゲームキャット、あなたは両方とも質問を誤解していると思います。
- 彼は文字列から日付に行きたくありません。
- 彼には日付があります。
- 彼は、ユーザーが指定した形式に従って、その日付を文字列に変換したいと考えています。
- つまり
DisplayDate := FormatDateTime(UserDefinedFormat, Now());
StrToDateTime(またはTryStrToDateTime)を使用できるのは、循環的な「整合性チェック」を試みることだけです。ただし、ユーザーが日付/時刻のすべての要素を表示したいという保証はないため、これは適切ではありません。その結果、循環チェックは機能しません!
function to_date(p_format,p_string:string): TDateTime;
var
v_day, //dd
v_month, //mm
v_year:Integer; //yyyy
v_hour, //hh
v_minute, //nn
v_second:Integer;//ss
v_date:TDateTime;
v_time:TDateTime;
begin
v_day:=Pos('dd',p_format);
v_month:=Pos('mm',p_format);
v_year:=Pos('yyyy',p_format);
v_hour:=Pos('hh',p_format);
v_minute:=Pos('nn',p_format);
v_second:=Pos('ss',p_format);
v_day:=StrToInt(Copy(p_string,v_day,2));
v_month:=StrToInt(Copy(p_string,v_month,2));
v_year:=StrToInt(Copy(p_string,v_year,4));
v_hour:=StrToInt(Copy(p_string,v_hour,2));
v_minute:=StrToInt(Copy(p_string,v_minute,2));
v_second:=StrToInt(Copy(p_string,v_second,2));
v_date:=EncodeDate(v_year,v_month,v_day);
v_time:=EncodeTime(v_hour,v_minute,v_second,0);
ReplaceTime(v_date,v_time);
Result:=v_date;
end;
プロシージャTForm1.BitBtn1Click(送信者:TObject);
var
mydate、mydate1:TDateTime;
TestDate、TestDate1:string;
TestDateを開始します:= '13/15/2021'
;
TestDate1:= '03/05/2021';
IsValidDate(TestDate)の場合、
mydate
:= strtodate(TestDate)
showmessage(TestDate +'は有効な日付');を開始します。
end
else
showmessage(TestDate +'は有効な日付ではありません!');
IsValidDate(TestDate1)の場合、
mydate
:= strtodate(TestDat1e)
showmessage(TestDate1 +'は有効な日付');を開始します。
end
else
showmessage(TestDate1 +'は有効な日付ではありません!');
終わり;
関数IsValidDate(S:string):boolean;
var
FS:TFormatSettings;
DT:TDatetime;
FSを開始します
:= TFormatSettings.Create('en-US');
TryStrToDate(S、DT、FS)の場合は
result:= true
、それ以外の場合は
result:= false;
終わり;