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

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

高性能动画!HTML5 Canvas JavaScript框架KineticJS Swift最酷炫的七大功能 微信开发者大会讲师介绍:柳峰与你一起玩转公众平台应用开发 TIOBE 2014年7月编程语言排行榜:仅发布1月,Swift进Top 20! 艾格拉斯CEO王双义:手游自研引擎的荣耀之路 以招行为例,深圳云软黄榕振谈微信公众帐号企业应用高级开发 来自前苹果高管Heidi Roizen的经验之谈 【短讯】Dropbox、微软OneDrive打不开,国内用户该如何应对? 5分钟弄懂Docker! RakNet:被OculusVR收购的跨平台游戏网络引擎 Qualcomm业务拓展副总裁沈劲:智能终端的延伸 苹果发布Xcode 6 Beta 3,Swift迎来重大更新! Linkedln技术高管Jay Kreps:Lambda架构剖析 《近匠》极光推送:聚焦巨头无法快速转身的领域 Babylon.js:拥有微软背景的开源3D游戏引擎 EMC 2014存储布局及十大新技术要点 腾讯推出零流量地图 离线实现公交步行导航 Atmel 1.4亿美元收购Newport Media 巩固物联网产品线 微信大会首批议程出炉 深度解析招行服务号是如何炼成的? 指尖上的阅读:MIT开发盲人专用设备FingerReader 从桌面到移动:异构计算翻天覆地的技术变革 《近匠》Blueware何晓阳,不做中国的New Relic 全球最杰出的14位程序员 Microsoft、RedHat、IBM、Docker等公司加入Kubernetes社区 Intel携手三星、博通等 建立物联网联盟OIC 一周消息树:微软半年内将终止对Win 7、Office 2010 SP1等产品的支持 深度神经网络DNN的多GPU数据并行框架 及其在语音识别的应用 浪潮通软GSP将打造开放平台 吸引更多ISV加入生态系统 国外安全产品再遭信任危机 安全产品国产化步伐加快 最终幻想XIV的重生--SQUARE ENIX《最终幻想14》制作人吉田直树介绍 如何打造百万级自然增长的微信HTML5应用 Oracle Intermedia Text支不支持中文的模糊查询 我是ORACLE菜鸟,现有一SQL语句(SQL Server语法),想转换成ORACLE语法,请指点 数据库连接问题??????????? 大虾,请看这里看看? vb中字符串中怎么输入双引号(")或单引号(')? 大家帮忙看看为什么这段代码不工作? ████ 这个帖子骂人,请斑竹秉公处理!!!!!!!████ 怎么样让时间加一个差值; 在另一个类中,怎样给Radio或Combobox赋值 ~~~~向各位高人请教三层线程模型,分可以另开贴加。 new出来的idicmpclient的onreply事件怎么响应? 那位大虾帮我看一下这断代码(JSP高分请教) 帮帮忙啦,哪位同志用过mscomm控件做点对点拨号通讯的 AspRunner是个不错的辅助编写ASP页面的工具,请问哪里有破解下载的啊?谢谢了! 在vc#中如何删除目录下的所有文件? 急 关于分级菜单 求救,如何在注册表中得到一个硬件设备(如猫)的驱动文件名称? 一个难题,希望高手能解决,急切等待! 关于网络状况测试的问题 新手上路,问一个很初级的问题,呵呵。。。 请问如何实现在同一个窗口中的自动跳转? 为什么不能调用类? 关于SQL语句求助 如何在asp和asp.net里面共享信息 溢出错误,麻烦来看看! 知道汉字的国标(gb?)码值,如何显示汉子,急求救!!!! 在SQL2000怎样建立全文索 Cannot start SQL Server Agent 能用case when 举一个例子吗?如果工资>1000 职务='处长',如果工资<1000 职务='科员' 如何将从xml文件中读取的文本在网页上保持格式的显示? sql语句求助!1 有宁波考高程的吗?有参加班的吗? 水晶报表问题???高手请进!!!!!! 使用openquery建立视图。急!急!急!急!急!急! 小问提 交个朋友 Blob类型的字段为什么不能做为Lookup或Calculated字段 有谁知道Any to Icon 的 注册码 怎么实现不同文件中的变量互访? ICS 的FTP控件问题:怎样建目录,我这样做不出错,但是就是建不出来: 数据库出错 怎样将weblogic7和MS sql 2000连接起来? sql语句求助! 关于文件关联的问题,不是那么简单的哦.!!!!!! 一个MM每天回家后做的事 [贴图] 我需要得到记录集中的一条记录 关于MODEN的问题 如何编写Delphi的DLL为C++Buider调用? 我将数据库连接作为一个bean封装,怎么样在sevlet中引用它? 源文件,修改?? 我该怎么做? 两磁铁相吸有无支持力?为什么? ∫(3 sin t+sin^2t/1) dt 设矩阵A 的特征多项式为I&E-AI=(&+1)(&+4)^2 ,则 IAI= 若向量a=(1,1),b=(1,-1),c=(-1,2),用ab(ab上有个箭头,打不出来)表示向量c=_______ ∫(3 sin t+sin^2 t 分之1) dt 根据所给的首字母,完成下面的句子1.Do you have an e-mail a______?2.He studies hard.His father is always h________ with him.3.What is your a______?I am 15.4.Jane's b_____ is on the twenty-first.I am going to buy a paresents for her.5.Xiao shuxue wenti甲,乙两人同时同地同向出发,沿环行跑道匀速跑步,如出发是乙的速度是甲的2.5倍,当乙第一次追上甲时,甲的速度立即提高25%,而乙的速度立即减少20%,并且乙第一次追上甲的地点与第二 高一数学向量【减法】不明白…(AB-CD)-(AC-BD) 我没打方向箭头…请问怎么做啊?不要答案…讲解一下 好像是跟物理冲量有关的(寻找那高中物理题)就是一个1.8米高有人,在他的骨骼能承受的压力下,在理想状态下,他能从多高的地方跳下利用自身条件进行缓冲来而不会受伤!(这是一道高中的 高一数学:表向量的0手写时上方定要加向右箭头吗? 两块磁铁相吸是什么力不是磁场力 德国农场主检查马厩时发现自家马匹驮回俄圣彼得堡将遭强飓风袭击 涅瓦河水位阿富汗一男子被疑制造炸弹袭击事件 遭日本两男子涉嫌介绍未成年少女夜总会打日本一办公室里种大麻盈利逾千万日元 朱国林:转基因是“欺骗的种子,失窃的王湘穗:建议国家成立“转基因安全国家顾秀林:坚决不同意标注出售转基因食品中国拟规定非法添加等危害食品安全行为纽约华裔男子眼红表哥家庭幸福 杀其一日官房长官称日国家安保“司令塔”或用范冰冰刘诗诗赵薇 女星古装仙气妖气灵日本艺妓PK清朝妃子 古代妆容无力吐日媒:世界围绕中美运转 强大中国欲改姚林辉参加“老年希望工程”公益活动 播报:揭秘邵逸夫传奇一生 季羡林抱怨水葫芦“围困”富春江>国际新闻精选:2013陕甘宁经贸文化合作大会暨陕甘中国体育代表团冬奥会领奖服发布江西一对连体女婴成功接受分离手术增加6个放票时间点
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘