JES: Just Educational Services

Jonathan E. Sisk's
Pick/BASIC: A Programmer's Guide

Chapter 7 - Data Conversion and Print Masking

Click to enlarge

In this example. the principles of converting and formatting are covered. Topics, statements, and functions covered include print (format) masking, GOTO, ICONV, OCONV(D,MT), SPACE, DATE(), TIME(), and TIMEDATE().

Enter Program Example 5, shown in Fig. 7-1.

THE ICONV FUNCTION

The ICONV function is used to convert data from its external format to its internal format. To explain external versus internal is relatively easy; external format is the form in which a piece of data is readable to humans; internal format, as briefly introduced in Chapter 1 , most often makes sense only to the computer.

Notice that the ICONV function has two arguments. The first argument is the string of numbers or characters that are to be converted. The second argument is the conversion code. One example of a conversion code is the date, or "D" conversion:

027 INTERNAL.BIRTHDAY = ICONV(BIRTHDAY,"D")

The Pick System stores dates in an internal format which is a number representing the number of days that have elapsed since December 31, 1967. (Day zero on the Pick Calendar). Every night at midnight, a counter is incremented by 1. Consequently, if you were to find an item in a file which had the number 7777 stored in an attribute, it could be a date in internal format, or an amount of money, or a street address. The only person who knows for sure is the programmer who put it there.

Fig. 7-1. Program Example 5.


001 * EX.005
002 * PRINT MASKING, INTERNAL AND EXTERNAL CONVERSIONS
003 * mm/dd/yy: date last modified
004 * JES: author's initials
005 *
006 PROMPT ":"
007 *
008 * GET FIRST AND LAST NAME
009 *
010 PRINT
011 PRINT "ENTER YOUR FIRST NAME :
012 INPUT FIRST.NAME
013 IF FIRST.NAME = "QUIT" THEN STOP
014 *
015 PRINT
016 PRINT "ENTER YOUR LAST NAME " :
017 INPUT LAST.NAME
018 IF LAST.NAME = "QUIT" THEN STOP
019 *
020 * GET BIRTHDAY
021 *
022 LOOP
023 PRINT
024 PRINT "ENTER YOUR BIRTHDAY (MM-DD-YY) " :
025 INPUT BIRTHDAY
026 IF BIRTHDAY = "QUIT" THEN STOP
027 INTERNAL.BIRTHDAY = ICONV(BIRTHDAY,"D")
028 UNTIL INTERNAL.BIRTHDAY # "" DO
029 PRINT "SEPARATE MONTH DAY AND YEAR WITH DASHES!"
030 REPEAT
031 *
032 * NOW LET'S SHOW OFF
033 *
034 PRINT
035 PRINT "HELLO THERE " : FIRST.NAME
036 PRINT
037 PRINT "THE CURRENT DATE IS ": OCONV(DATE(),"D2/")
038 PRINT "THE CURRENT TIME IS ": OCONV(TIME(),"MTH")
039 PRINT
040 PRINT "IF YOU WERE BORN ON " : BIRTHDAY :
041 PRINT ", THEN THE DAY OF THE WEEK WAS " :
042 PRINT OCONV(INTERNAL.BIRTHDAY,"DWA")
043 PRINT "THIS WAS DAY " : OCONV(INTERNAL.BIRTHDAY,"DJ") :
044 PRINT " OF THE YEAR "
045 PRINT
046 PRINT "THAT MAKES YOU " : DATE() - INTERNAL.BIRTHDAY : " DAYS OLD"
047 *
048 * GET NUMBER FOR SPACE TEST
049 *
050 PRINT
051 PRINT "LET'S TEST THE SPACE FUNCTION."
052 LOOP
053 PRINT "ENTER A NUMBER BETWEEN 5 AND 20 " :
054 INPUT YOUR.NUMBER
055 UNTIL NUM(YOUR.NUMBER) OR YOUR.NUMBER = "QUIT" DO REPEAT
056 IF YOUR.NUMBER = "QUIT" THEN STOP
057 *
058 * SHOW FIRST AND LAST NAME WITH SPACES BETWEEN
059 *
060 PRINT
061 PRINT "HERE'S YOUR NAME WITH " : YOUR.NUMBER: " EMBEDDED SPACES"
062 PRINT FIRST.NAME: SPACE(YOUR.NUMBER) : LAST.NAME
063 *
064 * SHOW TIMEDATE() AND MASKING
065 *
066 PRINT
067 PRINT "HERE' S TIME AND DATE LEFT JUSTIFIED IN 40 SPACES"
068 PRINT "*" : TIMEDATE() "L#40" : "*"
069 PRINT
070 PRINT "HERE'S TIME AND DATE RIGHT JUSTIFIED IN 40 SPACES"
071 PRINT "*": TIMEDATE() "R#40": "*"
072 END

Users see only the output of all the work performed by the computer. Now that you are the programmer, you need to know what type of data will be received in a program, because you have to make sure that the data is converted to its proper internal format. Otherwise, many strange things may occur.

With this first example, the ICONV statement is used to take the BIRTHDAY variable and converts it with the D (for "Date") conversion. This takes care of the "internal number of days" calculation, so it produces one of two results: Either the number of days since 12/31/67 if the date is "valid," or a null if it is determined to be "invalid." In the Pick System, a date is considered valid if it is received with consistent delimiters between the month, day and year. A date is invalid if the conversion fails.

Here are some valid dates for the date conversion function:

1-1-97
1.1.97
01/01/1997
01 JAN 97
1JAN1997

(Note that leading zeros are optional.)

Now here are two invalid dates for the date conversion function:

1197
010197

The reason they are considered invalid is that they already appear to be in internal format.

The same set of conversion codes that are available to ACCESS are also available to PICK/BASIC. The conversions used most often are covered in this book.

Here's what happens when a date is convened from its external format to its internal format:


External      Date        Result
Format        Conversion  Provided
12/12/97      D           10939
12 DEC 1997   D2          10939

Figure 7-2 illustrates the various date conversions that may be applied to internal dates.


There are many benefits in storing dates this way. First, it makes sorting easier because it's easy to compare two numbers to see which is greater. Second, it makes performing calculations on dates much easier. This might not seem significant until you have to figure out your own algorithm for calculating what 90 days is from any particular date. Finally, it is more efficient, in terms of storage, than its external counterpart.

On line 28, the contents of the variable, INTERNAL.BIRTHDAY, is examined to determine if it is null, which indicates that the internal conversion process failed. A valid external format is one in which the month, day, and year are each separated by any consistent non-numeric character. If the variable is determined to be null, then the response entered is definitely not a date, so a message is displayed and the birthday is again requested.


Internal                  Date
Format                    Conversion         Result

10939                     D                  12 DEC 1997
10939                     D2/                12/12/97
10939                     D2-                12-12-97
10939                     D-                 12-12-1997
10939 (julian date)       DJ                 346
10939 (numeric month)     DM                 12
10939 (alpha month)       DMA                DECEMBER
10939 (numeric day/week)  DW                 5
10939 (alpha day/week)    DWA                FRIDAY
10939 (4 digit year)      DY                 1997
10939 (quarter)           DQ                 4

Fig. 7-2. Sample external date conversions.


On the other hand, if there is a value in INTERNAL.BIRTHDAY, then program execution continues from line 31.

THE OCONV, DATE, AND TIME FUNCTIONS

The OCONV statement is exactly the opposite of the ICONV statement. It takes data in its internal format and converts it to external format, using the same set of conversion codes available to the ICONV function and the ACCESS retrieval language:

037 PRINT "THE CURRENT DATE IS ": OCONV(DATE(),"D2/")

A reserved system function, called DATE(), retrieves the current system date in its internal format. On line 37, the system date is retrieved and output converted using the "D2/" conversion. This takes the date and formats it in the form mm/dd/yy. Note for European readers: Many versions of Pick allow the date format to be "toggled" to European format, which this conversion formats as dd/mm/yy.

Time, like dates, is also stored in an internal format representing the number of seconds that have elapsed since midnight. This provides many of the same benefits as the date conversion, particularly with doing calculations:

038 PRINT "THE CURRENT TIME IS ": OCONV(TIME(),"MTH")

Figure 7-3 illustrates what happens when a time is converted from its external format to its internal format, as well as the various time conversions that may be applied to internal times.

On Line 38 of the example, the message, "THE CURRENT TIME IS ", displays, followed by the current time in the format hh:mmAM or hh:mmPM, depending on whether or not you are doing this before or after lunch.


External
format        Conversion      Result
12:30         MT              45000
10:00         MT              36000

Internal
format        Conversion      Result
61200         MT              17:00
61200         MTS             17:00:00
61200         MTH             05:00PM
61200         MTHS            05:00:00PM

Fig. 7-3. Time conversions.


Using OCONV with Dates

Once a date is converted to its internal equivalent, it may be output formatted with any of the many types of date conversions. This statement takes the INTERNAL.BIRTHDAY variable and converts it to the external format using the DWA conversion, which spells out the day of the week:

042 PRINT OCONV(INTERNAL.BIRTHDAY,"DWA")

Line 43 does the same with the DJ conversion, which returns the date in its Julian date format. The Julian date is the sequential number of the day within the year. For example, January 15 is the 15th day of the year and February 15 is the 46th day. This is how you may calculate the number of shopping days left until Christmas. Just for fun, the program to do just that is provided in Appendix C. It's called EX.005A.

Performing Calculations with DATE

On line 46, your age in days is calculated and displayed. This is done by taking the internal system date, DATE(), and subtracting your birthday, which is stored in INTERNAL. BIRTHDAY. Incidentally, days before December 31, 1967 (day zero on the Pick calendar) are stored internally as negative numbers.

THE SPACE FUNCTION

The SPACE function is used to produce or display a string of spaces. The number of spaces is determined by the result of the numeric expression, in this case, the number you entered into YOUR.NUMBER:

062 PRINT FIRST.NAME: SPACE(YOUR.NUMBER) : LAST.NAME

If the value of YOUR. NUMBER were 15, for example, the statement would be equivalent to:

PRINT SPACE(15)

This prints 15 spaces at the current cursor or printer position.

The SPACE function comes in handy when formatting output on reports and screens. (Another way of doing output formatting is through the use of print masks, to be discussed shortly.)

THE TIMEDATE FUNCTION

When the TIME( ) and DATE( ) functions were discussed earlier, it was noted that both of these functions retrieve their respective current values in internal format. The TIMEDATE( ) function retrieves the current system time and date in its external format.

For example, the instruction:

PRINT TIMEDATE()

produces output in the form:

10:17:36 12 DEC 1997

Line 68 of Program Example 5 uses it in this form:

068 PRINT "*" : TIMEDATE() "L#40" : "*"

PRINT (FORMAT) MASKING

Print masking is the process of taking an expression and presenting it in a particular output format, typically either left- or right-justified. Print masks are composed of several elements: the justification indicator, a "fill" or "pad" character, and a number to indicate the length of the output.

068     PRINT "*" : TIMEDATE() "L#40" : "*"

Together, these three elements comprise a print mask. The print mask immediately follows the output-producing expression that it is to format.

The justification is usually either an L for left-justified or R for right- justified. Some systems additionally support extra justification codes, such as D for date justification, which effectively produces the same result as an OCONV function; only the L and R are covered here.

The second of the three elements is the single character to "pad" the output. There are three "standard" characters available:

*  Fills output with asterisks.
#  Fills output with blanks.
%  Fills output with zeros.

The third and final element of the print mask expression is an integer number which indicates the maximum length of the output.

On line 68, an asterisk (*) is displayed. This is to indicate the beginning position of the output. It is immediately followed by the current system time and date, produced with the TIMEDATE( ) function. Notice that the output is displayed left-justified in a field of 40 blanks and followed immediately by another asterisk to indicate the "end" of the output.

This appears as:

*08:15:34 12 DEC 1997                  *

On line 71, an asterisk is displayed, followed by the current system time and date, right-justified in a field of 40 blanks, followed by another asterisk. This appears as:

*                  08:15:34 12 DEC 1997*

Here's a very important note about print masking: Did you notice that there is no character, other than an optional space, between the expression being printed and the mask expression? This is extremely important, because it directs the program to treat the "first" expression as an object of the "second" expression, which is considered a "masking" expression. Shown below are correct and incorrect use of print masking:

PRINT "*" : "HI THERE " "L#15" : "*"

outputs

*HI THERE	*

whereas, the statement:

PRINT "*" : "HI THERE" : "L#15" : "*" 

outputs

*HI THEREL#15*

Not exactly what you wanted ....

The moral of this story is that you may use print masking anytime you need it, but remember to separate the expression being printed from its mask expression with only a space, or, of course, the ever-popular null.


REVIEW QUIZ 5

1) What does internal format mean? What does external format mean?

2) What instruction and conversion code is required to convert a date from its external format to its internal format?

3) Suppose you have a variable called BILL.DATE. In this variable is the value "12-12-1999." How could you find out what day of the week it was? If this bill were due in 30 days, how could you determine when it should be paid?

4) What instruction and conversion prints the system time in its external format?

5) What does the SPACE function DO?

6) What is print masking?

7) What output do the following examples produce?

    PRINT "NAME" "L#15" : "ADDRESS"
    PRINT "123" "R#8": "456" "R#8"
    PRINT "NAME" : "L#15" : "ADDRESS"

8) What function retrieves the current system time and date?

9) How do you really know when you are a programmer?

Previous chapter Next chapter Top

 

Creative Commons License
Jonathan E. Sisk's "Pick/BASIC: A Programmer's Guide" by Jonathan E. Sisk is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at jes.com.