|
一、引 言
Y2K问题即计算机千年虫问题,是困扰全世界的国际性难题。其实质是指60年代以来开发和应用的计算机软件、硬件系统,为了节约存储空间,在日期的年份表示上只采用后两位十进制数字,整个日期字段只有8个字符的宽度。当时间进入到2000年1月1日时,就会出现将2000年误认为是“00”(或1900)年的问题。这样,就会影响计算机系统的正常运行,一切与日期有关的过程,如日期的计算、排序、检索、比较和存取等,都会出现逻辑判断的错误,还有可能造成重大事故,引起整个社会的混乱。
Y2K问题涉及的范围非常广泛,包括决策系统、人事管理、工资管理、财务管理、生产管理、销售管理等信息管理系统。笔者在软件开发实践中,经过详细的分析、研究和反复试验,终于找到了一种在FOXBASE/FOXPRO 程序设计时解决Y2K问题的简便方案。
二、Y2K问题解决方案的基本原理
目前,我国有很多用户正在使用FOXBASE/FOXPRO数据库管理系统。这种数据库管理系统的日期型字段为八个字符宽度,只能输入表示年份的后两位十进制数字。另外,FOXBASE/FOXPRO的日期函数也只有八个字符宽度,只能显示年份的后两位数字。因此,在FOXBASE/FOXPRO数据库系统中,会产生Y2K问题。笔者的解决方案的基本原理是: 拓展“日期”字段的宽度,扩大“日期”字段的信息域。一般用户是无法修改FOXBASE/FOXPRO数据库系统的“日期型字段”的宽度(固定为八个字符)的。但是,如果将“日期”字段的数据类型由“日期型(D)”改为“字符型(C)”,然后用“2000”或“2001”等替换原来的“00”,问题就迎刃而解了。字符型数据同样可以进行计算、排序、检索、比较和存取等操作。这样,就不会发生逻辑判断错误了。对于数据库系统的日期函数,同样可以设计一个“自定义函数”进行相应的修改。
三、拓展“日期”字段的宽度
在FOXBASE/FOXPRRRO数据库管理系统中建立数据库文件时,如果要设置“日期”字段(或与日期有关的字段,如:出生年月、开始工作时间等),可将字段的数据类型选择为“字符型(C)”而不要选择为“日期型(D)”,并且将字段宽度定义为10个字符。这样,用户就可以输入用四位十进制数字表示年份的日期数据了,如:“1998-12-28”。2000年1月1日到来时,就可以输入“2000-01-01”表示的日期了。字符型字段和日期型字段一样,可以进行逻辑比较运算。这样设计的数据库文件,在进行与日期有关的操作时,就不会出现混乱了。对于以前设计的正在运行的数据库管理系统,同样可以将数据库文件中的“日期”字段“日期型(D)”改成“字符型(C)”,将字段宽度设置为10个字符。当时间进入2000年1月1日时,就可以输入“2000-01-01”表示日期了,再对应用软件作一些相应的修改,一般是可以正常运行的。修改的步骤如下:
(1) 打开要修改的数据库文件;
(2) 键入命令:MODIFY STRUCTURE;
(3)用光标移动键将光标移到“日期”字段(或其他与日期有关的字段)的“TYPE(字段类型)”上;
(4) 按空格键选择字段类型为“C(字符型)”;
(5)将光标移到“日期”字段的“Width(字段宽度)”定义域上,由8个字符改成10个字符的宽度;
(6)日期格式可设为“YYYY-MM-DD”,对应用软件修改的工作量可以少一些;
(7)存盘后退出系统,修改完毕。
数据库中2000年以前的“日期”如果要和2000年以后的“日期”作比较运算,也要将字段类型由“日期型”改成“字符型”,将表示年份的数字由两位改为4位,在年份的前面加上“19”,总共要设置10个字符的长度。格式可设置为“YYYY-MM-DD”,如“1998-12-31”,然后再对应用程序作一些相应的修改,就可以安全进入2000年了。
[例] 我们可以用上述方法建立如下工资档案数据库GZL1.DBF。
我们将“工作日期”字段设置为“字符型”,经试用表明,同样可以对“工作日期”字段进行计算、排序、比较、检索、存取等操作。如查询在某一日期的上限值和某一日期的下限值之间参加工作的职工数据,计算职工的工龄等。时间进入2000年1月1日后, 就可以输入“2000”表示年份,不会产生日期计算的错误和混乱了。
工资档案数据库文件的结构和数据如表1。
对于上面的工资档案数据库,可以设计一个组合条件查询程序,输入工作日期的上限值和下限值以及职务,就能够反复查询在这两个日期间参加工作的指定职务的职工记录,查到时,显示该记录的所有数据。程序名为GZL5.PRG,清单见附录。计算工龄时,日期要加上括号,就能得到正确的结果。如(1999-01-05)-(1969-01-05)=30(年)。
四、修改数据库系统的日期函数
如果要使用FOXBASE/FOXPRO 的日期函数,就要设计一个自定义函数CATE()来代替原来的日期函数DATE()。先将原来的日期函数转换成字符型数据,然后用“2000”替换“00”,将其存放在自定义函数CATE()中,再将自定义函数CATE()中的字符型日期数据和用户输入的字符型日期数据进行比较运算。进入2000年以后,程序设计时就可以调用这个自定义函数。自定义函数CATE()中的字符型日期数据的格式为:YYYY-MM-DD,如2000年1月1日可表示为“2000-01-01”,用户也要以相同的格式输入日期数据。如果用户用“ACCEPT”命令输入数据,则所有键入的字符,系统都认为是字符型数据;如果用“INPUT”命令输入数据,则字符型数据要用引号括起来。自定义函数的程序清单见附录。
五、结束语
表1 工资档案数据库gzl1.dbf结构
| 字段名称 |
字段类型 |
字段宽度 |
小数位数 |
| 姓 名 |
c(字符型) |
8个字符 |
|
| 性 别 |
c(字符型) |
4个字符 |
|
| 职 务 |
c(字符型) |
10个字符 |
|
| 工作日期 |
c(字符型) |
10个字符 |
|
| 基本工资 |
n(数值型) |
8个字符 |
2个字符 |
| 职务补贴 |
n(数值型) |
8个字符 |
2个字符 |
上述方案对于在FOXBASE/FOXPRO数据库管理系统中设计新的数据库文件和修改以前的数据库文件的用户是很方便实用的。这是一种比较彻底的解决方案,因为这种方案直接拓展了日期字段的宽度,扩大了“日期”的信息域,将表示年份的信息域扩展到了4个字符。用这种方案设计或修改的数据库文件,决不会产生Y2K问题。这种方案的缺点是抛弃了“日期型数据”,某些要求必须使用“日期型数据”的命令和函数以及某些不能使用“字符型数据”的命令和函数在对日期数据操作时将不能使用。应当注意的是,用自定义函数代替日期函数时,每年1月1日都要将替换值(2000)修改一次,如:2001年1月1日后应改为“2001”。
表2 工资档案数据库gzl1.dbf文件数据
| 姓 名 |
性别 |
职务 |
工作日期 |
基本工资 |
职务补贴 |
| 赵 琳 |
女 |
科长 |
1980-03-25 |
250.00 |
80.00 |
| 钱深清 |
男 |
总工程师 |
1978-09-10 |
350.00 |
100.00 |
| 孙详理 |
男 |
工程师 |
1969-04-20 |
270.00 |
70.00 |
| 李 云 |
男 |
工人 |
1960-07-28 |
300.00 |
30.00 |
由此可见,Y2K问题这个困扰全世界的“不大不小”的难题,如果用统一的模式来解决,确实是非常复杂的艰巨工程,因为各种程序设计语言和应用软件多达成千上万种,要用一种方案来解决所有的问题,其难度可想而知。但是,如果化整为零,各个击破,在各个较小范围的具体应用领域内,问题的解决就会简单一些,因为这些程序设计语言和应用软件本身总会提供一些拓展字段宽度和转换数据类型的方法。
[注] 本文提供的程序已在486/586计算机上,FOXBASE2.1 和FOXPRO2.5 环境下调试通过。FOXPRO3.0以下版本都存在2000年问题。
六、附录
程序清单:
C:\〉 TYPE C:\FOX\GZL5.PRG
**用组合条件查询工资档案数据库GZL1.DBF程序GZL5.DBF
SET TALK OFF
@ 3,0 CLEAR
@ 3,10 SAY'正在进行的操作是按职务和工作日期组合查询职工数据。‘
USE GZL1.DBF
@ 8,0 CLEAR
STORE SPACE(10) TO ZW
STORE SPACE(10) TO D1,D2
@ 8,5 SAY'请输入欲查询职工的职务:' GET ZW
@ 9,5 SAY'请输入欲查询职工工作日期的上限日期:' GET D1
@ 10,5 SAY'请输入欲查询职工工作日期的下限日期:' GET D2
READ
LOCATE FOR 职务=ZW.AND.工作日期>=D1.AND.工作日期<=D2
IF EOF()
@ 20,0 CLEAR
@ 20,10 SAY'没有符合条件的职工,按任一键返回!'
WAIT
USE
ELSE
SET FILTER TO 职务=ZW.AND.工作日期>=D1.AND.工作日期<=D2
LIST
ENDIF
WAIT
DD=' '
@ 10,0 CLEAR
@ 10,10 SAY'还要查询其他满足条件的职工吗(Y/N)?' GET DD
READ
IF UPPER(DD) ='Y'
CLEAR
DO GZL5.PRG
ENDIF
USE
RETURN
C:\〉TYPE C:\FOX\CATE.PRG
**2000年日期转换自定义函数CATE.PRG,日期格式:YYYY-MM-DD.
SET TALK OFF
DATEC=DTOC(DATE())
M1=SUBSTR(DATEC,1,2)
D1=SUBSTR(DATEC,4,2)
RETURN '2000-'+M1+'-'+D1
C:\〉
|