File: STORTIME July 17, 1989 Saving Time and Date as a Number Data logging frequently requires time and date stamping. This data is usually saved as a string. However, this method takes up storage space. Also, determining the time between two periods can be cumbersome. This note shows a method of saving the date and time as a 2 byte number. Saving data in this format makes it handy when using the 8560 RAM disk card. Representing time as a number consists of multiplying components of the current time times some factors. The zero count is at midnight (00:00:00.00) while the maximum count is one minute before (23:59:59.99). One way to represent the time is to use the following formula: hr*3600 + min*60 + sec A numerical representation for the time 1:35:17.34 PM would be: 13*3600 + 35*60 + 17.34 = 48917.34 Hours must be represented in a 24 hr clock format. Octagons CAMBASIC II, STD Basic II, or STD Basic III POKE! command can be used to save time to memory while PEEK! can return it. An example program converting time and storing it is shown below: 10 A$ = TIME$(0) .. get time 20 D = VAL(LEFT$(A$,2))*3600 + VAL(MID$(A$,3,2))*60 + VAL(RIGHT$(A$,5)) 30 POKE! D,address Remember that POKE! requires 4 bytes of memory to store a floating point number. Retrieving the time and converting it to a displayable number consists of multiplications. For this example, hours, minutes, and seconds will be left as numerical components. Note integer divide is denoted by a back slash (\). 100 D = PEEK!(address) 110 HR = D\3600 .. hours 120 MN = (D - HR*3600)\60 .. minutes 130 SC = D - HR*3600 - MN*60 .. seconds & hundreds Hours, minutes, and seconds can be converted to strings if necessary by using the STR$ function. When using this function, a space will be added before the number. This is because there is an implied '+' sign before it. To get rid of the space, use the LEN function to get the string length and the RIGHT$ to get all but the last character. The following example illustrates this: 150 SC$ = STR$(SC) ..convert number to string 160 SC$ = RIGHT$(SC$,LEN(SC$)-1) .. take out left space Saving time as a floating point number requires 4 bytes. For some applications, memory requirements may make this excessive. Storing time to the second as a 16 bit number is more efficient but is not possible, however. The maximum count of a 16 bit number is 65535 while the number of seconds in a day is 86400. One "solution" is to ignore seconds when saving the time. Some applications require only knowing to the minute the data of an event. Converting time to a 16 bit number is similar to above: 200 A$ = TIME$(0) .. get time 210 D = VAL(LEFT$(A$,2))*60 + VAL(MID$(A$,3,2)) Line 210 above gets the hours and minutes and converts it to a number from 0 to 1439. Time value D can then be stored with a DPOKE or DOUT statement and retrieved with DPEEK or DINP functions. Data can also be stored to the 8560 RAM disk. See the data logging application note (LOGGER) for software examples. Converting the above value D into printable hours and minutes is similar to the example in lines 100-130. 330 HR = D\60 .. convert hours 340 MN = D - HR .. convert minutes Some situations require that the exact seconds and hundreds be recorded to the 8560 card in addition to hours and minutes. Here again, data can be converted into a decimal format suitable for storing as a 16 bit number. Simply take the seconds and hundredths part of the time and multiply it by 100. Seconds and hundreds can then be stored as a 16 bit number. The largest number stored will be 5990. The example below extracts seconds and hundreds of a second and converts it to an integer number. 250 D = VAL(RIGHT$(A$,5))*100 To convert back to the correct units of time, just divide D by 100. The date can be saved as a 16 bit number, since there are 36525 days to a century. The examples shown here convert the date into a LOTUS 123 @DATE compatible number. Dates up to June 4, 2079 may be stored using a two byte format. There is bit more involved to converting a date to a number than there is with time. The largest problem is in the changing number of days per month. To complicate things, February gains a day every 4 years. A way to get around this problem is to use assign the days of the month to an array using DATA statements. The initialization subroutine is shown below: 400 DIM MD(13) ..declare array 410 FOR N = 1 TO 12 ..loop to read in data and 420 READ MD(N) .. initialize array 430 NEXT 440 RETURN 450 DATA 31,28,31,30,31,30,31,31,30,31,30,31 This subroutine is necessary regardless of whether you are converting a date to a number or visa versa.The following program converts the current date to a 2 byte integer: 500 A$ = DATE$(0) .. get current date 510 YR = VAL(RIGHT$(A$,2)) * 365.25 .. extract year 520 IF YR-INT(YR)=0 THEN MD(2)=29 ELSE MD(2)=28 ..leap year 530 D = INT(YR) ..set year 540 MO = VAL(LEFT$(A$,2)) .. get month 550 FOR N = 1 TO MO .. loop to add in days 560 D = D+MD(N-1) .. add in completed months 570 NEXT 580 D = D+VAL(MID$(A$,4,2)) .. add in day of month 590 INC D .. adjustment factor for LOTUS 123 The number of days since January 1, 1900 is in variable D. If you are using this routine without the DATE$ function (i.e. operator input), make sure you follow the date format mm/dd/yy. Entering in a 2 as opposed to a 02 will cause an error. Line 520 adjusts February for leap year. To convert the number of days back to month, day, and year, use the following program: 600 DEC D ..adjustment factor 610 YR = D\365.25 .. get year 620 IF (D/365.25) - YR = 0 THEN MD(2) = 29 ELSE MD(2)=28 630 DS = D - INT(YR*365.25) .. number of days into year 640 MO = 1 .. initialize month 650 IF DS < MD(MO) THEN 690 ..add in months 660 DS = DS - MD(MO) 670 INC MO 680 GOTO 650 690 .. your program continues The program in lines 600-690 returns the year (YR), month (MO), and day (DS) as three separate variables. Note in line 610 the integer divide is denoted by a backslash. Line 620 adjusts for leap year. Note the floating point divide.