Opened 5 years ago
Last modified 3 years ago
#243 new enhancement
Dates with 2-digit year values after 2129 are assumed to be in the 20th century (e.g, 1930).
| Reported by: | Gary Dixon | Owned by: | Eric Swenson |
|---|---|---|---|
| Priority: | major | Milestone: | |
| Component: | General | Version: | MR12.7 |
| Keywords: | Cc: |
Description
The Y2K change for interpreting 2-digit year numbers will have problems for years later than 2129. A date like 30-12-18 would be interpreted as 1930-12-18 according to algorithm used in the current convert_date_to_binary_ code. It may be appropriate to interpret years before 1960 (the year of early Multics design papers) as being in the 21 century, rather than in the 20th century.
The current code treats all 2-digit years < 30 as being in 21st century (e.g., 2125), and years in range 30 to 99 as being in the 20th century (e.g., 1950).
The following example shows where the breakpoint lies in the current code:
clock ^yc-^my-^dm 30-10-12 30-10-12 r 11:55 0.059 0 level 2 clock iso_date [clock ^yc-^my-^dm 30-10-12] 1930-10-12 r 11:55 0.377 0 level 2 clock ^yc-^my-^dm 29-10-15 29-09-15 r 11:56 0.054 0 level 2 clock iso_date [clock ^yc-^my-^dm] 2029-09-15 r 11:56 0.345 0 level 2
Change History (2)
comment:2 by , 3 years ago
In general, there has to be a 100-year window (that will usually cross a century boundary) and a tiny bit of code needs to determine which century needs to be associated with the two-digit year to make it fall within the 100-year window. It is possible for the system to determine the position of the 100-year window - either statically or dynamically (if dynamically, probably based on the current year).
A system-imposed 100-year window might be appropriate for the majority of users, but I'd like to see users be able to set the position of the 100-year window for conversions of two_digit_years to four_digit_years in their processes. This could be done by having a system-wide default that could be overridden for a project, a user, and/or a process.
A 100-year window could be defined by one value - the starting year. But since I want to support the idea of a window that automatically moves each year, I prefer to define the window by two values: A context year and the number of years before the context year, that establishes the start of the 100-year window. There should also be an active function which takes arguments so that the user could have different 100-year windows in a single exec_com. A (very simple) algorithm is described in my previous note. The simple algorithm is implemented in the following exec_com. This exec_com is just to illustrate the algorithm, so it doesn't do any checking or validation of its arguments. Nonetheless it looks long because of comments and the code to gather arguments. The actual operational part is only four lines (and would be shorter in a language that allowed more flexible string manipulation).
Here are the operational four lines:
set context_year &[minus &(context_year) &(years_before)] &set cc &[substr &(context_year) 1 2] &if &[nless &(yy) &[substr &(context_year) 3 2]] &then &set cc &[plus &(cc) 1] &return &(cc)&(yy)
And here is an active function exec_com that gathers (but doesn't check) arguments:
&version 2
&- This exec_com converts a two-digit year to a four-digit year by
&- prepending the appropriate two-digit century
&-
&- Syntax: ec two2four-digit-year.ec 2-digit-year {-control_args}
&-
&- As an AF [ec two2four-digit-year.ec 2-digit-year {-control_args}]
&-
&- Required argument: 2-digit-year - The two-digit year to be converted
&-
&- (Optional) Control arguments:
&-
&- '''-years_before''' ''an_integer'' - The century is selected so that the
&- four-digit year will be within a 100-year block. The first year of
&- the 100-year block is '''years_before''' prior to the '''context_year'''.
&- '''years_before''' is intended to be in the range 0 <= '''years_before''' <= 99.
&- If this parameter is not supplied, it defaults to 49 (which means
&- that the 100-year block extends from 49 years before the '''context-year'''
&- through 50 years after the '''context_year''')
&-
&- '''-context_year''' ''four-digit-year'' - that provides the context for the
&- selection of the appropriate century. If '''years_before''' is in the range
&- 0 <= '''years_before''' <= 99, then '''context_year''' will be within the
&- 100-year block. If this parameter is not supplied, it defaults to the
&- current four-digit year.
&-
&set arg_no 1
&set last_arg_no &n
&set years_before 49
&set context_year &[long_year]
&-
&label loop_over_arguments
&if &[ngreater &(arg_no) &(last_arg_no)] &else &goto process_args
&goto start_work
&-
&label process_args
&if &[equal &[substr &(&(arg_no)) 1 1] -] &then &do
&if &[equal &r(&(arg_no)) "-years_before"] &then &do
&set arg_no &[plus &(arg_no) 1]
&set years_before &(&(arg_no))
&end
&else &if &[equal &r(&(arg_no)) "-context_year"] &then &do
&set arg_no &[plus &(arg_no) 1]
&set context_year &(&(arg_no))
&end
&end
&else &set yy &(&(arg_no))
&set arg_no &[plus &(arg_no) 1]
&goto loop_over_arguments
&-
&label start_work
&- adjust context_year to make it the start of the 100-year window by
&- subtracting the years_before argument.
&set context_year &[minus &(context_year) &(years_before)]
&-
&- cc = the left two digits (the century digits) of the adjusted
&- context_year
&set cc &[substr &(context_year) 1 2]
&-
&- if two_digit_year < the right two digits of the adjusted
&- context_year, then cc = cc + 1
&if &[nless &(yy) &[substr &(context_year) 3 2]] &then &set cc &[plus &(cc) 1]&-
&- return four-digit year as cc concatenated with two_digit_year
&return &(cc)&(yy)
In summary, I propose:
- an implementation that (optionally) can automatically adjust the 100-year window each year
- allows the designation of a static 100-year window that only changes when manually adjusted
- provides a system default that can be overridden on a per project, per user, or per process basis
- provides an active function so that an exec_com author can set appropriate years_before and context_year arguments each time he uses a two-digit year.

Suggestion for a general facility for converting a two-digit year to a four-digit year
Convert a two-digit year to a four-digit year by prepending the appropriate two-digit century
Required Parameter
two_digit_year:: The two-digit year to be converted
Optional Parameters
years_before:: An integer. The century is selected so that the four-digit year will be within a 100-year block. The first year of the 100-year block is years_before prior to the context_year. years_before is intended to be in the range 0 <= years_before <= 99, however there might be some cases where it is useful to have years_before < 0 or > 99 (although I can't think of any). If this parameter is not supplied, it defaults to 49 (which means that the 100-year block extends from 49 years before the context-year through 50 years after the context_year)
context_year:: A four-digit year that provides the context for the selection of the appropriate century. If years_before is in the range 0 <= years_before <= 99, then context_year will be within the 100-year block. If this parameter is not supplied, it defaults to the current four-digit year.
start_year = context_year - years_before/* If the language allows arithmetic with character variables and allows the result to replace one of the operands, start_year need not be a separate variable, it could be the modified context_year */
yy = the right two digits of start_year/* If the language allows numeric comparisons with part of a character variable, yy need not be a separate variable, it could be the right two digits of start_year */
cc = the left two digits (the century digits) of start_year/* If the language allows numeric operations on part of a character variable and allows the result to replace that part of the character variable, cc need not be a separate variable, it could be the left two digits of start_year */
if two_digit_year < yy, then cc = cc + 1returned four-digit year is cc concatenated with two_digit_year/* If the language allows substitution of characters in a character variable, the return value need not be a separate variable, it could be start_year with two_digit_year replacing the right two digits of start_year */