Time Inquiry is a world time-zone lookup program that lets users find the corresponding local time for any city or country when given a known time at another location. It loads a companion machine code file (“time.C1”) into memory above address 32550 and uses a Z80 machine code routine (POKEd in from DATA statements at line 9030) to perform a binary search or sequential scan through a packed city/time-zone database stored in high RAM. City entries are encoded as a numeric time-zone code prefix concatenated with the city name and terminated by an asterisk (ASCII 42). The program supports adding new cities to the database via menu option 2 and can save both the BASIC program and the updated code/data file back to tape. Input validation routines check for alphabetic city names and numeric hour values in the range 0–24, rejecting fractional hours other than half-hours (converted to display as “.30”).
Program Structure
The program is organized around a central menu at line 350 with four options dispatched via GO TO VAL x$*2000 (line 460), routing to:
2000– Time inquiry (main feature)4000(via4060) – Add cities/countries to the database6020– Information/help text8000/9900– Save to tape
Initialization (lines 10–80) loads the machine code data file, POKEs the Z80 routine from DATA, sets up display attributes, and draws decorative border rectangles using PLOT/DRAW. The subroutine at 9000–9010 RESTOREs to line 9030 and POKEs 68 bytes of machine code into addresses 32552–32619.
Variable Conventions
Several variables are pre-initialized at line 20 using idiomatic ZX Spectrum BASIC to avoid repeating numeric literals and to save memory:
| Variable | Value | Meaning |
|---|---|---|
oo | 0 (NOT PI) | Zero / false |
oa | 1 (PI/PI) | One / true |
ob | 2 | Two (max consecutive spaces) |
oj | 10 | Column/row offset |
ol | 12 | Noon pivot value |
w | 350 | Menu line number |
v | 3000 | Screen-clear scroll subroutine line |
l | 32658 | Base address of city database in RAM |
Using NOT PI for 0 and PI/PI for 1 is a well-known memory-saving idiom on this platform, avoiding storage of the numeric literal in the program line.
Machine Code Usage
Lines 9000–9034 POKE a 68-byte Z80 routine into RAM starting at address 32552. The routine is invoked at line 2530 via LET b= USR 32552. Before the call, lines 2460–2500 set up a search string in RAM at 32513, and patch the machine code at addresses 32604–32607 with the database pointer p (split into low and high bytes). After the call, lines 2540–2590 read the result address from PEEK 32617/32618 and walk the found record to extract the numeric code (up to 5 characters, digits only) into b$ and the city name into d$, stopping when a * terminator (ASCII 42) is found.
The companion file “time.C1” is loaded at line 10 as a CODE block starting at 32656, which stores the city database. The current end-of-database pointer p is reconstructed at line 15 from a two-byte little-endian value PEEKed from addresses 32656/32657.
Database Format
Each city record in the CODE block is formatted as a numeric time-zone offset (e.g., 7) immediately followed by the city name (e.g., NEW YORK), terminated by an asterisk (*, ASCII 42). The time-zone number represents the local hour when Greenwich Mean Time is 12:00 noon, functioning as an absolute UTC offset expressed on a 24-hour clock. New records are appended by the menu-option-2 path (lines 4060–4200), with p maintained as a running pointer and persisted back into addresses 32656/32657.
Time Calculation
The core arithmetic (lines 2170–2330) computes the time difference as:
- Extract origin city offset
a = VAL a$and destination offsetb = VAL b$from the database. - Compute displacement
t = b - a + fwherefis the user-entered known hour. - Wrap
tinto the 1–24 range, then classify as A.M., P.M., NOON, or MIDNIGHT usingol(12) as pivot.
Line 2326 handles half-hour time zones: if t - INT t <> 0, it sets display suffix r$ to "0 " and adds 0.3 to the integer part of t to produce a display like 7.30 instead of 7.5. This is a practical workaround for displaying fractional hours since the platform’s PRINT would otherwise show 7.5.
Input Validation
Two validation subroutines are used:
100–180: Validates a city/country name. Allows uppercase letters A–Z (ASCII 65–90), spaces, commas, and periods. Rejects strings with more than one consecutive space (qcounts spaces; ifq=2, branches to320). Invalid input triggers an error message at line325.240–310: Validates a numeric hour. Allows digits and one decimal point; rejects values outside 0–24 or non-integer values (line302). The slash character (/, ASCII 47) is explicitly excluded despite being in the digit range check.
Screen Management
The subroutine at line 3000 scrolls the screen by printing 32 spaces (e$, dimensioned at line 80) from row 21 up to row oj (10) in a FOR loop with STEP -1, effectively clearing lines without a full CLS. The variable v=3000 is used throughout as GO SUB v for this purpose.
Notable Anomalies
- Line
2165testsIF LEN A$=0(uppercaseA$) but setsA$="0"; however, the origin city data was stored in lowercasea$at line2020. On this platform uppercase and lowercase variable names are distinct, so this guard may not function as intended if the origin city lookup populateda$rather thanA$. - Line
2210modifiesf(subtracts 12) after it has already been used to computet, which could affect the display label consistency in edge cases but does not alter the already-computed result. - Lines
3100–3140appear to be a diagnostic/debugging utility left in the listing: they scan RAM from address 37380 onward and print raw memory contents. Line3130is commented out withREM. - Line
4000is referenced byGO TO 4000at line4140but does not appear in the listing; the add-city entry point visible is4060. This is a non-existent line reference. - The
INKEY$loop at line2370–2380has a subtle logic issue: line2370waits for a non-empty keypress, but line2380then re-readsINKEY$, which may already be empty by the time it executes, causing “N” to never be detected reliably. A stored variable for the keypress would be more robust. - Line
9910doesGO TO ol, i.e.,GO TO 12, a non-existent line — standard technique to halt after saving.
Source Code
1 REM TIME INQUIRY
2 REM George Chambers
3 REM 14 Richome Court
4 REM Toronto,Ont. M1K 2Y1
10 CLEAR VAL "32550":LOAD "time.C1"CODE
15 LET p= PEEK VAL "32656"+ VAL "256"* PEEK VAL "32657"
20 LET oo= NOT PI:LET oa= PI/ PI:LET ob=2:LET oj= VAL "10":LET ol= VAL "12":LET w= VAL "350":LET v= VAL "3000":LET l= VAL "32658"
30 BORDER VAL "5":INK oo:PAPER VAL "5":CLS
40 GO SUB VAL "9000"
50 PRINT AT VAL "3",oj; PAPER VAL "6";"TIME INQUIRY"; PAPER VAL "5";,, TAB VAL "7"; PAPER VAL "6";"By George Chambers"
60 INK oa:PLOT oo, VAL "108":DRAW oo, VAL "62":DRAW VAL "255",oo:DRAW oo,-62:DRAW -255,oo
70 INK ob:PLOT VAL "8", VAL "114":DRAW oo, VAL "50":DRAW VAL "238",oo:DRAW oo,-50:DRAW -238,oo:INK oo
80 DIM e$(32)
90 GO TO w
100 LET q=oo
110 FOR n=oa TO LEN x$
120 IF x$(n) <>" " THEN LET q=oo
130 IF x$(n)=" " THEN GO TO VAL "150"
135 IF x$(n)= CHR$ VAL "46" OR x$(n)= CHR$ VAL "44" THEN GO TO VAL "150"
140 IF x$(n)< CHR$ VAL "65" OR x$(n)> CHR$ VAL "90" THEN GO TO VAL "320"
150 IF x$(n)=" " THEN LET q=q+oa
160 IF q=ob THEN GO TO VAL "320"
170 NEXT n
180 RETURN
240 LET q=oo
250 FOR a=oa TO LEN x$
260 IF x$(a)< CHR$ VAL "46" OR x$(a)> CHR$ VAL "57" OR x$= CHR$ VAL "47" THEN GO TO VAL "325"
270 IF x$(a)= CHR$ VAL "46" THEN LET q=q+oa
280 IF q=ob THEN GO TO VAL "325"
290 NEXT a
300 IF VAL x$> VAL "24" OR VAL x$<oo THEN GO TO VAL "325"
301 LET x= VAL x$
302 IF x <> INT x THEN GO TO VAL "320"
310 RETURN
320 PRINT ,, TAB VAL "10";x$
325 PRINT AT VAL "18",oa; FLASH oa;"YOU HAVE ENTERED INVALID DATA"; FLASH oo
330 PRINT ,,"Please press any key to restart"
340 IF INKEY$="" THEN GO TO VAL "340"
350 GO SUB v:PRINT AT oj,oo;"This program will provide theproper time displacement for anycountry or city in the world"
380 PRINT ''"1) Time Inquiry"
390 PRINT '"2) To Add Cities/Countries"
400 PRINT '"3) Information"
410 PRINT '"4) To save To Disk"
420 PRINT #1; INK oa;" PRESS A KEY:(1 TO 4)"; INK oo
430 LET x$= INKEY$
440 IF x$<"1" OR x$>"4" THEN GO TO VAL "430"
460 GO TO VAL x$* VAL "2000"
2000 GO SUB v:PRINT AT oj,oo;"First enter the "; INK ob;"name of the city"; INK oo;"or country.";
2010 GO SUB VAL "2400"
2020 LET a$=b$
2030 LET c$=d$
2040 PRINT INK oa;"** ";c$;" **"; INK oo
2050 PRINT ,,"Now enter the "; INK oa;"known hour"; INK oo;" at ",; INK oa;c$; INK oo;" (as a figure","between 1 and 24)";
2060 POKE VAL "23658", VAL "8":INPUT x$
2070 IF x$="" THEN GO TO VAL "2060"
2080 PRINT INK ob;" ** ";x$;" **"; INK oo
2090 GO SUB VAL "240"
2100 LET f$=x$
2120 LET h$="A.M."
2130 IF VAL f$>ol THEN LET h$="P.M."
2135 IF VAL f$=ol THEN LET h$="NOON"
2137 IF f$="24" THEN LET h$="MIDNIGHT"
2140 LET f= VAL f$
2150 PRINT ,,"Next, Enter the "; INK oa;"name of the cityor country"; INK oo;" where you wish thecorresponding time check."
2160 GO SUB VAL "2400"
2165 IF LEN A$=0 THEN LET A$="0"
2170 LET a= VAL a$
2180 LET b= VAL b$
2190 LET t=b-a
2200 LET t=t+f
2210 IF f>ol THEN LET f=f-ol
2220 LET j$="A.M."
2230 IF t> VAL "24" THEN LET t=t- VAL "24"
2240 IF t<oo THEN LET j$="P.M.":LET t=t+ol
2260 IF t>ol THEN LET j$="P.M.":LET t=t-ol
2280 IF t=ol AND j$="A.M." THEN LET j$="NOON"
2290 IF t=ol AND j$="P.M." THEN LET j$="MIDNIGHT"
2305 LET r$=".00 "
2307 GO SUB v
2310 PRINT AT oj,oo;"WHEN IT IS "; INK ob;f;".00 ";h$; INK oo;" AT"
2320 PRINT ' INK ob;c$; INK oo;" THE TIME AT"
2326 IF t- INT t <>oo THEN LET r$="0 ":LET t= INT t+.3
2330 PRINT ' INK ob;d$; INK oo;" WILL BE "; INK ob;t;r$;j$; INK oo
2340 PRINT ''"DO YOU WANT ANOTHER TIME CHECK?"
2350 PRINT ,, TAB oj;"ENTER Y/N"
2370 IF INKEY$="" THEN GO TO VAL "2370"
2380 IF INKEY$="N" THEN CLS :GO TO VAL "8010"
2390 GO TO w
2400 POKE VAL "23658", VAL "8":INPUT x$
2410 IF x$="" THEN GO TO VAL "2400"
2420 GO SUB VAL "100"
2430 LET d$=x$
2440 LET x$=x$+"\::"
2450 FOR x=oa TO LEN x$
2460 POKE VAL "32513"+x, CODE x$(x)
2470 NEXT x
2480 POKE VAL "32606",p- VAL "256"* INT (p/256)
2490 POKE VAL "32607", INT (p/256)
2500 POKE VAL "32604", VAL "146":POKE VAL "32605", VAL "127"
2530 LET b= USR VAL "32552"
2540 LET x= PEEK VAL "32617"+ VAL "256"* PEEK VAL "32618"
2542 IF x=l THEN GO TO VAL "5000"
2543 LET b$=""
2545 LET d$=""
2550 FOR y=x TO x+ VAL "16"
2555 IF y-x>4 THEN GO TO VAL "2570"
2560 IF PEEK y> VAL "44" AND PEEK y< VAL "58" AND PEEK y <> VAL "45" AND PEEK y <> VAL "47" THEN LET b$=b$+ CHR$ PEEK y
2570 IF PEEK y> VAL "64" AND PEEK y< VAL "91" THEN LET d$=d$+ CHR$ PEEK y
2575 IF PEEK y= VAL "32" OR PEEK y= VAL "44" OR PEEK y= VAL "46" THEN LET d$=d$+ CHR$ PEEK y
2580 IF PEEK (y+oa)= VAL "42" THEN RETURN
2590 NEXT y
2690 RETURN
3000 FOR N=21 TO oj STEP -oa:PRINT AT N,oo;e$:NEXT N:RETURN
3100 REM \{17}\{4}To scan names list\{17}\{5}
3110 FOR n=37380 TO VAL "65000"
3120 PRINT n, CHR$ PEEK n
3130 REM IF PEEK (n)=42 THEN PRINT :PRINT (n+1);" ";
3140 NEXT n:STOP
4060 GO SUB v:PRINT AT oj,oo;" Enter the code number and name",,," of the city or country"
4070 PRINT '" (See Instructions)"
4080 INPUT x$
4090 LET a$="*"+x$
4100 PRINT AT VAL "14", VAL "8";e$' TAB oj; INK ob;x$; INK oo
4110 PRINT AT 18,oo;"Press N/L to log this listing or C to correct it"
4120 INPUT x$
4130 GO SUB v
4140 IF x$="C" THEN GO TO VAL "4000"
4150 FOR x=oa TO LEN a$
4160 POKE l+p, CODE a$(x)
4170 LET p=p+oa
4180 NEXT x
4190 POKE l+p, VAL "42"
4195 POKE VAL "32657", INT (p/ VAL "256"):POKE VAL "32656",p-(PEEK VAL "32657"* VAL "256")
4200 GO TO w
5020 GO SUB v:PRINT AT oj,oo;" The name you requested",,," ";d$;" "
5025 PRINT ,," is not in our records"
5030 PRINT ,,"Please select another name."
5040 PRINT ,," If you wish, it is possible toenter additional locations intothis program via Menu item No.2. Check the instructions."
5060 PRINT AT VAL "18",oo;"Press any key to return to Menu"
5070 IF INKEY$="" THEN GO TO VAL "5070"
5080 GO TO w
6020 CLS :PRINT AT oo,oo'"If the requested locality is notstored, you will be advised."
6030 PRINT '"You may add localities to thedata base, if you wish."
6040 PRINT '"An entry consists of the name ofthe city, plus a numerical codeprefix denoting it's time zone."''" (Example) 7NEW YORK"
6050 PRINT '"The code prefix must correspondto the time (as a 24-hour clock)in that locality,when the Green-wich Mean Time is 12 noon."
6060 PRINT '"Note: This program does not copewith Daylight Saving Time."
6300 PRINT INK oa'"Press any key to return to Menu"; INK oo
6310 IF INKEY$="" THEN GO TO VAL "6310"
6320 CLS :GO TO VAL "50"
8000 GO TO VAL "9900"
8010 GO SUB v:PRINT AT oj, VAL "8";" TEMPUS FUGITS "
8020 PRINT ,, TAB VAL "6";" MY,HOW TIME FLIES "
8030 PAUSE oo:STOP
9000 RESTORE VAL "9030"
9010 FOR n= VAL "32552" TO VAL "32619":READ a:POKE n,a:NEXT n:RETURN
9030 DATA 42,92,127,237,75,94,127,17,2,127,26,237,177,226,96
9031 DATA 127,19,26,254,143,202,71,127,237,161,202,56,127,195,47
9032 DATA 127,34,92,127,43,126,254,42,202,84,127,195,74,127,34
9033 DATA 105,127,237,67,94,127,201,44,142,228,3,33,146,127,1
9034 DATA 1,0,195,84,127,34,142,0,0
9890 STOP
9900 SAVE "time.B1" LINE 1:SAVE "time.C1"CODE VAL "32656",p
9910 GO TO ol
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

