2

I have set standard VCL TDateTimePicker - MaxDate property to Date - e.g.

DTPicker.MaxDate := Date;

However, there is a problem. If I now set the date to be the current one:

DTPicker.Date := Date;

It will not accept it. The control simply stays at the date which is set at the design time. I can solve it by setting MaxDate to be Date + 1 and then setting the Date property works fine and shows today's date, but then user is able to select tomorrow's date. I also tried to set MaxDate to Date + 0.99999999 but that also is of no help.

I use Delphi 2010 and C++Builder 2010 (if this is a bug in either of them).

Any ideas how to prevent selecting any date beyond today and set the control date to today's date?

Changing the date results in - "Failed to set calendar date or time."

Update:

I managed to make it work as following:

  1. open drop-down in TDateTimePicker (during runtime) and intentionally select Today's date (click on already selected Today's date)
  2. after that select any past date
  3. click button which has the code to reset the date and then it works.

My solution will likely be to use range-check before closing the form, as it seems that MaxDate is useless, at least with this version of Delphi.

Coder12345
  • 3,431
  • 3
  • 33
  • 73
  • 2
    TDateTimePicker's starting date is date+time of component creation. When you select antoher date at runtime it just changes the Date part. You can't select today since the component's time part would make entire value *after* MaxDate. Either set MaxDate to (Tomorrow - 1ms) or set picker's initial date to not include the time portion. – Boris B. Sep 23 '15 at 18:04
  • 1
    It sounds somewhat weird that you cannot enter Today when MaxDate is Today, but can enter Tomorrow when MaxDate is Tomorrow. BTW, I just tested it in D2010 on Windows 7 and everything works as expected. So it is very unlikely a bug in D2010. – Uwe Raabe Sep 23 '15 at 18:39
  • There is definitely an issue with D2010. I managed to make it work. Here is how - start the program. Intentionally select Today's date. Then select any other date. Then click the button - and then the same code works. – Coder12345 Sep 23 '15 at 18:41

2 Answers2

3

It appears it's the time portion of Date that's causing the problem. This works fine on D2007, XE, XE8, and Delphi 10 Seattle:

DateTimePicker1.MaxDate := Trunc(Date) + 0.99999999999;
DateTimePicker1.Date := Date;

Tested using a brand new VCL forms application. Drop a TDateTimePicker and a TButton on the form, and generate an event for the FormCreate for the form:

procedure TForm1.FormCreate(Sender: TObject);
begin
  DateTimePicker1.MaxDate := Trunc(Date) + 0.99999999999;
end;

and the button:

procedure TForm1.Button1Click(Sender: TObject);
begin
  DateTimePicker1.Date := Date;
end;

Run the app, click the DateTimePicker combobox to display the calendar, and pick any date that's available. The DateTimePicker displays the selected date. Click the button, and the DateTimePicker updates to show today's date. Dropping down the calendar again shows the correct dates available.

Of course, as Remy Lebeau pointed out in a comment: in an actual application, you wouldn't want to hard-code the time portion. A better solution would be to use DateUtils.EndOfDay(Date) or Trunc(Date) + EncodeTime(23, 59, 59, 999).

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Ken White
  • 123,280
  • 14
  • 225
  • 444
  • Sorry, just tried it in Delphi 2010 and it does not work. It sets the date to current if I comment out the first line, but if I remove the comment, it no longer works - date stays to whatever value it was set before and does not change. – Coder12345 Sep 23 '15 at 18:09
  • I just tested on three other Delphi versions, and they all work fine. ?? What happens when you try in a brand new project? – Ken White Sep 23 '15 at 18:16
  • I simply add TDateTimePicker on the form, and a TButton and add the code for the button OnClick event. Run it. Change the date to Monday. Click button - to reset - and it does nothing, stays at Monday's date. If I comment out first line, then it resets the date to today's date. It all looks like a bug in Delphi 2010, especially if you say it works in 3 different versions. – Coder12345 Sep 23 '15 at 18:19
  • 1
    `TDateTimePicker` is simply a wrapper around the Windows common control. It's not changed much since it was introduced. – Ken White Sep 23 '15 at 18:21
  • I was trying out on Windows XP. Now I tried the same on Windows 7 and it pops a message with red cross - `Failed to set calendar date or time`. Again, if I remove the line in `FormCreate` it works perfectly fine, or if I set the date to Date + 1. I will have to conclude this is some kind of bug in Delphi 2010. – Coder12345 Sep 23 '15 at 18:34
  • In my D2010 it also refuses to work (I get exception "Failed to set calendar date or time"). If I replace 0.9999999 with 1 then it works fine. So it seems like there's a strange thing going on in D2010 compared to the other versions. – HeartWare Sep 23 '15 at 18:35
  • I also found something else. If open the dropdown and select Today's date (even if it is selected already!) - after that, clicking the button WORKS - then it works just fine from that point on no matter what date I set. Go figure! – Coder12345 Sep 23 '15 at 18:37
  • `Trunc(Date) + 0.99999999999` can be simplified to `EndOfTheDay(Date)`, which just calls `RecodeTime(Date, 23, 59, 59, 999)`. Even if you use `Trunc()` or `DateOf()` and then add a time to that value, I would still suggest using `EncodeTime(23, 59, 59, 999)` instead hard-coding `0.99999999999`. – Remy Lebeau Sep 24 '15 at 02:21
  • @Remy: I was not advocating using the hard-coded value; I was simply demonstrating that the time portion was the cause of the problem. – Ken White Sep 24 '15 at 02:34
  • @Remy: Edited to include the suggestions from your comments for future readers. Thanks. – Ken White Sep 24 '15 at 03:04
2

There is no big difference between adding 1 and 0.99999, as 1 you would increment one day to the date, and 0.999999 it would be almost one day (something like 23:59:59:xxx).

Try the following (you have to include DateUtils in the uses list):

DTPicker.MaxDate := IncSecond(Date);
Alisson Reinaldo Silva
  • 10,009
  • 5
  • 65
  • 83
  • 1
    Thank you for your suggestion, I have tried that one too but it does not work either. It looks like Delphi 2010 bug. – Coder12345 Sep 23 '15 at 18:21