How to make a countdown program in one line of Delphi code

Theo Hupkens

You can make a countdown program like Y2100.exe if you have Delphi. In its simplest version you only have to type one line of program code yourself, all other code is generated automatically by Delphi. The program described here counts down to January 1, 2100. You can modify this program to use any other date (marriage, retirement, reaching age of consent…). Also, you could modify the program to count down in days, hours or minutes instead of seconds.

To make this program do the following: Create a new application and place any component (Label, Edit, Memo, Button) that can show text. Alternatively you can use the Caption of the Form. I have used an Edit component. Set FormStyle to fsStayOnTop. Place a Timer component on the Form and double-click on it. Delphi generates the code for the OnTimer event handler. Place the following statement between the begin and end statement

Edit1.Text := Format (' 8.0n', [EncodeDate(2100, 1, 1) - Now) * 24 * 60 * 60])

If you don't use an Edit component, or use a different name, you should modify this statement accordingly. Save/compile and your program is ready!

The magic text '8,0n' is a format specifier*: the 8 means that at least 8 places for the integral part of the displayed number are reserved. If you want the displayed number to shift to the left when the number of digits becomes smaller, you should use fewer places than this. With long numbers, the above way of formatting is very practical, because of the thousands separators. Which thousands separators will be used? That depends on how your Windows is configured. In America normally comma's are used, in parts of Europe points are more common. But Windows allows you to choose other separators as well, so if you like to see dollars, that's also possible. You can change the Windows set-up while the program is running, so you can see the effect immediately:

Explanation of how this program works:

The function Now returns a floating point number of which the integral part contains the number of days that have passed since a certain date. The fraction of the current day that has passed is stored in its fractional part. The function EncodeDate(Year, Month, Day) is similar to Now, but returns the number of days that will have passed at the specified date. So EncodeDate(2100, 1, 1) - Now is the number of days between January 1, 2100 and now. By multiplying this number by * 24 * 60 * 60, the number of seconds is obtained. This number must be rounded to the nearest integer, because the timer doesn't tick exactly at seconds boundaries.

If you use a format specifier like '8.1n', you can see that the timer interval is not exactly 1 second! Sometimes the rounding can result in a counter that is a little irregular, if you find this annoying you could try using a smaller timer interval (for instance 200) -- with the original format string.

Is there a Y3K millennium bug?

I tried the next millennium change (3000) and the program seemed to work perfectly (Delphi 4).

Daylight Saving Time

There is no obvious way to determine whether one of the two dates is in a period that daylight saving time is 'active'. So if you run the counter during the daylight saving period (and your computer time reflects this) and the final date is not in a daylight saving period you should add 3600 to the reading. (You cannot know this for sure if the final date lies far ahead). If the opposite is true you should subtract 3600.

Hint

It is also possible to place the result on the Windows task bar. To do this, use an empty form and place the timer component on it. Set the property WindowState to wsMinimized (and FormStyle not to fsAlwaysOnTop). Replace the above statement by something like

Application.Title := 'Still ' + IntToStr(round( (EncodeDate(2100, 1, 1) - Now) * 24 * 60 * 60)) + 'seconds to go.' If the displaced number does not fit in the reserved space at the task bar, place your mouse above the number to see it all!

 

*Note that Delphi has many more ways to format numbers. For instance FloatToStr(..) or IntToStr(round(..)). You could even use FormatFloat(',0', (EncodeDate(2100, 1, 1) - Now) * 24 * 60 * 60).

Last modified: August 7, 2000