NOTE : THIS DOCUMENT WAS WRITTEN
ORIGINALLY FOR MOBIL’S Y2K COMPLIANCE
EFFORT.
PLEASE SEND YOUR CONTRIBUTIONS TO
SUDARSHANA RAMAKRISHNAN
I will
include it in this page.
Some programs will stop working after an obvious
error message, others will simply stop working. The programs to worry
about won't show symptoms at all. They'll just give incorrect results,
like mis-scheduled events and bad sales projections..
Do you have a problem?
Maybe. If you have dates in your programs,
then probably. Even if you don’t work directly with dates, you may
still be affected by Year 2000 changes if your program uses production
data. There are many databases that will be modified in the next
three years, and unless you're aware of changes by the production teams,
your programs may suddenly ‘crash’.
The bad news for Focus is that lots of old programs used dates as a six digit alphanumeric field. It was easier to continue with the old functions then rewrite and retest with a smarter field. The big job now is to find and convert the old ways to the new ways.
This is the easiest problem to find, and often occurs in reports. It happens when the characters '19' are added to the front of a six-digit date. In Focus, there are three common variations:
Between quotation marks:
-SET &PRINTDATE = '19' | &YMD;
or
COMPUTE PRINTDATE/A8YYMD = '19' | INDATE;
Next to a dialogue manager variable:
HEADING
"Printed: 19&YMD at &TOD"
Next to a spot marker:
ON ENDYEAR SUBFOOT
"Subtotal for 19<ENDYEAR : <TOTDOLLARS"
How to find it:
This strings are fairly easy to find with
a search program. There may be a few extra lines located in cases
where '19' means such things as the first part of an account code, or a
partof
How to fix it:
For Dialogue Manager programs that use today's
date, Focus has new system variables in version 7.0. The general
format is:
&DATEfmt
where 'fmt' can be set to all of the regular 'new date' format options. The limitation on these variables is that they only contain today's date - you can't assign a new value to them. Still, they can be quite useful in reports and screens where &YMD or &DATE are used today.
For TABLE, DEFINE, COMPUTE, and MODIFY, the only way to fix hard-coded 19's is to change the variable to the 4-digit year equivalent. Using the last example above, do this:
DEFINE FILE REVENUE
ENDYEAR2/YYMD = ENDYEAR;
END
TABLE FILE REVENUE
SUM TOTDOLLARS
BY ENDYEAR2
ON ENDYEAR2 SUBFOOT
-*"Subtotal for 19<ENDYEAR : <TOTDOLLARS"
"Subtotal for <ENDYEAR2 : <TOTDOLLARS"
END
2. Dates have special meanings
Does ‘12/31/99’ mean ‘Forever’ or 'end of file' to your program? Do you have a prompt that says "Enter the Year to extract or type '00' to quit"?
How to find it:
To find this problem in your programs, you
could search for the strings '99' and '00'. However, these strings
occurs frequently in Focus programs especially in the EDIT function, so
you would have to search through lots of good code before you found the
problem. It will be more productive to use your experience
with the program to answer this question.
How to fix it:
Let's say you have a database where '12/31/99'
means 'No data found', or 'Invalid entry', or 'Last record in the database'.
Before you can fix it, there are two things you need to think about.
First, what will happen when 12/31/99 becomes a 'real' date? Remember,
that's Friday, a regular business day. If you remove the special
meaning on this field, then you'll suddenly have a database filled with
regular transactions for December 31, 1999. Second, what value can
you use as the new 'special' date? All zeroes? All nines?
You may not be able to create a new fake date if the field is validated
somewhere else. If you have the option of expand the year to four
digits, then your 'special' date could be '12/31/9999', which isn't a bad
solution. If expansion is not an option, then the solution is not
to use 'special' date fields to control the program, in which case you'll
need to change the logic.
If you have a Dialogue Manager program in which entering '00' in a year means 'Quit', then there is no other option except changing the logic. That is, of course, unless you don't plan to do any business until 2001! If you have a prompt where you need to enter '00' and press 'Enter', consider changing the 'Exit' input to an 'X' or a 'Q'.
3. Validations using part of the date
Does your program compare two dates?
For example, does it make sure that the 'shipment date' is not before the
'order date'? Does your program make sure that input is greater than
a certain year? A very common method of validating a 2-digit year
is to make sure it's after a 'reasonable' year like '80'. Unfortunately,
'00' is less than '80', so your data will be rejected.
How to find it:
There is no "industry-standard threshold year"
that you can search for. The low threshold could be most any decade
since 1950. And occasionally, theres' an upper threshold of '99',
which means you might have a program that's going to break at the end of
1998! Generally it's been up to the whim of the programmer to pick
threshold years. Unless you want to search the source code in detail,
you'll need to rely on your personal experience with the program.
The brute force method of finding this problem is to run the program and enter '00' in every available date field, and see if you get an error message.
The other method of finding this problem is to search the code and find it indirectly. Sometimes it will turn up around 'YMD' and 'MDY' . You could also search for a message such as 'invalid year' or 'year must be'.
It might appear like this (MODIFY):
CASE GETDATA
COMPUTE INDATE/A6MDY = ;
CRTFORM
...
COMPUTE
INMONTH = EDIT(INDATE,’99’);
INDAY = EDIT(INDATE,’$$99’);
INYEAR = EDIT(INDATE,’$$$$99’);
VALIDATE
GOODONE = INYEAR GT ‘80’;
ON INVALID TYPE “Please enter
a year after 1980”
ON INVALID GOTO GETDATA
...
ENDCASE
or this (Dialogue Manager):
-GETDATE
-PROMPT &INDATE.Please enter a date(MMDDYY).A6.
-SET &INMONTH = EDIT(&INDATE,’99’);
-SET &INDAY = EDIT(&INDATE,’$$99’);
-SET &INYEAR = EDIT(&INDATE,’$$$$99’);
-SET &MSG = IF &INMONTH LT ‘01’ OR
&INMONTH GT ‘12’ THEN
-
‘Invalid month’ ELSE
-
IF &INDAY LT ‘01’ OR &INDAY GT ‘31’ THEN
-
‘Invalid day’ ELSE
-
IF &INDYEAR LT ‘80’ OR &INYEAR GT ‘99’ THEN
-
‘Invalid year’ ELSE ‘ ‘;
-IF &MSG EQ ‘ ‘ GOTO GOODDATE;
-TYPE &MSG
-GOTO GETDATE
-*--------------------------------------------------
-GOODDATE
...
How to fix it:
The best way of fixing this problem is to
remove it. Simply 'comment out' any logic that validates or restricts
a year to a certain range. The original logic was put in to protect the
user from data entry mistakes. To make it work 'correctly' again,
you need to revisit the arguments of what a 'good' year is with the users.
This could make logic even more complicated than before. You don't
have time for that now.
If you can expand the year to four digits, then the validation must also be expanded. For example, from 'Year must be greater than 80' to 'Year must be greater than '1980'.
4. Arithmetic calculations
Do your programs calculate elapsed time between dates? Many do. For some time, Focus has had FUSELIB functions that work quite nicely with the old A6 and I6 dates. However, the manual states clearly that these functions only work in the 20th century, and tests have proven it. For example, the YMD function calculates the difference between two A6YMD fields. Look at the following code sample:
DEFINE FILE TESTDATE
DATE1/A6YMD = '990101';
DATE2/A6YMD = '000101';
DIFF/I6 = YMD(DATE1,DATE2);
END
TABLE FILE TESTDATE
PRINT DATE1 DATE2 DIFF
END
PAGE 1
DATE1 DATE2
DIFF
-----
-----
----
99/01/01 00/01/01
-36159
END OF REPORT
The answer should have been 365. The new features in Focus 7.0 (DEFCEN, YRTHRESH) do not have any effect on these functions.
How to find it:
These are the date functions that are stuck
in the 20th century:
AYMD AYM YM YMD MDY
DMY
CHGDAT JULDAT GREGDT
Include these strings in your searches.
How to fix it:
Since these functions are used in DEFINEs
and COMPUTEs, fixing the problem means adding or replacing fields with
'new' dates. Using the sample above, the fix is:
SET DEFCENT = 19
SET YRTHRESH = 50
DEFINE FILE TESTDATE
DATE1/A6YMD = '990101';
DATE2/A6YMD = '000101';
DATE3/YMD = DATE1;
DATE4/YMD = DATE2;
DIFF/I6 = DATE4 - DATE3;
END
TABLE FILE TESTDATE
PRINT DATE1 DATE2 DATE3 DATE4 DIFF
END
PAGE 1
DATE1 DATE2
DATE3 DATE4
DIFF
-----
----- -----
----- ----
99/01/01 00/01/01
99/01/01 00/01/01
365
END OF REPORT
As you can see, DATE3 and DATE4 print the same as before, but now the calculation is correct.
5. Sequence
Is your output sorted by 2-digit years? '00' comes before '99', so a sales report that spans 6 months could come out like this:
MYRPT FOCEXEC Sales
by Month From 99/09 to present
Run: 02/29/2000
($000)
YEARMON SALES
------
------
00/01
6,789
00/02
4,321
99/09
876
99/10
2,345
99/11
4,567
99/12
5,678
TOTAL 24,576
In the sample above, the results are ugly, but the correct answer is still available.
However, if the statements 'LAST', 'FIRST', 'LOWEST x', or 'HIGHEST x' are used against two digit years, then the results would be wrong. If the report above was generated with the statement 'BY HIGHEST 6 YEARMON', then nothing in the year 2000 would be selected as long as there was sales data from 1999!
How to find it:
To find this problem, you have to know how
your data and how your reports are built. If you have A6YMD or I6YMD
fields in your database and you sort on these fields, then you have a potential
problem. Even if your database has all 'smart' dates, that's no guarantee
that a 'dumb' date has been DEFINEd just for a report.
You can search for 'FIRST', 'LAST', 'HIGHEST', and 'LOWEST' to find the places where the report would definitely have a problem. In the end, though, careful inspection is the best way to find this problem.
How to fix it:
Since 'smart' dates sort correctly regardless
of their display format, the best and perhaps only way to fix this problem
is to define new fields. A6YMD becomes YMD, I4YM becomes YM, etc.
Version 7.0 features work very nicely in this respect. The internal values assigned to the new fields will depend on the settings for DEFCENT and YRTHRESH. In other words,
DEFINE FILE TESTDATE
DATE1/A6YMD = '000101';
DATE2/YMD = DATE1;
DATE3/YYMD = DATE1;
END
TABLE FILE TESTDATE
PRINT DATE1 DATE2 DATE3
END
PAGE 1
DATE1 DATE2
DATE3
-----
-----
-----
00/01/01 00/01/01 2000/01/01
END OF REPORT
6. Historical data integrity
Do you have historical data in your database
from around 1900? Especially if parts of your corporation are
over 100 years old, it's possible. In this situation, using the 'windowing'
features of Version 7.0 will not work, since any given window only spans
100 years.
How to find it:
You have to know your data. Period.
Real estate, fixed asset accounting, and personnel systems are the most
common places where data spans centuries.
How to fix it:
Since 'smart' dates have been available in
Focus for several years, in all likelihood any database that has historical
data already has them in that format, or at least A8YYMD.
These sort correctly regardless of their display format, the best and perhaps only way in this circumstance, you'll have to rebuild your database, and expand the date fields from 6 to 8 digits. There's no other reasonable way to fix it.
Another potential problem with historical data
is if you already have dates in 'New' date formats YMD or MDY for the year
2000 and greater. Focus 7.0.6 is Year 2000 compliant, but previous versions
were not, so even 'New' dates without
the DEFCENT &
YRTHRESH options will not work.
7. Leap year Calculation
2000 A.D. *IS* a leap year. This may
seem obvious to most people, because it's divisible by four. However,
most centuries are NOT leap years, e.g., 1900 A.D. Centuries divisible
by 400 (1600, 2000, etc.) are exceptions to the exception.
Most users don't write their own leap-year calculations, so the odds that one of your programs has this problem are extremely low. But still possible...
How to find it:
You have to know your programs. But
let's be realistic. If you're skilled enough to write your own leap
year routines, you belong in an IS department, not a business department.
A search of 5,000 programs on MVS (626,000 lines) revealed no occurrences
of 'user-written' leap year calculations.
How to fix it:
Focus 'new' dates correctly take care of leap
years, so any home-grown leap year calculation should be converted to use
the new date format. Remember that the FUSELIB routines that are
stuck in the 20th century (YMD, CHGDAT, etc.) won't work here.