说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Delphi系列的Y2K问题

HTML文档下载 WORD文档下载 PDF文档下载
Delphi系列的Y2K问题

Delphi发展至今,已经是第五版本了。尽管各个版本有大大小小的Bug

但疵不掩暇,她还是赢得了广大程序员和编程爱好者的追随和爱戴。随着2000年的逼近, Y2K的一系列问题和各种解决方案也就随之提到日程上来。对编程者来说,我们现在关心的焦点是:Delphi系列有没有Y2K问题呢?

答案当然是肯定的。从 Delphi4 起,Inprise 公司就在系统单元 Sysutils. pas(dcu)中增加了TwoDigitCenturyWindow 这一关键词。它表示从当前年份起加到两位数的年份的数值

缺省为50(年)

也就是说允许Y2K拖后50年才发生。可以这样举一简单的例子:

当前日期为 1999年

调用 FormatDatetime(LongdateFormat

'20-11-04') 为 2020年11月4日。而 FormatDatetime(LongdateFormat

'50-11-04') 却为 1950年 11月4日 而不是 2050 年11月4日。

因此,现在的Y2K问题方案只是在争取时间,而没有彻底解决. 理想的解答是到了 2000年,年份的输入和表示应该是4位数,而不是两位,这样才能除去世纪之交的二义性。

沿着这一思路 Delphi5中最重要的插件 MIDAS 3.X(多层分布式应用服务)

也是建立在这一时间差基础之上的

它往往和 BDE 的Y2K 修正日期范围联系在一起。需要注意的是:运行时(RTL)控件,Inspire 建议在日期多应用场合,如出生登记,到期付款凭证等事务处理应用时,可根据自己的实际需要来设定(TwoDigitCenturyWindow) 这一初始值,最好实在窗口建立时,及 OnCreate 事件里面设置。Inprise 建议用 100年的世纪窗口(the century window)(相对2000年以前)

大部分程序员都喜欢这样设 TwoDigitYearCenturyWindow := CurrentYear - 1950。

100年的世纪窗口(the century window)应作如下解释 :

设 TwoDigitCenturyWindow := 20

那么从现在起,时间支持是20年,其中80年应为过去时间。如:当前时间是 1999年,FormatDatetime(LongdateFormat

'18-11-04') 为 2018年11月4日,超过了期限

FormatDatetime(LongdateFormat

'20-11-04') 为 1920年11月4日。

在标准控件中,与日期输入有关的插件是 TMaskEdit.及其派生的子类。TdateTimePicker 插件在没有安装最新的微软 Visual Dev 6.0 以前,到了2000年2月29日时,不能显示正确的日期。另外由于操作系统的原因,COMCTL32.DLL如果不更新到 4.72.2106.4 版本(及以后),那么在 NT 4 或视窗 95 操作系统上

TdateTimePicker 将会用1752 替换所有的奇数。

在数据库控件中,漏斗和过滤(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的"字串-日期"转换过程。

因此

Delphi IDE 环境和 DBExplorer 都在安装时设定了50 年的世纪窗口,其设定对独立运行的 SQL Explorer.exe 也有效,在数据浏览时的"2-4"年份转换都是这样设定. 不过,这些值是可以修改的。IDE 的注册表项为

HKEY_CURRENTUSER\Software\Borland\Delphi\4.x\ Globals\TwoDigitYearCenturyWindow

.

DBExplorer.EXE 的注册表项为

HKEY_CURRENTUSER\Software\Borland\Database Explorer\2.x\DBXForm\TwoDigitYearCenturyWindow

.

如果将TwoDigitYearCenturyWindow变为0,那么 Delphi3、Delphi4、Delphi5 对日期的解释都将一模一样只处理两位数年份。

J-MIDAS (Java Midas) 和 J-TClientDataSet 是依靠 JBUILDER 引擎对日期格式进行解释,所以对两位数的年份,JBUILDER 只保留了 20 年的有效期。

现在回头来看一下 Delphi 3。由于先天不足,对仍还在使用他的程序员们来说,多少是有些失望。不过,如果进行一番改造,再把 BDE 升级到 5.1 以上,或用 ADO 2.1 代替 BDE,还是可以正常在低档机上披星戴月,披挂上阵。

我们先看一下 Delphi 3 中对年份处理的 EraToYear 函数。该函数返回一符号整形值。定义如下:

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;

我们看到,Delphi 对 2000 年并未加以考虑,其中 Year 获取年份的后两位。这样的话,到了2000 年,日期将回到从前。故而,必须将此函数加以修改,以便使我们的日期转换能通过2000 年。首先,按照 Delphi 一贯的兼容性做法,应该在单元头部声明一 TwoDigitCenturyWindow 的 Byte 变量。在单元初试化时(initialization)

把其附值为 50。其次,对 EraToYear 做如下改动:

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;

然后对 ScanDate 函数做相应的处理,以使其适应 2000 年过度。

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

.....

由此,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 就更好了。

Whois 示例程序-VB资料 Winsock Terminal示例程序 -VB资料 WinSock断开导致客户端问题-VB资料 把Outlook信箱中的附件另存为 -VB资料 保证连网计算机时间同步-VB资料 编写网络寻呼机 -VB资料 编制自已的电话录音小程序-VB资料 程序中如何启动默认的拨号连接-VB资料 打开浏览器并进入指定网址-VB资料 得到用户的IP地址 -VB资料 电话拨号 -VB资料 电子邮件的标准格式 (RFC 822)-VB资料 断开拨号网络的连接-VB资料 断开与 Internet 的连接 -VB资料 发送电子邮件附件-VB资料 VB获得用户网络登录名 基 于Win95 的VB5 串 口 通 信 程 序 基于Win95的VB5串口通信程序 检测运程数据传送的断线-VB资料 简单电子邮件发送程序-VB资料 VB建立拨号联接 -VB资料 将所有窗口最小化-VB资料 VB利用IE控件访问Internet VB利用IE控件设计简易浏览器 VB利用Mscomm32控件判断MODEM是否打开,或者正在工作,并且判断拨号时是否遇忙音 VB利用TAPI进行电话拨号 利用VB访问Internet 利用VB设计聊天室 利用Visual Basic实现无线通讯 VB利用Winsock控件实现局域网通信 VB如何从 Internet 上取回某一个网页的內容? xml里有什么method可以取得子节点在父节点中的位置(序号)? please help me 怎么样才可以把系统存储过程的结果写到结果集里? 如何声明和使用自定义对象(如:Tdataset)的事件(beforecancel)?? 一个奇怪的问题? 各位兄弟,谁知道哪里有pb7的下载? 天呐 我提的问题从来没人回答 SQL Server小小问题 请问那里有DELPHI第二张光盘下载! 如何是使用describe来获取datawindow中的带区参数? 谁有早期的TeeChart5.ocx,文件大小为2,576,384,发行日期在2001-06-17号以前的,我这里有个crack软件,但是新下载的不行,所以重金寻求!!! 请问C语言中有字符串查找函数吗? 请问如何动态的改变应用程序的图标,一定给分 Query主从表编辑问题,从不丢失! 急急急!!!! 高分求禁止IE的自动谈出的广告,有个软见也行,或者告诉实现方法。请告诉下载的网址。 打印一些清单在delphi中用哪些控件比较好? 如何打印到文件 如何得到WINDOWS的拼音字库 如何在BCB中进行SDK编程? 一个简单关于对话框的问题------->> 用asp将图片插入数据库,到底错在哪?苦恼啊!以前这个也通过了(win2000server+Sql7.0)但...(高分!!!!) 为什么我在Access2000的mdb中只能最多得到一条记录? 男人25岁就大吗? 关于 C 类IP的屏蔽 配置为COM+组件后,CoCreateInstance 失败! 关于C 类 IP的屏蔽 有谁知道本.拉登的QQ,俺找他有事?重奖`~~~~~~~~~~~~~~~~~~~! 有没有人告诉我,HTTP头跟正文中间夹的什么? 请问asp和php能访问webservice吗??? 如何一打开NOTE客户端就执行我的数据库(不能设书签)? true dbgrid控件怎么使一个网格又下拉的列表弹出来 关于计数器的代码 那里有含有K线图的图表控件和像OFFICE的工具栏控件下载? 十万火急!如何在Dialog上显示Menu??(我只能给到27分了) 十万火急!如何在Dialog上显示Menu??(我只能给到27分了)十万火急! 问一下,笔记本上的软驱通用吗? maskedit的问题? delphi中报表的问题 关于常用的几种压缩编码? tomcat启动出错,请问什么原因? 一个小问题。回答就给分? 在JSP页面中,能否嵌入ActiveX控件 增加控件的成员变量对程序有什么影响?会使EXE变大吗? shr 是什么意思? 我想用delphi删除一文件夹下面的全部文件,我可以删除一条记录,但无法自动删除全部,数据,我该如何做??? 77分征收四个Delphi中buttons的bmp图标--顶张、下张、上张、末张! 有谁用C++Builder做过corba SQL Server编程求解!!!!! 请问如何测试C#代码的运行瓶颈以便进行优化 80端口是干什么用的 我快要疯了!有关最简单的mdb数据库连接也出问题 1*2*3*4*5 221*2*3*4*5 22 十,一,X,÷ 用12345十一X÷最后等于22 花生是不是又称为长生果? 用一根长48厘米的铁丝焊接长一个长方体,已知长,宽,高的比是3:2:1,求这个长方体的表面积和体积. 一个长方体的表面积是84平方厘米,把它割成三个相等的正方体,每个正方体的表面积是( )平方厘米.(要算式) 书为什么会被人类称为“长生果”? 棱长是a的两个小正方体拼成一个长方体,长方体的表面积比两个小正方体的表面积之和减少了多少? 一个长方体的棱长之和是36厘米,已知道长是4厘米,宽是3厘米.求这个长方体的表面积.列式计算 沿圆柱的直径把圆柱切成两半后,截面是个正方形,表面积增加50平方分米,圆柱的表面积和体积 一个小正方体的棱长是3cm,用3个这样的小正方体拼成一个长方体,长方体的表面积比3个正方体的表面积之和减少多少平方厘米? 一个长方体的棱长的和是36厘米,它的长和宽都是2厘米,这个长方体的表面积是多少平方厘米?急,我有用 花生的英文名是什么? 有一桶水,用同样大小的瓶子去装,如果灌满8瓶后,桶内还剩七分之六,如果灌满7瓶后,桶内还剩2分之49.这桶水有多少千克 一个长方体的长、宽、高分别是a米、b米、h米.如果高增加3米,新长方体的表面积增加多少平方米? 英语翻译做包装的英文 有一桶水,用同样大小的瓶去装,如果灌满8瓶后,桶内还剩6/7,如果灌满7瓶后,桶 某书店以“20元办会员享受8折优惠”的方式进行促销,你认为在什么情况下办会员卡消费合算? 史努比所在的书的英文名是什么?是叫花生还是叫Snoopy?我想买英文原版的, 实验小学组织春游活动,共有230名师生参加.现在要去公交公司租车,公交公司提供了一下2种车型(数学高手来大巴车:限坐52人,每辆车每天租金250元.中巴车:限坐34人,每辆车每天租金200元.1) 一个长方体的长宽高分别是6米,5米,4米.如果高增加2米,新长方体的表面积比原来增加多少平方米? 有机花生是啥意思? 实验小学师生共198人去春游,有两种车供选.大客车:限乘55人 中巴车:限乘35人大客车租金400元/辆,中巴车租金280元/辆.请设计一个最省钱的租车方案,并算一算租金是多少钱.(要算式+答案) 某书店以“20元办会员卡8折优惠”的方式进行促销,你认为在什么情况下办会员卡和算 一个圆柱,底面半径是3分米,侧面展开是正方形.这个圆柱的表面积是()平方厘米?体积是()立方厘米.把它截成2段,表面积增加了()平方厘米 实验小学六年级的同学们乘大客车去春游,如果每辆车坐60人,则有15人不能上车,如果每辆车多坐5人,恰好多出一辆车,一共有几辆车?一共有多少个学生? 一桶油,第一次用去5分之2,第2次比第1次多2千克,桶里还剩下3千克.这桶油原来有多少千克? 一个圆柱的表面积比侧面积大12.56dm的平方,高是3dm,这个圆柱的体积是多少立方厘米? 三个同样大的正方体拼成一个长方体后,表面积减少了114cm²,这个长方体的表面积是多少平方厘米?要详细的介绍每一步求什么 土豆,芋头这些淀粉类的吃多了会导致长胖啊? 一个长方体的棱长之和是36厘米,长、宽、高的比是5:3:1,这个长方体的表面积是( ),体积是( )谢谢了! 芋头可以和莲藕一起吃吗?我想把芋头,莲藕排骨一起熬汤不知道可不可以?希望有人可以替我解答下~!谢谢咯~!~! 用果实、茎和根给油莎果、南瓜、芋头、红薯、莲藕、萝卜、姜和土豆分类 一个长方体的长、宽、高的比是3:2:1,它的棱长总和是48厘米 ,求此长方体的表面积 藕、洋葱、番薯、胡萝卜、芹菜等植物中,供我们食用的部分分别属于植物的哪一种营养器官?为什么? 已知圆柱底的半径是3dm,高是10dm,求表面积 小客车每辆600元,限乘12人;大客车每辆1300元,限乘30人.共有师生73人,怎样租车最省钱?租金共多少元2门票问题太.信息;门票每人40元,团体票价格如下表.算一算:购票至少需多少元?人数30--50 51-- 莲藕的食用部分是什么 一个圆柱的高是10dm,底面积的半径是3dm,它的表面积是多少 一个圆柱底面直径是20分米,高是6分米,沿着底面直径把圆柱切成两半,这个圆柱的表面积增加了多少? 下列各项中,除哪种植物外,我们食用的部分是植物的茎A藕B马铃薯C甘薯D甘蔗 圆柱底面积半径3dm 求表面积? 落花生名字的由来 下面是一个长方体的展开图,求围成的长方体的表面积和体积.(单位:厘米) 一个长方体的棱之和是36厘米.已知长是4厘米,宽是3厘米.求这个长方体的表面积. 落花生的名字由来 下面是一个展开图求围成长方体的表面积和体积长是7厘米、宽是5厘米、高是3厘米 把一个长10dm,底面半径3dm的圆柱锯成四段小圆柱,表面积增加了多少 《落花生 》名字的来历 求下面长方体的表面积和体积,长2分之1,宽5分之1,高5分之1,要算式,递等式 一个长方体的棱长之和是36厘米.已知长是4厘米,宽是3厘米,求这个长方体的表面积急1 课文《落花生》名字由来五年级语文《落花生》名字的由来. 下图是一个长方体的表面展开图,根据条件,求出这个长方体的表面积和体积. 一个长方体的棱长和是36厘米,已知长是4厘米,宽是3厘米.求这个长方体的表面积.(快!) 一桶水,把水加到原来的2倍,连桶重10千克,要时把水加到原来的4倍,连桶重18千克,桶里原有多少水? 用两个完全一样的长方体平成一个大长方体,这个长方体的表面积最小是多少平方厘米?长方体的长6厘米,宽2厘米, 某书店以“50元办理会员卡,享受七五折优惠“,你认为在什么情况下办理会员卡消费合算 用一根长48厘米的铁丝焊接成一个长方体,已知长、宽、高的比是1:2:3,长方体的表面积是多少?体积是多少 把两个表面积是30平方厘米的正方体,平成一个长方体,这个长方体的表面积是多少?我急用.快 番薯甘薯红薯白薯马铃薯土豆地瓜有什么区别和联系?拒接长篇大论啊...分分类就行了..... 某书吧的会员卡100元一张,会员的消费打八折,那么当消费达到多少元以上时买会员卡比较划算.A.100 B.300 C.500 D.600 将一根长48厘米的铁丝焊成一个长方体,已知长宽高得比是3;2;1,这个长方体的表面积是多少平方厘米
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn