The Worksheet Fixing Date Problems

# Chapter 12: Year 2000 Problems and Solutions

This chapter explains some of the basic year 2000 problems and the principles for fixing them using the windowing technique. It is equally suitable as background information whether you are verifying or remediating applications.

## 12.1 Year 2000 Problems in COBOL Programs

The COBOL constructions that can cause a year 2000 problem are:

• Comparisons - Comparing two 2-digit years produces the wrong result if the years are in different centuries. Comparisons occur as conditional expressions in EVALUATE, IF, PERFORM and SEARCH statements. PERFORM and EVALUATE statements can also involve arithmetic modifications, and can have an additional complications in the PERFORM loop or the EVALUATE WHEN clauses.

• Subtraction - Subtracting years from each other or subtracting a value from a year can produce the wrong result if the century boundary is crossed. Subtractions can occur in SUBTRACT or COMPUTE statements or in arithmetic expressions. It can also occur in an ADD statement if one of the operands is negative.

• Addition - Adding increments to two-digit years causes a problem if the result is not truncated and is allowed to extend beyond the two digits. This is a particular risk if you use the NOTRUNC compiler directive.

• Truncation - Truncating dates can be a problem if this loses the century information or if the century is assumed to be a constant.

• Other date calculations - Multiplication and division are mostly handled correctly, although they can fail in some situations, such as where a number of years is converted into a number of months since 1900.

• Special values - Literals that represent or imply the century can cause problems. For example, literals such as 19 and 1900 might indicate that a twentieth century date has been assumed. These need fixing to allow for the twenty first century. Also special values can be used to represent the end of file and if you fix these as if they hold dates, this could cause problems.

• Sort order - reversing the sort order by calculating a complement key causes a problem if the sort key includes a date.

• Some data item definitions - The physical representation of a data item affects how it is treated arithmetically and how comparable it is with others. Although this does not cause a failure in the original COBOL, it affects how you fix the code. For example, non-numeric items can not be handled arithmetically to add on the century.

• Group items, subfields and other data item references - Problems can occur when referring to a data item as a group item, or using a subscript or with reference modification.

• Constructions using keys, such as READ and WRITE. These require manual attention. Indeed you will probably want to fix these using data expansion rather than the windowing that SmartFind Plus is intended for.

In addition, although CALL statements do not in themselves cause a problem, if you pass year data items as parameters to the called programs, you will need to check and fix those programs as necessary.

To see sample code showing these and more complex problems, see the gotchas.cbl sample program within the sfplus\revolve\sample directory.

## 12.2 SmartFix Assumptions and Restrictions

SmartFix generates fixes based on the year type of the suspect data items and applies the fixes according to the type of suspect statement, as follows:

• If none of the data items in a suspect statement has a year type, SmartFix does not provide a fix for that statement. A fix is always provided for a data item with a year type.

• You can manually disable fixing a data item in individual statements. You can also set a year type for data items where the year type is used only in the context of that statement, and SmartFix generates appropriate fix code as a consequence.

SmartFix provides a fix for only some types of statements, and sets the fix status of the statement accordingly, as follows:

• If SmartFix can generate a full fix, it changes the status to Auto Fix and generates the fix

• If SmartFix can not fully fix the statement, it changes the status to Not Fixed and does not generate a fix

• If you change the status to Fixed, SmartFix generates a partial fix and you can then adjust it as necessary

Note: By default, SmartFix inserts COBOL code that conforms to the ANSI '85 standard. You can for fix code that conforms to the ANSI '74 standard. This fix code is in the ANS74 macro library and is available from the Fix Options tab of the worksheet Options.

SmartFix provides fixes for:

• IF statements.

• ADD, SUBTRACT and COMPUTE statements.

• Simple constructions of CALL statements that use only the USING clause and no call convention.

• Conditional expressions in IF statements and in EVALUATE and PERFORM statement headers, but not the complete PERFORM or EVALUATE statements. See the Restrictions that follow.

• The VARYING clause of PERFORM statement headers, but not the complete PERFORM statement. See the Restrictions that follow.

• Arithmetic expressions in COMPUTE statements, IF statements, and EVALUATE statement headers, and also in reference modification, subscripts and indexes. All types of arithmetic are handled in these expressions, including multiplication and division.
##### Restrictions:

SmartFix does not provide fixes for:

• MULTIPLY and DIVIDE statements.

• Complex CALL statements, such as those using call conventions and using the BY REFERENCE, BY CONTENT and BY VALUE phrases.

• The complete PERFORM statements. Only the PERFORM statement header is fixed and not the rest of the PERFORM statement, which might need fixing to ensure the data items in the header are up to date every time through the PERFORM loop. If any other part of the PERFORM statement needs fixing, you have to manually edit the code outside SmartFix.

• WHEN clauses of EVALUATE statements.

• SEARCH statements.

• Constructions using keys, such as READ and WRITE. You will probably want to fix these using data expansion rather than the windowing that SmartFind Plus is intended for.

## 12.3 Comparisons

##### Problem:

Comparisons can occur in EVALUATE, IF, PERFORM and SEARCH statements. SmartFix does not handle SEARCH statements at all.

The following statement compares two years. If the two years are in different centuries, the wrong result is produced. For example:

```     if yy1 > yy2
*    if 05 > 98       *> wrong result
*    if 2005 > 1998   *> correct result ```

Note that if the comparison is comparing for equality or non-equality, there is not a logic problem at the century boundary.

##### Find:
1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify IF*.
4. Click OK.

You now need to search for the PERFORM, EVALUATE and SEARCH statements in much the same way.

##### Fix:
```*     if yy1 > yy2         *> original IF statement
1     expand yy1 into ccyy1   *> ready to compare in line 3
2     expand yy2 into ccyy2   *> ready to compare in line 3
3     if ccyy1 > ccyy2     *> compare expanded data items```
 Lines 1 and 2 The two date data items need expanding ready for the comparison in the IF statement in line 3. Line 3 The IF statement needs to use the expanded versions of the two date data items.
##### How to fix:

SmartFix fixes any comparison that has an operand with a year type allocated. SmartFix uses the macros for each operand's year type and handles the statement as follows:

1. Expands each date data item according to its year type.

2. Replaces the date data items in the IF statement with their expanded versions.

SmartFix does not do anything with the expanded date data items after the statement, since the operands were not changed in the statement and the originals are still valid.

• Comparing non-numeric operands - In COBOL, non-numeric operands can be compared with numeric operands. The alphanumeric equivalent of the numeric operand is compared with the non-numeric operand. Providing SmartFix expands the date operands and compares the expanded operands, the combination of numeric and non-numeric operands does not matter.

For example, when comparing a group item with a numeric item, the group item is treated as a non-numeric item and so the alphanumeric equivalent of the numeric item is successfully compared with it.

```     01 display-date     PIC 9(6).
01 yymmdd
03 yy             PIC 99.
03 mm             PIC 99.
03 dd             PIC 99.
. . .
if display-date > yymmdd```
• Combined conditions with logical connectors - A combined condition comprises two or more conditions with logical connectors, such as AND and OR, and a negated combined condition uses the logical operator NOT. SmartFix handles these by expanding the date operands and comparing the expanded operands.

• Conditions with arithmetic expressions - SmartFix handles conditions with arithmetic expressions in the same way as the other arithmetic expressions and conditions, expanding the operands and comparing the expanded operands.

## 12.4 PERFORM Statements

The PERFORM statement header can involve a comparison in its UNTIL clause, and an arithmetic modification in its VARYING clause. Both the comparison and the modification can cause logic problems if the data items involved represent dates.

SmartFix automatically generates a fix for the PERFORM statement header so that the UNTIL condition and the VARYING clauses are evaluated correctly the first time through the PERFORM loop. The compared data items are expanded before the header, and the varied operand is expanded before the header and contracted after it.

However a complication arises in fixing PERFORM statements because the date data items in the PERFORM statement header might be modified during the performed code and so they need fixing every time through the PERFORM loop. In these situations, you need to manually add code at the end of the PERFORM loop to ensure the date data items are up to date when they tested and varied again in the UNTIL and VARYING clauses of the PERFORM statement header.

### 12.4.1 PERFORM UNTIL Condition

##### Problem:

In a PERFORM UNTIL statement, two operands are compared, and one or other of them will be modified within the performed code before they are compared again.

```    perform until yy1 > yy2
. . . performed code . . .
end-perform```

The initial comparison can be fixed like any other comparison, by expanding the date data items before the comparison. The complication in a PERFORM statement is that the date data items might change each time through the loop and so they need re-expanding every time.

##### Find:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify PERFORM*.
4. Click OK.
##### Fix:
```1    expand yy1 into ccyy1      *> ready to compare in line 3
2    expand yy2 into ccyy2      *> ready to compare in line 3
3    perform until ccyy1 > ccyy2  *> compare expanded dates
. . . performed code . . .
11       expand yy1 into ccyy1    *> in case yy1 has changed
12       expand yy2 into ccyy2    *> in case yy2 has changed
13   end-perform ```
 Lines 1 and 2 The two date data items need expanding ready for the first comparison in the UNTIL clause in line 3. Line 3 The UNTIL clause needs to use the expanded versions of the two date data items. Lines 11 and 12 The date data items might have been modified in the performed code since the PERFORM statement header. In case they have, they need re-expanding, ready for the next comparison in the UNTIL clause.
##### How to fix:

SmartFix automatically generates a fix that:

• Expands the date data items before the PERFORM statement header. See lines 1 and 2 in the fix above.

• Changes the PERFORM statement header to use the expanded version of the date data items. See line 3 in the fix above.

You need to manually edit the code to expand the date data items at the end of the performed code, immediately before the END-PERFORM statement. If the performed code modifies only one of the date data items, you need expand that one only. See lines 11 and 12 in the fix above.

### 12.4.2 PERFORM VARYING ... Where the Varied Item is not Compared

##### Problem:

In a PERFORM VARYING . . . statement, an operand is assigned an initial value at the start of the loop and is varied every time through the loop. This section describes the case where the varied operand is not involved in the comparison in the UNTIL clause.

```    perform varying yy1 from yy2 by 1 until yy3 > yy4
. . . performed code . . .
end-perform```

This VARYING clause assigns the date data item, `yy1`, with an initial value and then modifies that date data item each time through the loop. The initial assignment does not cause a problem. The modification, however, might involve problematic arithmetic and so needs fixing.

##### Find:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify PERFORM*.
4. Click OK.
##### Fix:
```1    expand yy2 into ccyy2     *> ready to assign in line 4
2    expand yy3 into ccyy3     *> ready to compare in line 4
3    expand yy4 into ccyy4     *> ready to compare in line 4
4    perform varying ccyy1 from ccyy2 by 1 until ccyy3 > ccyy4
5        contract ccyy1 into yy1     *>since ccyy1 has changed
. . . performed code . . .
11       expand yy1 into ccyy1       *> in case yy1 has changed
12       expand yy2 into ccyy2       *> in case yy2 has changed
13       expand yy3 into ccyy3       *> in case yy3 has changed
14    end-perform
15    contract ccyy1 into yy1        *> since ccyy1 has changed```
 Line 1 In theory, this date data item does not need expanding. However, for practical purposes it does, because it is used to assign an expanded date to the date data item `ccyy1`. Note that the date data item, `yy1`, does not need expanding initially, since it is assigned its value in line 4. Lines 2 and 3 The two compared date data items need expanding ready for the first comparison in the UNTIL clause in line 4. Line 4 Although, the expanded `ccyy1` is not needed for the assignment in the first execution of the PERFORM statement, it is needed in subsequent executions, where modifications occur. Since the expanded `ccyy1` is needed, the expanded `ccyy2` is also needed for the initial assignment. As described in the previous section, the two expanded date data items, `ccyy3` and `ccyy4`, need to be used in the UNTIL clause. Line 5 The varied date data item, `ccyy1`, needs to be contracted back after being varied, in case the varied value is used in the performed code. Lines 11, 12 and 13 The date data items might have been modified in the performed code since the PERFORM statement header. In case they have, they need re-expanding, ready for the next variation and the next comparison in line 4. Line 15 In theory, the varied date data item, `ccyy1`, needs to be contracted back after dropping out of the PERFORM loop, since the last action in the PERFORM loop was to vary it. In practice, this needs to happen only if the unexpanded version of the date data item, `yy1` is used subsequently.
##### How to fix:

SmartFix automatically generates a fix that:

1. Expands the date data items before the PERFORM statement header. See lines 1, 2 and 3 in the fix above.

2. Changes the PERFORM statement header to use the expanded version of the date data items. See line 4 in the fix above.

3. Contracts the varied date data item, `ccyy1` immediately after the PERFORM statement header. See line 5 in the fix above.

You need to manually edit the code to:

• Expand the date data items at the end of the performed code, immediately before the END-PERFORM statement. If the performed code not modify all the date data items, you need expand only the ones that are modified. See lines 11 and 12 in the fix above.

• Contract the varied date data item, `ccyy1` immediately after dropping out of the PERFORM loop, after the END-PERFORM statement. You do not need to do this if the date data item, `yy1`, is not used in the subsequent code. Also, you do not need to contract back any operands that are not varied, since their contracted versions are still valid. See line 14 in the fix above.

### 12.4.3 PERFORM VARYING ... Until the Varied Item Meets a Condition

##### Problem:

In a PERFORM VARYING ... statement, an operand, `yy`, is varied until it meets the condition in the UNTIL clause.

```    perform varying yy1 from yy2 by 1 until yy1 > yy3
. . . performed code . . .
end-perform```

The varied operand, `yy1`, might be used during the performed code and it might be modified before it is varied and tested again. An up-to-date version of this operand needs to be available to the condition every time it is tested.

##### Find:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify PERFORM*.
4. Click OK.
##### Fix:
```1     expand yy2 into ccyy2    *> ready for assignment in line 3
2     expand yy3 into ccyy3    *> ready for comparing in line 3
3     perform varying ccyy1 from ccyy2 by 1 until ccyy1 > ccyy3
4         contract ccyy1 into yy1    *> since ccyy1 has changed
. . . performed code . . .
11        expand yy1 into ccyy1      *> in case yy1 has changed
12        expand yy3 into ccyy3      *> in case yy3 has changed
13    end-perform
14    contract ccyy1 into yy1        *> since ccyy1 has changed```
 Line 1 In theory, this date data item, `yy2` does not need expanding. However, for practical purposes it does, because it used to assign an expanded date to the date data item `ccyy1` in line 3. Consequently, the date data item, `ccyy1`, does not need expanding initially, since it is assigned its value in line 3 from `ccyy2`. Line 2 The other date data item to be compared, `ccyy3`, needs expanding ready for the comparison in the until clause on line 3. Line 3 Although an expanded `ccyy1` is not needed for the assignment in the first execution of the PERFORM statement, it is needed in subsequent executions where a modification occurs. Since the expanded `ccyy1` is needed, the expanded `ccyy2` is also needed for the initial assignment. As described in the previous section, the PERFORM statement needs to use the expanded versions of the two compared date data items, `ccyy1` and `ccyy3`, in its UNTIL clause. Line 4 The varied date data item, `ccyy1` needs to be contracted back after being varied, in case the varied value is used in the performed code. Lines 11 and 12 The date data items might have been modified in the performed code since the PERFORM statement header. In case they have, they need re-expanding, ready for the next variation and the next comparison in line 3. The date data item, `ccyy2`, that was used for the initial assignment is not used in the PERFORM statement again and so does not need re-expanding. Line 14 In theory, the varied date data item, `ccyy1`, needs to be contracted back after dropping out of the PERFORM loop, since the last action in the PERFORM loop was to vary it. In practice, this needs to happen only if the unexpanded version of the date data item, `yy1` is used subsequently.
##### How to fix:

SmartFix automatically generates a fix that:

1. Expands the date data items before the PERFORM statement header. See lines 1 and 2 in the fix above.

2. Changes the PERFORM statement header to use the expanded version of the date data items. See line 3 in the fix above.

3. Contracts the varied date data item, `ccyy1` immediately after the PERFORM statement header. See line 4 in the fix above.

You need to manually edit the code to:

• Expand the date data items at the end of the performed code, immediately before the END-PERFORM statement. If the performed code does not modify all the date data items, you need expand only the ones that are modified. See lines 11 and 12 in the fix above.

• Contract the varied date data item, `ccyy1` immediately after dropping out of the PERFORM loop, after the END-PERFORM statement. You do not need to do this if the date data item, `yy1`, is not used in the subsequent code. See line 14 in the fix above.

### 12.4.4 PERFORM WITH TEST AFTER

##### Problem:

When using the WITH TEST AFTER clause, the condition is tested after the PERFORM code has been executed, and so affects which operands need to be expanded when.

```    perform with test after varying yy1 from yy2 by 1
until yy1 > yy3
. . . performed code . . .
end-perform```

In this statement, the varied operand, `yy1`, is not varied until the end of the performed code. Since it is possible that `yy1` was modified during the performed code and it needs expanding at the end of the performed code, just before it is varied and tested.

##### Find:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify PERFORM*.
4. Click OK.
##### Fix:
```1     expand yy2 into ccyy2     *> ready for assigning in line 2
2     perform test after varying ccyy1 from ccyy2 by 1
until ccyy1 > ccyy3
3         contract ccyy1 into yy1   *> because ccyy1 has changed
. . . performed code . . .
11        expand yy1 into ccyy1     *> in case yy1 has changed
12        expand yy3 into ccyy3     *> in case yy3 has changed
13    end-perform ```
 Line 1 The date data item `ccyy2` needs expanding ready for the initial assignment. Lines 11 and 12 These date data items `ccyy1` and `ccyy3` need expanding ready for the test at the end of the performed code. Note that they did not expanding before the PERFORM statement header.
##### How to fix:

SmartFix automatically generates a fix that:

1. Expands the date data item, `ccyy2`, ready for assigning to `ccyy1` in the PERFORM statement header. See line 1 in the fix above.

2. Changes the PERFORM statement header to use the expanded version of the date data items. See line 2 in the fix above.

3. Contracts the varied date data item, `ccyy1` immediately after the PERFORM statement header. See line 3 in the fix above.

You need to manually edit the code to:

• Expand the date data items `ccyy1` and `ccyy3` at the end of the performed code, immediately before the END-PERFORM statement. If the performed code does not modify all the date data items, you need expand only the ones that are modified. See lines 11 and 12 in the fix above.

Note that the automatically generated fix expands these date data items, `ccyy1` and `ccyy3` before the PERFORM statement header. This expansion does not need before the header, although it does no harm. SmartFix includes these expansions so that you can easily copy them from before the header to the end of the PERFORM loop.

When the PERFORM loop finishes, no action is needed, since the test is done without varying any expanded operands. The expanded and contracted versions of all the operands are in step.

### 12.4.5 PERFORM Out-of-Line-Procedure

##### Problem:

In this statement an out-of-line routine is performed.

`    perform routine varying yy1 from yy2 by 1 until yy1 > yy3 `

The operands need attention every time through PERFORM loop, and yet you cannot apparently fix them without changing the performed routine itself.

##### Find:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify PERFORM*.
4. Click OK.
##### Fix:
```1     expand yy2 into ccyy2     *> ready to assign in line 3
2     expand yy3 into ccyy3     *> ready to compare in line 3
3     perform varying ccyy1 from ccyy2 by 1 until ccyy1 > ccyy3
4        contract ccyy1 into yy1
perform routine
11       expand yy1 into ccyy1  *> ready to compare in line 3
12       expand yy3 into ccyy3  *> ready to compare in line 3
13    end-perform
14    contract ccyy1 into yy1 ```
 Line 1 In theory this date data item, `yy2` does not need expanding. However, for practical purposes it does, because it used to assign an expanded date to the date data item `ccyy1` in line 3. Consequently, the date data item, `ccyy1`, does not need expanding initially, since it is assigned its value in line 3 from `ccyy2`. Line 2 The date data item, `ccyy3`, needs expanding ready for the comparison in the until clause on line 3. Line 3 Although an expanded `ccyy1` is not needed for the assignment in the first execution of the PERFORM statement, it is needed in subsequent executions where a modification occurs. Since the expanded `ccyy1` is needed, the expanded `ccyy2` is also needed for the initial assignment. As described in the previous section, the PERFORM statement needs to use the expanded versions of the two compared date data items, `ccyy1` and `ccyy3`, in its UNTIL clause. Line 5 The varied date data item, `ccyy1` needs to be contracted back after being varied, in case the varied value is used in the performed code. Lines 11 and 12 The date data items might have been modified in the performed code. In case they have, they need re-expanding, ready for the next variation and the next comparison in line 3. The date data item, `ccyy2`, which was used for the initial assignment, is not used in the PERFORM statement again and so does not need re-expanding. Line 14 In theory, the varied date data item, `ccyy1`, needs to be contracted back after dropping out of the PERFORM loop, since the last action in the PERFORM loop was to vary it. In practice, this needs to happen only if the unexpanded version of the date data item, `yy1` is used subsequently.
##### How to fix:

To avoid changing the performed routine, SmartFix adds an in-line PERFORM to test the condition and retains the out-of-line PERFORM without a condition. All the necessary expansions and contractions are done within the new in-line performed code, either before it is called or on return from it.

SmartFix automatically generates a fix that:

1. Expands the date data items before the PERFORM statement header, in the same way as for an in-line PERFORM VARYING. See lines 1 and 2 in the fix above.

2. Adds an in-line PERFORM statement that uses the expanded version of the date data items. See line 3 in the fix above.

3. Contracts the varied date data item, `ccyy1` immediately after the PERFORM statement header. See line 4 in the fix above.

4. Changes the original PERFORM statement to just perform the out-of-line routine without any condition test. See line 5 in the fix above.

5. Expands the date data items immediately after the out-of-line PERFORM section. If the PERFORM section code does not modify all the date data items, you need expand only the ones that are modified. See lines 11 and 12 in the fix above.

You need to manually edit the code to:

• Contract the varied date data item, `ccyy1` immediately after dropping out of the PERFORM loop, after the end PERFORM statement. You do not need to do this if the date data item, `yy1`, is not used in the subsequent code. See line 14 in the fix above.

### 12.4.6 EXIT PERFORM and GOTO

Exiting from performed code in the middle does not cause a problem. You can exit using:

• EXIT PERFORM - no action is needed.

Wherever there is an EXIT PERFORM within inline performed code, no action is needed. The contracted versions of the varied operand and those tested in the UNTIL condition are up to date, ready for use in the rest of the program.

• EXIT PERFORM CYCLE - probably no action is needed.

This is a relatively new construct in the COBOL language and so you probably will not have to handle it. After an EXIT CYCLE statement, control passes to the END-PERFORM statement and the PERFORM cycle continues.

• GOTO - no action is needed.

If there is a GOTO within the performed code, both contracted data items are up to date. The GOTO statement passes control to the procedure-name, from which control does not return.

### 12.4.7 Summary of Fixes Needed for PERFORM Variants

Until

Test after until

Varying until

Test after varying

Before PERFORM statement:

Expand operands in FROM and BY

-

-

y

y

Expand operands compared in UNTIL

y

-

y

-

After PERFORM statement:

Contract the varied operand

-

-

y

y

After performed code:

Expand varied operand, if changed

-

-

y

y

Expand operands compared in UNTIL, if changed

y

y

y

y

After END-PERFORM statement:

Contract the varied operand

-

y

-

## 12.5 EVALUATE Statements

##### Problem:

EVALUATE statements comprise comparisons and potentially arithmetic expressions, both of which can cause problems at the century boundary. For example:

```    Evaluate 05 - 95    *> fails. Should be 10 not -90.
When 05 > 95        *> fails. Should be true not false. ```

The following EVALUATE statement involves a conditional expression and so needs fixing:

```    evaluate yy1 > yy2
when true . . .
when false . . .
end-evaluate ```

The following EVALUATE statement involves an arithmetic expression and so needs fixing:

```    evaluate yy1 - yy2
when tmp-1 . . .
when tmp-2 . . .
end-evaluate```
##### Find:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify EVALUATE*.
4. Click OK.
##### Fix:

SmartFix handles EVALUATE statement headers that contain conditional or arithmetic expressions, but not any of the WHEN clauses.

```1    expand yy1 into ccyy1
2    expand yy2 into ccyy2
3    evaluate yy1 > yy2
when true . . .
when false . . .
end-evaluate ```
 Lines 1 and 2 The year operands, `yy1` and `yy2`, need expanding before the EVALUATE statement in line 3. Line 3 The EVALUATE statement needs to use expanded versions of the year operands.
##### How to fix:

Use SmartFix to expand the year data items as described above to fix the EVALUATE statement header.

For other constructions of EVALUATE statements, you need to edit the WHEN clauses manually.

## 12.6 CALL Statements

##### Problem:

CALL statements do not in themselves cause a problem, but if you pass year data items as parameters to the called programs, you will need to check and fix those programs as necessary.

For example, in the following CALL statement, two year date data items are passed to the called program:

`    call program using yy1 yy2 `
##### Find:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify CALL*.
4. Click OK.
##### Fix:

SmartFix fixes simple CALL statements only, fixing the year data items in the USING clause, but not if other phrases all included in the statement, such as BY VALUE.

```1     expand yy1 into ccyy1
2     expand yy2 into ccyy2
3     call program using ccyy1 ccyy2 ```
 Lines 1 and 2 The year data items, `yy1` and `yy2`, need expanding before the CALL statement in line 3. Line 3 The CALL statement needs to use expanded versions of the year data items.
##### How to fix:

Use SmartFix to handle the year data items as described above.

You also need to fix the called program to expect the expanded parameters. For example, if you are calling a COBOL program. you might need to update the PROCEDURE DIVISION USING statement in the called program and its Linkage section.

##### Restrictions:

SmartFix does not currently handle the following components of CALL statements:

• Call conventions

• BY REFERENCE, BY VALUE and BY CONTENT clauses

• GIVING and RETURNING clauses

In addition SmartFix does not provide any fixes for the called program or any data declarations for it.

## 12.7 Subtraction

If the operands input to the subtraction represent dates, SmartFix expands them before the operation. If the result is a date, it is contracted back after the operation.

Interestingly the result of a subtraction might be a year or the difference between some dates. Be wary of a non-date result that is stored in an operand that potentially holds a date. Similarly a date might be stored in a non-date data item.

### 12.7.1 Subtracting One Year from Another

##### Problem:

The following statement subtracts one year from another, giving the difference between them, and not a year. If the two year operands are in different centuries, the wrong result is produced. For example:

```    subtract yy1 from yy2 giving difference
05 - 95 = - 90     *> wrong result
2005 - 1995 = 10     *> correct result```
##### Find:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify SUBTRACT*.
4. Click OK.

Having studied the SUBTRACT statements, you need to examine statements with arithmetic expressions that might contain subtractions. To do this:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. In Statement, specify * - *. You must put a space on both sides of the hyphen before the wildcard *.
4. Click OK.
##### Fix:
```1     expand yy1 into ccyy1
2     expand yy2 into ccyy2
3     subtract yy1 from yy2 giving difference ```
 Lines 1 and 2 The two year operands, `ccyy1` and `ccyy2`, need expanding before the subtraction in line 3. Line 3 The subtraction needs to use the two expanded year operands. In this situation, the result, `difference` is not a year and so does not need expanding or contracting in any way.
##### How to fix:

Use SmartFix to handle the year operands as described above, expanding them as necessary, according to their year types.

### 12.7.2 Subtracting a Value from a Year

##### Problem:

The following statement subtracts a value from a year, giving a new year. If the subtraction causes the century boundary to be crossed, the wrong result is produced:

```    subtract temp from yy1 giving yy2
03 - 5 = - 2     *> wrong result
2003 - 5 = 1998    *> correct result```
##### Find:

Find the subtractions in the same way as described in the section, Subtracting One Year from Another

##### Fix:
```1     expand yy1 into ccyy1
2     subtract temp from ccyy1 giving ccyy2
3     contract ccyy2 into yy2
```
 Line 1 The year operand, `yy1`, needs expanding before the subtraction in line 2. However, the year operand, `yy2`, does not need expanding, since it is generated by the subtraction in line 2. The operand `temp` is not a date and so does not need expanding. Line 2 The subtraction needs to use expanded year operand, `ccyy1`, and to store the result in the expanded operand, `ccyy2`. Line 3 The result operand `ccyy2` needs to be contracted ready for use in subsequent code.
##### How to fix:

Use SmartFix to handle the year operands as described above, expanding them as necessary, according to their year types.

### 12.7.3 Subtracting Giving a Year in a Nonyear Data Item

##### Problem:

In the following statement, the result is not a year and yet is stored in a data item that is allocated a year type. This causes an additional problem for you when fixing, because the year type allocated to the result operand is no longer appropriate after the operation.

```    subtract yy1 from yy2
05 - 95 = - 90      *> wrong result
2005 - 1995 = 8     *> correct result```
##### Find:

Find the subtractions in the same way as described in the section, Subtracting One Year from Another

##### Fix:
```1     expand yy1 into ccyy1
2     expand yy2 into ccyy2
3     subtract ccyy1 from ccyy2
3     contract ccyy2 into yy2
```
 Lines 1 and 2 The two year operands, `yy1` and `yy2`, need expanding before the subtraction in line 3. Line 3 The subtraction needs to use the two expanded year operands. Line 4 The result operand `ccyy2` needs to be contracted ready for use in subsequent code.
##### How to fix:

Use SmartFix to handle the year operands as described above, expanding them as necessary, according to their year types.

In this situation, the result, `ccyy2`, is not a year and yet is stored in a operand that is allocated a year type. This potentially causes you a problem when fixing subsequent lines. SmartFix will expect to map the operand according to its year type in subsequent suspect lines, giving the wrong result.

To avoid this, you need to examine subsequent uses of the operand and when it does not contain a date, disable any automatic mapping of the operand to an expanded version. To disable operand mapping in one statement, go to the operand table in the SmartFix dialog and right-click the operand. You can then click Leave operand alone.

##### Problem:

An addition might hide a subtraction, if one of the data items is negative or if a negative literal is used. This statement then has the same problems as a subtraction, and needs fixing in a similar way.

##### Find:

The negative additions might already be identified in the worksheet as a result of running Verify all research. In which case the negative additions are categorized as R-AddNegLtil. To find them:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. Click Show items.
4. Click Categories.
6. Click OK twice.

If the negative additions are not categorized in the worksheet, you can run the tool, Find negative additions to do this. This tool searches the worksheet and identifies any ADD and COMPUTE statements in the worksheet that involve a negative literal or a signed data item. The tool then categorizes those statements and their data items as R-AddNegLitl.

##### Fix:
```1     expand yy1 into ccyy1
3     contract ccyy1 into yy1
```
 Line 1 The year operand, `yy1`, needs expanding before the addition in line 2. The operand `temp` is not a date and so does not need expanding. Line 2 The addition needs to use expanded year operand, `ccyy1`, in which the result is also stored. Line 3 The result operand `ccyy1` needs to be contracted ready for use in subsequent code.
##### How to fix:

Use SmartFix to handle the year operands as described above, expanding them as necessary, according to their year types. Regardless of whether the operands are positive or negative, the correct result will be produced.

Addition of two-digit years does not always cause a problem. When numeric data items (such as PIC 99) are added, they are successfully truncated:

```01  yy        PIC 99.
0 1  yymmdd    PIC 9(6).
. . .
*    05 + 98 = 03               (correct)

*    050000 + 981122 = 031122   (correct)```
##### Problem:

Addition of positive two-digit years causes a problem if the result is not truncated and is allowed to extend beyond the two digits. This can happen when the result operand can hold a three-digit result. For example:

```01  yyyy      PIC 9(4).
0 1  ddmmyy    PIC 9(6).
0 1  yy-comp   PIC 99 COMP.
. . .
*    05 + 98 = 0103             (wrong)
*    05 + 1998 = 2003           (correct)

*    05 + 070998 = 071003       (wrong)
*    05 + 07091998  = 07092003  (correct)

*    05 + 98 = 103              (wrong) ```

Data items defined as COMPUTATIONAL do not hold the data as decimal digits. This means that a data item, such as PIC 99 COMP, is normally assigned one byte, which can hold values up to 255.

These additions can be a problem if the programs are compiled with the NOTRUNC Compiler directive, which prevents the results being truncated.

##### Find:

The additions without truncation might already be identified in the worksheet as a result of running Verify all research. In which case they are categorized as R-Add3DigitYr or R-UseNOTRUNC. To find them:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. Click Show items.
4. Click Categories.
6. Click OK twice.

If the additions without truncation are not categorized in the worksheet, you can run the tool, Find add to 3-digit year, to do this. This tool searches the worksheet for additions where the data item holding the result can hold more than 2 digits, and optionally binary items of 1 and 2 bytes. The tool then categorizes those statements and their data items as R-Add3DigitYr.

Alternatively, you can use Find potential NOTRUNC problems, which finds the additions involving COMP and COMP-4 data items of 2 bytes. The tool then categorizes those statements and their data items as R-UseNOTRUNC.

##### Fix:
```1     expand yy1 into ccyy1
3     contract ccyy1 into yy1
```
 Line 1 The year operand, `yy1`, needs expanding before the addition in line 2. The operand `temp` is not a date and so does not need expanding. Line 2 The addition needs to use expanded year operand, `ccyy1`, in which the result is also stored. Line 3 The result operand `ccyy1` needs to be contracted ready for use in subsequent code.
##### How to fix:

Use SmartFix to handle the year operands as described above, expanding them as necessary, according to their year types.

## 12.9 Date Truncation

##### Problem:

If a date data item is truncated by two or four digits, it is possible that the two digits representing the century are lost and this could cause a problem in subsequent statements that use the truncated item. For example:

```     Move ccyy to yy
*    Move 1956 to 56   (could cause a problem)```

If the target is alphanumeric or a group item, the least significant two digits of the year are lost and the statement is probably not of interest. For example:

```     Move ccyy to yy
*    Move 1956 to 19   (not a problem)
```

Situations where the century might be lost through truncation are where a:

• 4-digit date, CCYY, is moved to a 2-digit numeric data item.

• 6-digit date, CCYYMM, is moved to a 4-digit numeric data item.

• 7-digit date, CCYYDDD, is moved to a 5-digit numeric data item.

• 8-digit date, CCYYMMDD, is moved to a 6-digit numeric data item.

• 10-digit date, CCYY/MM/DD, is moved to a 6-digit numeric data item.
##### Find:

The date truncations might already be identified in the worksheet as a result of running Verify all research. In which case they are categorized as R-DateTrunc. To find them:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. Click Show items.
4. Click Categories.
5. Check R-DateTrunc.
6. Click OK twice.

If the date truncations are not categorized in the worksheet, you can run the tool, Find date truncation, to do this. This tool searches the worksheet for MOVE statements that truncate the values of the data items being moved. A value might be truncated because it is being moved to a data item of a smaller size, or because it is being moved from a data item of COMP format into one of Character or Display format. COMPUTATIONAL data items can hold values greater than implied by their COBOL PICTURE, which can lead to truncation. The tool then categorizes those statements and their data items as R-DateTrunc.

##### Fix:

The statements are not a problem in their own right and so do not need fixing.

## 12.10 Multiplication and Division

Multiplication and division are not frequently used on dates. However, multiplication can be used to multiply the years by 12 to calculate the number of months since 1900, or by 52 to calculate the weeks, and so on, and this might lead to problems

Multiplication and division do not cause a problem if the purpose is to convert a year into a different representation, since the century boundary is not crossed.

```    multiply yy 10000 giving tmp-yyyyyy
*             69 * 1000 = 690000```

Division is similar to multiplication. The added danger is where the divisor is zero when it represents the two-digit form of the year 2000.

##### Find:

The multiplication or division statements might already be identified in the worksheet as a result of running Verify all research. In which case they are categorized as R-YYMultDiv. To find them:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. Click Show items.
4. Click Categories.
5. Check R-YYMultDiv.
6. Click OK twice.

If the multiplication or division statements are not categorized in the worksheet, you can run the tool, Find YY multiply, divide, which identifies year data items used in multiplication or division statements. This tool searches the worksheet for the statements involving 2-digit numeric data items in multiplication or division, which includes MULTIPLY, DIVIDE and COMPUTE statements. The tool then categorizes those statements and their data items as R-YYMultDiv

### 12.10.1 Division by the Year 00

Problems:

Division can cause a problem if the divisor is 00, representing the year 2000.

##### Find:

Find these divisions in the same way as described in the previous section.

##### Fix:

If the division is included in a COMPUTE statement or arithmetic expression, SmartFix applies the appropriate macros to handle any data items that have a year type. SmartFix uses the macros for the relevant year types and handles the statement as follows:

1. Adds code to expand each input operand that has a year type, before the suspect statement.

2. Changes the suspect statement to operate on the expanded operands.

3. Compress or move the result back to the appropriate form.
##### Restriction:

If the suspect statement uses the DIVIDE verb, SmartFix does not provide a fix, or allow you to specify a fix. If you need to fix the statement, you have to edit the code manually.

## 12.11 Special Values in Date Handling

### 12.11.1 Literals 4, 12, 365

##### Problem:

In the following statement, the year operand, `yy`, is multiplied by 12 to calculate the months since 1900. If the year is in the 2000s the wrong result is produced. For example, to calculate the months for June 2005:

```compute total-mm = (yy * 12) + mm
*        66 = (05 * 12) + 6                   (wrong)
*        1266 = (05 * 12) + (100 *12) + 6     (correct) ```

Unlike in subtractions, expanding the year operand does not solve the problem, since the computation produces the months since the year 0000, and not the months since 1900 as required. Also the result might be too large for the receiving data item. For example:

```compute total-mm = (ccyy * 12) + mm
*   24066 = (2005*12) + 6              (wrong, mm since 0000)
*   1266 = ((2005*12) + 6) - (1900*12) (correct, mm since 1900)```
##### Find:

These date calculations might already be identified in the worksheet as a result of running Verify all research. In which case they are categorized as R-UseOfLiterals. To find them:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. Click Show items.
4. Click Categories.
5. Check R-UseOfLiterals.
6. Click OK twice.

If the date calculations are not categorized in the worksheet, you can run the tool, Find multiply, divide by 4, 12, 365, which identifies calculations that might operate on date values, such as leap-year calculations or time-duration calculations. The tool searches the worksheet for data items initialized to or used with the values 4, 12, 365 or 366 and then finds any statements involving those data items in multiplication or division, which includes MULTIPLY, DIVIDE and COMPUTE statements. The tool then categorizes those statements and their data items as R-UseOfLiterals

##### Fix:
```1     expand yy1 into ccyy1
2     subtract 1900 from ccyy1
3     compute total-mm = (ccyy1 * 12) + mm ```
 Line 1 The year operand, `yy1`, needs expanding before the computation in line 3. The operand `mm` is not a year and so does not need expanding. Line 2 The computation in line 3 is expecting the years since 1900, not since the year 0000, so 1900 needs to be subtracted from the expanded year operand, `ccyy1`. Although you can subtract an equivalent value after the computation, there is a danger that the result operand `total-mm` is not large enough, so it is safer to subtract before the computation in line 3. Line 3 The COMPUTE statement needs to use expanded year operand, `ccyy1`, which now hold the years since 1900.
##### How to fix:

There are broadly two places where you can fix this problem. You can either fix the statements where the month value is used in a comparison, subtraction or addition. This is the usual windowing approach. However, you can fix the month value where it is calculated, where the multiplication occurs, which can be simpler and incur less change to the program.

To fix the statement where the month operand is calculated:

1. Using SmartFix, expand the year operand, `yy1`, using the appropriate macro for that operand's year type. See line 1 in the fix above.

2. In SmartFix, add a line before the COMPUTE statement, by editing the fix in the New Code tab. The new line needs to subtract 1900 from the expanded year operand, `yy1`. See line 2 in the fix above.

3. Using SmartFix, change the COMPUTE statement to use the expanded operand that represents the years since 1900. See line 3 in the fix above.

To generate fixes for the statements that operate on the month operand:

1. Create a date type, using Edit Year Type, and write the corresponding macros to handle data items that hold the months since 1900.

2. Allocate the new date type to the total months operand, so that SmartFix will apply the macros for that date type whenever that operand is used.

3. In the statement where the total months are calculated, do not expand the year operand or the result operand. To do this, you need to disable data item mapping for this statement. Go to the operand table in the SmartFix dialog and right-click the data item. You can then click Leave operand alone.

This means the result does not represent the months since 1900 as originally intended.

##### Restriction:

If the suspect statement uses the MULTIPLY verb, SmartFix does not provide a fix, or allow you to specify a fix. If you need to fix the statement, you have to edit the code manually.

### 12.11.2 Literals 19 and 20

##### Problem:

Literals representing the century or years in some form or another can cause problems. For example specific literals representing the century, like 19 and 1900, might need fixing.

```    add 1900 yy giving ccyy
*        1900 + 03 = 1903          (wrong)
*        2000 + 03 = 2003          (correct)```

The expansion that SmartFix generates does not take account of literals that represent years or centuries. SmartFix expands the year operands correctly and then proceeds to add 1900 as well. For example:

```    add 1900 ccyy-1 giving ccyy-2
*        1900 + 1903 = 3803          (wrong)
*        1900 + 2003 = 3903          (wrong)```
##### Find:

These embedded centuries might already be identified in the worksheet as a result of running Verify all research. In which case they are categorized as R-19/20Litl. To find them:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. Click Show items.
4. Click Categories.
5. Check R-19/20Litl.
6. Click OK twice.

If these embedded centuries are not categorized in the worksheet, you can run the tool, Find embedded century literals, which finds literal strings that might have a century value embedded in them, such as "July 24, 1998". This tool searches the worksheet for data items initialized to the values "* 19" and "* 20", that is 19 or 20 preceded by a space. The tools also searches for the statements that use those strings. The tool then categorizes those statements and their data items as R-19/20Litl

##### Fix:
```1     expand yy1 into ccyy1
2     move ccyy1 into ccyy2
```
 Line 1 The year operand, `yy1`, needs expanding, as intended in the original statement. Line 2 The expanded year operand `ccyy1` needs moving into the result operand, `ccyy2`, as intended in the original statement.
##### How to fix:

1. Use SmartFix to expand the year operand, according to its year type, before the statement.

2. In SmartFix, edit the code in the New Code tab to replace the original ADD statement with a MOVE statement to move the result into the required data item, `ccyy2`.

### 12.11.3 Sentinels

##### Problem:

Sentinel processing is the process where a date data item is used to hold a non-date value to flag some condition. Although this is not a problem in its own right, if the data item is fixed assuming that it holds a date, a problem might occur.

##### Find:

These sentinels might already be identified in the worksheet as a result of running Verify all research. In which case they are categorized as R-SentinelValue. To find them:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. Click Show items.
4. Click Categories.
5. Check R-SentinelValue.
6. Click OK twice.

If these sentinels are not categorized in the worksheet, you can run the tool, Find sentinel values: 000000 999999, which searches the worksheet for data items that might contain a value indicating a special condition, such as start or end-of-file, rather than containing a legitimate date value. The tool then categorizes those data items and their containing statements as R-SentinelValue

### 12.11.4 Complements

##### Problem:

Date data items might contain values in complement form. Typically, these fields are used to order date-values for SORT statements or in indexed file keys. The year 2000 fix might have to be adjusted to handle these values correctly.

##### Find:

These date values in complement form might already be identified in the worksheet as a result of running Verify all research. In which case they are categorized as R-1Complement, R-2Complement and so on. To find them:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. Click Show items.
4. Click Categories.
5. Check R-1Complement, R-2Complement and so on.
6. Click OK twice.

If these date values in complement form are not categorized in the worksheet, you can run the tool, Find 1s complement, Find 2s complement and so on, which search for data items that might contain date values in complement form. The Find 1s complement tool finds binary data items (COMP or COMP-4) that are initialized with high-values or hexadecimal FF and that are used in SUBTRACT statements. The tool then categorizes those statements and their data items as R-1Complement

## 12.12 Group Items

### 12.12.1 Implicit Century

##### Problem:

A date field that holds the century is often redefined with a subfield that omits the century. The date is set in the subfield with the assumption that the century is constant and is implicitly set.

There are two typical cases, one in which an 8-digit date of the form CCYYMMDD has a 6-digit subfield that omits the century and the other in which a 7-digit date of the form CCYYDDD has a 5-digit subfield that omits the century. In both cases, a MOVE statement that sets the subfield might yield the wrong date because the century is not adjusted.

##### Find:

These MOVEs to subfields might already be identified in the worksheet as a result of running Verify all research. In which case they have a category such as R-5-7Digit. To find them:

1. At the worksheet, click Display Filters.
2. Click Defaults.
3. Click Show items.
4. Click Categories.
5. Check R-5-7Digit.
6. Click OK twice.

If these MOVEs to subfields are not categorized in the worksheet, you can run a tool such as, Find 5- to 7-byte subfield (moves to window), which searches the worksheet for the MOVE statements where a 5-digit data item is moved either to a 7-digit elementary item or to a 5-digit item subordinate to a 7-digit group item. The tool then categorizes those statements and their data items as R-5-7Digit.

Similarly, use Find 4- to 6-byte subfield (moves to window) and so on to search for the MOVEs to subfields

### 12.12.2 Redefined Group Items

##### Problem:

Handling group items that contain elementary items representing the year is in principle the same as handling those elementary items. Since group items are not used in arithmetic, only comparisons offer a potential problem. When group items are compared, if the year is significant the result might be wrong.

```    if yymmdd-1 >= yymmdd-2
051228 >= 971228          wrong
20051228 >= 19971228        correct```

There is an additional problem in that group items are treated as character items and not numeric items. This means the macros handling group items cannot perform arithmetic, such as adding the century onto the year.

##### Fix:

Since group items are not numeric, the macros to handle them use MOVE statements rather than arithmetic to determine the century. Consequently the year type that you allocate to a group item has macros designed for handling non-numeric items.

##### How to fix:

1. Allocate a year type to the group item, using a year type designed for non-numeric items and designed with the date format of this group item.

2. In SmartFix, whenever the group item is involved in a suspect statement, use the macros for its year type to expand the year operands using MOVE statements rather than arithmetic.

If any subordinate items to a group item are defined as numeric non-display, such as PIC 9(4) COMPUTATIONAL, you cannot treat the group item as PIC X. In this case, you can edit the statement manually, or define a year type for group items like this and write the corresponding macros to handle them.

Example:

In this example, the two compared group items are treated as PIC X(6) even though their subordinate items are numeric (PIC 99).

```01 yymmdd-1
03 yy-1          pic 99.
03 mm-1          pic 99.
03 dd-1          pic 99.
0 1 yymmdd-2
03 yy-2          pic 99.
03 mm-2          pic 99.
03 dd-2          pic 99.
. . .
*    If yymmdd-1 > yymmdd-2         *> original code

* begin fix
move yymmdd-1 to ccyymmdd-1 of ccyymmdd-1   *> expand yymmdd-1
if ccyy-1 of ccyymmdd-1 > 60
move 19 to cc1 of ccyymmdd-1
else
move 20 to cc1 of ccyymmdd-1
end-if
move yymmdd-2 to ccyymmdd-2 of ccyymmdd-2   *> expand yymmdd-2
if ccyy-2 of ccyymmdd-2 > 60
move 19 to cc2 of ccyymmdd-2
else
move 20 to cc2 of ccyymmdd-2
end-if
If ccyymmdd-1 > ccyymmdd-2               *> compare group items
*  end fix ```

## 12.13 Subscripts

##### Problem:

If a subscript is a year and is used for accessing a table of data, problems occur when:

• The subscript is 00, representing the two-digit year 2000, because zero subscripts fail.

• The subscript has a negative value, resulting from an arithmetic expression, such as in:
```    move a(yy-70) to b.
```
##### Fix:

SmartFix handles arithmetic expressions in subscripts in the same way as COMPUTE statements, but does not handle negative or zero subscripts.

##### How to fix:

To fix zero subscripts, manually edit the code to adjust the subscript to run in sequence from 1 through 99. For example, for the window 1960-2059: for dates in the 1900s, subtract 59 from the subscript, and for dates in the 2000s, add 60 to the subscript.

Year Subscript

Array of Data

60 - 59 = 1

data

99 - 59 = 40

data

00 +60 = 60

data

59+ 60 = 99

data

## 12.14 Reference Modification

Problems:

Reference modified operands that hold dates have the same problems as any other date operands when involved in comparisons or arithmetic. They can be fixed in the same ways.

`    move record-yy-date(8:2) to account-year`

However, it is possible to use a date data item as one of the modifiers, although this is a rare construct:

```    move record(yy: data) to this-year-data
move record(start: yy) to accumulated-data```

If the reference modifier is a two-digit year, the code fails for the year 2000, as neither modifier can be zero. The COBOL compiler does not fail, but the logic is wrong.

##### How to fix:

In a similar way to fixing subscripts, adjust the offending reference modifier to run in sequence from 1 through 99. For example, for the window 1960-2059: for dates in the 1900s, subtract 59 from the modifier, and for dates in the 2000s, add 60 to the modifier.

## 12.15 Constructs Using Keys

SmartFix does not address any constructs that use keys, which might be dates and whose sequence might be significant. These constructs include:

• Tables

• SORT and MERGE statements

• SEARCH statements

• Statements operating on indexed files, such as READ and WRITE