I want user to be able to manually enter format of the datetime fields in the program. I have Tedit component. For example if user enters 'HH:nn', then this is a valid datetime format string and all datetime components should change format property to this, but if he enters 'asd', it is not. Is there a quick way to check this, without writing my own function?
You could use the functions:
TryStrToDate
TryStrToTime
TryStrToDateTime
They try to convert a string to a date/time and if the conversion succeeds, it returns true. So there are no exceptions raised.
You can use the optional TFormatSettings parameter to define your own format.
All functions are defined in SysUtils.
But there are some date/time controls available in the VCL like TDateTimePicker and TMonthCalendar. You can use them also.
The problem is, how do you define a 'valid format'? Possibly, the best you could do is search for the existence of specific letters in the format string. But what if the user doesn't care about seeing the year, or doesn't want to see the time?
I wouldn't stress too much about verifying that they have entered a 'valid format'. Rather just give them a preview of the format they've entered using the current date-time.
Edit: Update for new info from OP
There was a little clarification on the question:
Actually I need to specify Format property of TDateTimePicker and TDateTime fields in Database. And I want user to be able to change these formats. – Tofig Hasanov
That's an important clarification, perhaps you want to include it in your question?
The important thing is that the format string will not only indicate the Display Format, but also the editing format. Now although pretty much any string is valid, not all are particularly useful (especially for editing). E.g.:
FDateTimeFormat := '"The day is "d" of this month of the year "yy';
This is perfectly valid in the sense that your date can be formatted accordingly. However, it is not particularly useful for setting the month.
Now IMHO, if a user wants to make make their lives difficult by not including month fields in their format string - tough! The problem however comes in that the format rules are a little technical, and a user may get months and minutes mixed up. E.g. FTimeFormat := 'HH:MM:SS'
which is actually <hours>:<months>:<seconds>
Even so, I stand by my original suggestion (with one minor tweak): Rather just give them a preview of the format they've entered using the current date-time a predetermined date-time that should emphasise 'mistakes' in the format string.
Assuming you have a configuration dialog in which you intend letting the user define this setting:
- Add a TComboBox (you can then 'pre-load' it with sample strings to guide the user; also they may simply choose one of your already suitable options.
- Add a label in which you illustrate the sample behaviour of the chosen format string.
- Implement TComboBox.OnChange to illustrate the effect of the user's choice.
The following code should do the trick:
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;
WARNING
You mentioned you want to use this for both TDateTimeField
and TDateTimePicker
. Unfortunately, TDateTimePicker
simply wraps a built-in Windows Control which does not use FormatDateTime, and consequently also has different rules for its format strings.
So I'm afraid you'll have to allow your users to configure two different format strings. :(
To expand on Gamecat's answer
If not tryStrToDateTime(Edit1.text,MyDateTimeVar) then
ShowMessage('You need to make your entry look like a date...how about yy/mm/dd');
If you just want to check it without setting up the MyDateTimeVar variable to pass to tryStrToDateTimeVar you can just use exception handling
try
StrToDateTime(Edit1.Text);
except
ShowMessage('You need to make your entry look like a date...how about yy/mm/dd');
end;
Doug and Gamecat, I believe you are both misunderstanding the question.
- He doesn't want to go from a string to a date.
- He has the date.
- He wants to convert that date into a string according to a format specified by the user.
- I.e.
DisplayDate := FormatDateTime(UserDefinedFormat, Now());
The only thing that StrToDateTime (or TryStrToDateTime) could be used for is to attempt a circular 'consistency check'. But that would be no good, because there is no guarantee the user wants to see all elements of the date/time. Consequently the circular check cannot work!