⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 122902_05.htm

📁 对于学习很有帮助
💻 HTM
字号:
<html>

<head>
<link REL="stylesheet" HREF="/style.css" TYPE="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>计算机世界日报:
Delphi 系列的 Y2K 问题
</title>
<!--***********-->
</head>

<body bgcolor="#FFFFFF" >














<p><br>
<font color="#b904e8"><b><em><a href="class.htm">返回</a></em></b></font>
<center>
<font color="#0000c0"><h2>
Delphi 系列的 Y2K 问题
</h2></font>
<h3>
云南昆明市江岸小区
<br>吴中卫
</h3>
</center>
<p><font color="#ffffff">----</font>

Delphi发展至今,已经是第五版本了。尽管各个版本有大大小小的Bug,但疵不
掩暇,她还是赢得了广大程序员和编程爱好者的追随和爱戴。随着2000年的逼近,
Y2K的一系列问题和各种解决方案也就随之提到日程上来。对编程者来说,我们现
在关心的焦点是:Delphi系列有没有Y2K问题呢?
<p><font color="#ffffff">----</font>
  答案当然是肯定的。从 Delphi4 起,Inprise 公司就在系统单元 Sysutils.
pas(dcu)中增加了TwoDigitCenturyWindow 这一关键词。它表示从当前年份起加到
两位数的年份的数值,缺省为50(年),也就是说允许Y2K拖后50年才发生。可以这样
举一简单的例子:
<p><font color="#ffffff">----</font>
   当前日期为 1999年,调用 FormatDatetime(LongdateFormat,'20-11-04') 为
2020年11月4日。而 FormatDatetime(LongdateFormat,'50-11-04') 却为 1950年
11月4日 而不是 2050 年11月4日。
<p><font color="#ffffff">----</font>
 因此,现在的Y2K问题方案只是在争取时间,而没有彻底解决. 理想的解答是到
了 2000年,年份的输入和表示应该是4位数,而不是两位,这样才能除去世纪之交
的二义性。
<p><font color="#ffffff">----</font>
   沿着这一思路 Delphi5中最重要的插件 MIDAS 3.X(多层分布式应用服务),也是
建立在这一时间差基础之上的,它往往和 BDE 的Y2K 修正日期范围联系在一起。需
要注意的是:运行时(RTL)控件,Inspire 建议在日期多应用场合,如出生登记,到
期付款凭证等事务处理应用时,可根据自己的实际需要来设定(TwoDigitCenturyWindow)
这一初始值,最好实在窗口建立时,及 OnCreate 事件里面设置。Inprise 建议用
100年的世纪窗口(the century window)(相对2000年以前),大部分程序员都喜欢这
样设 TwoDigitYearCenturyWindow := CurrentYear - 1950。
<p><font color="#ffffff">----</font>
100年的世纪窗口(the century window)应作如下解释 :
<p><font color="#ffffff">----</font>
设 TwoDigitCenturyWindow := 20,那么从现在起,时间支持是20年,其中80年应为
过去时间。如:当前时间是 1999年,FormatDatetime(LongdateFormat,'18-11-04')
为 2018年11月4日,超过了期限,FormatDatetime(LongdateFormat,'20-11-04') 为
1920年11月4日。
<p><font color="#ffffff">----</font>
   在标准控件中,与日期输入有关的插件是 TMaskEdit.及其派生的子类。TdateTimePicker
插件在没有安装最新的微软 Visual Dev 6.0 以前,到了2000年2月29日时,不能显
示正确的日期。另外由于操作系统的原因,COMCTL32.DLL如果不更新到 4.72.2106.4
版本(及以后),那么在 NT 4 或视窗 95 操作系统上,TdateTimePicker 将会用1752
替换所有的奇数。
<p><font color="#ffffff">----</font>
在数据库控件中,漏斗和过滤(Filter)函数将 '00-1-1' 转换到 ’1900-1-1', 
在用 Locate 指令时,'00-1-1' 到 '99-1-1'期间将被转换成 '20XX-1-11','30-1-1'
到 '99-1-1' 期间将被转换到 '19XX-1-1'.原因是 Locate 使用变数(variants)进行
定位,日期定位并被没有通过 Delphi 的运行时库进行,而是调用了 WIN32 API 函数
转换到日期类型。这是由于 OLE 自动服务器对象的 OLE 字串转换到日期类型的规则
造成的。尤其是当你调VarToDateTime 函数去试图从一包含日期的字串分离出 TDateTime
类型时。一些数据库操作在内部使用变体来提取实际数据,TDataset.Locate 和 Tparams
类将依照 OLE 变体转换规则来实施具体操作,而非通过Delphi的"字串-日期"转换过程。
<p><font color="#ffffff">----</font>
   因此,Delphi IDE 环境和 DBExplorer 都在安装时设定了50 年的世纪窗口,其设定
对独立运行的 SQL Explorer.exe 也有效,在数据浏览时的"2-4"年份转换都是这样设定.
不过,这些值是可以修改的。IDE 的注册表项为
<pre>
"HKEY_CURRENTUSER\Software\Borland\Delphi\4.x\
 Globals\TwoDigitYearCenturyWindow". 
DBExplorer.EXE 的注册表项为 
"HKEY_CURRENTUSER\Software\Borland\Database Explorer\
2.x\DBXForm\TwoDigitYearCenturyWindow".
</pre>
<font color="#ffffff">----</font>
   如果将TwoDigitYearCenturyWindow变为0,那么 Delphi3、Delphi4、Delphi5 对日期
的解释都将一模一样只处理两位数年份。
<p><font color="#ffffff">----</font>
   J-MIDAS (Java Midas) 和 J-TClientDataSet 是依靠 JBUILDER 引擎对日期格式进行解释,所以对两位数的年份,JBUILDER 只保留了 20 年的有效期。
<p><font color="#ffffff">----</font>
现在回头来看一下 Delphi 3。由于先天不足,对仍还在使用他的程序员们来说,多少是有些失望。不过,如果进行一番改造,再把 BDE 升级到 5.1 以上,或用 ADO 2.1 代替 BDE,
还是可以正常在低档机上披星戴月,披挂上阵。
<p><font color="#ffffff">----</font>
  我们先看一下 Delphi 3 中对年份处理的 EraToYear 函数。该函数返回一符号整形值。
定义如下:
<pre>
 function EraToYear(Year: Integer): Integer;
 begin
   if SysLocale.PriLangID = LANG_KOREAN then
   begin
 if Year <= 99 then
   Inc(Year, (CurrentYear + Abs
(EraYearOffset)) div 100 * 100);
 if EraYearOffset > 0 then
   EraYearOffset := -EraYearOffset;
   end
   else
 Dec(EraYearOffset);
   Result := Year + EraYearOffset;
 end;
</pre>
<font color="#ffffff">----</font>
我们看到,Delphi 对 2000 年并未加以考虑,其中 Year 获取年份的后两位。这样的话,到了2000 年,日期将回到从前。故而,必须将此函数加以修改,以便使我们的日期转换能通过2000 年。首先,按照 Delphi 一贯的兼容性做法,应该在单元头部声明一 TwoDigitCenturyWindow
的 Byte 变量。在单元初试化时(initialization),把其附值为 50。其次,对 EraToYear 做
如下改动:
<pre>
function EraToYear(Year: Integer): Integer;
begin
  if SysLocale.PriLangID = LANG_KOREAN then
  begin
if Year <= 99 then
Begin
  if Year > TwoDigitYearCenturyWindow then
 Inc(Year, (CurrentYear + Abs(EraYearOffset)) 
	div 100 * 100)
  else
 Inc(Year, (2000 + Abs(EraYearOffset))
 div 100 * 100);
end;
if EraYearOffset > 0 then
  EraYearOffset := -EraYearOffset;
  end
  else
Dec(EraYearOffset);
  Result := Year + EraYearOffset;
end;

</pre>
<font color="#ffffff">----</font>
然后对 ScanDate 函数做相应的处理,以使其适应 2000 年过度。
<pre>
function ScanDate(const S: string; var Pos: Integer;
  var Date: TDateTime): Boolean;
var
  DateOrder: TDateOrder;
  N1, N2, N3, Y, M, D: Word;
  EraName : string;
  EraYearOffset: Integer;

.....

begin
  Y := 0;
  M := 0;
  D := 0;
  Result := False;
  DateOrder := GetDateOrder(ShortDateFormat);
  EraYearOffset := 0;
  if ShortDateFormat[1] = 'g' then 
 // skip over prefix text
  begin
ScanToNumber(S, Pos);
EraName := Trim(Copy(S, 1, Pos-1));
EraYearOffset := GetEraYearOffset(EraName);
  end
  else
if AnsiPos('e', ShortDateFormat) > 0 then
  EraYearOffset := EraYearOffsets[1];
  if not (ScanNumber(S, Pos, N1) and ScanChar(S, 
	Pos, DateSeparator) and
ScanNumber(S, Pos, N2)) then Exit;
  if ScanChar(S, Pos, DateSeparator) then
  begin
if not ScanNumber(S, Pos, N3) then Exit;
case DateOrder of
if not ScanNumber(S, Pos, N3) then Exit;
case DateOrder of
  doMDY: begin Y := N3; M := N1; D := N2; end;
  doDMY: begin Y := N3; M := N2; D := N1; end;
  doYMD: begin Y := N1; M := N2; D := N3; end;
end;
if EraYearOffset > 0 then Y := EraToYear(Y);

{ 在这里 Century Window 发挥作用 }
if Y <= 99 then
Begin
  if Y > TwoDigitYearCenturyWindow then
 Inc(Y, CurrentYear div 100 * 100)
  else
 Inc(Y, 2000);
end;
  end else
.....

</pre>
<font color="#ffffff">----</font>
由此,Delphi 3 已经可以渡过 2000 年了,不过,Inprise 建议
Delphi 3 的版本为 3.02。如果是 3.0 极其以下(不支持 MIDAS 1.,X)
象Delphi 1.x(16位)、Delphi 2.x(32位)不如直接升级到 Delphi 4.02.
有条件的爱好者用 Delphi 5 就更好了。



 



<p align="right"><small><em>中国计算机世界出版服务公司版权所有</em></small> 
<br>
</p>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -