# Counting down to the end of the world

March 22, 1999
by Pat McClellan

Dear Multimedia Handyman,

I'm trying to create a countdown clock for a screensaver that looks for the year 2000 and consequently calculates how long we have left ie: 277 days : 12 hours : 13 Mins etc. I would also like to then make a sprite move along a line in accordance with the present date.

Can you help me? I'm a novice with Director 7.

Colin Usher

Dear Colin,

Glad to see you're using Director 7. That means that we can use a Lingo function that is new to D7, the systemDate. This function returns the date (as set in the user's computer) in a predictable format that is capable of math functions. For example, the systemDate will return today's date, in the format (yyyy,mm,dd). That year in 4 digits, month in 2 digits, and day in 2 digits. That means that this format does not vary between US and European displays. So, we can set a variable to the last day of this century (1999,12,31), and then subtract the systemDate to get the number of days left.

The next step is a little more complicated because D7 does not have time functions that are as useful as the systemDate. For time, use "the long time" to return a string which contains the hour, minute and second, as well as AM or PM. For example:

```put the long time
-- "10:51:36 AM"
```

We'll need to separate the hour, minute and second from this string. It's fairly easy to do. First, I'll set "the itemDelimiter" to be the colon. Then, I can refer to the hour as "item 1 of the long time". Minutes will be item 2. Seconds is trickier because item 3 is anything after that second colon, so the AM or PM gets included. So, before setting seconds = item 3, I have to delete these last 3 chars of the time (space, + AM or PM).

With the current hour, minute and second separated out, we can do our math calculations. Since we don't know if the user is on a 12 or 24 hour clock, we'll have to check for that with the AM/PM, and whether the hour is greater than 12. So, if the time contains AM or if the hour is greater than 12, we know we're safe subtracting the hour from 23 to get hours left. Otherwise, it must be afternoon or evening, and the displayed hour is less than 12 so we're on a 12 hour clock. That means we need to subtract the current hour from 11 to get hours left (in this day.)

Minutes and seconds are much easier. Subtract the current minutes from 59 to get minutes left in this hour, and subtract the current seconds from 59 to get the seconds left in this minute. NOTE: You use 59, because you would never want to display 60 minutes left. Instead, you'd display 1 hour and 00 minutes left. Same for seconds, and 23 or 11 for days.

The final step is simply to plug the values into a field or text cast member. Here's the behavior for the countdown.

```-- Millennium Countdown Behavior
-- Free use for readers of Director Online
on exitFrame me
set daysLeft = date(1999,12,31) - the systemdate
set the itemDelimiter to ":"
set timeNow = the long time
set theHour = item 1 of timeNow

set the floatPrecision = 0

if timeNow contains "AM" or theHour > 12 then
set hoursLeft = string(23 - theHour)
else
set hoursLeft = string(11 - theHour)
end if
if hoursLeft contains "." then delete ¬
the last char of hoursLeft
if the number of chars in hoursLeft < 2 ¬
then put "0" before hoursLeft

-- crop off the AM/PM part
set totalChars = the number of chars in timeNow
delete char (totalChars - 2) to totalChars of timeNow

set theMinute = item 2 of timeNow
set minutesLeft = string(59 - theMinute)
if minutesLeft contains "." then delete the ¬
last char of minutesLeft
if the number of chars in minutesLeft < 2 ¬
then put "0" before minutesLeft

set theSecond = item 3 of timeNow
set secondsLeft = string(59 - theSecond)
if secondsLeft contains "." then delete the last ¬
char of secondsLeft
if the number of chars in secondsLeft < 2 then ¬
put "0" before secondsLeft

-- put it into the display
put daysLeft && "days" & RETURN into member "display"
put hoursLeft && "hours" & RETURN  after  member "display"
put minutesLeft && "minutes" & RETURN  after  member "display"
put secondsLeft && "seconds" after  member "display"

end
```

Having the pointer move across a timeline is a little tricky. The key is that you have to figure out a "factor" which converts the number of increments where the pointer could be positioned (365 in our case) into the range of pixels (146 in the case of this demo).

You'll notice that I only bother to change the pointer's position on beginSprite. That means that it won't move if you happen to be running the program when the day changes. It would only move less than a half a pixel per day anyway, so I figured that it's ok to update the position only when the sprite first appears. If you want, you could have it update on every exitFrame, but that sure seems like a waste of processing.

```property pRange, pTimeLineSpriteNum, pRight, pFactor, pSprite

on getPropertyDescriptionList me
set pdlist to [:]
addprop pdlist, #pRange, [#comment:"Number of increments", ¬
#format:#integer, #default:365]
SpriteNum", #format:#integer, #default:1]
return pdlist
end getPropertyDescriptionList

on beginSprite me
set timeWidth = the width of sprite pTimeLineSpriteNum
set pFactor = timeWidth/float(pRange)
set pRight = the right of sprite pTimeLineSpriteNum
set pSprite = the spriteNum of me
set daysLeft = date(1999,12,31) - the systemdate
set the locH of sprite pSprite = pRight - (daysLeft * pFactor)
put pRight
put daysLeft
put pFactor
end
```

Hope that helps with your project!

Patrick McClellan is Director Online's co-founder. Pat is Vice President, Managing Director for Jack Morton Worldwide, a global experiential marketing company. He is responsible for the San Francisco office, which helps major technology clients to develop marketing communications programs to reach enterprise and consumer audiences.