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

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

【CTO讲堂】NoSQL对未来大数据发展的意义何在? 从Java转向Go——AeroFS的一段奇妙之旅 谷歌重组建母公司Alphabet,新来的CEO Sandar Pichai是什么来头? 《近匠》专访AllSeen联盟主席薛国栋:从通讯层为物联网去中心化 Android性能优化典范(三) 杭州兆合陈洋:微气象大民生,气象微信平台研发探索 【探秘ES6】系列专栏(十):更深入了解生成器 【探秘ES6】系列专栏(十一):类语法 《近匠》专访Depth VR:浅析VR交互技术选型中的瓶颈与机遇 【CTO讲堂】将“简单快速”渗透到移动开发测试每个环节,从fir.im团队说起 全球开发者报告:Windows Phone已死,Windows 10长存 苹果官方博客:从SDK详说Swift代码的改变 Espresso实战:快速的Android UI自动化测试 《Java并发编程的艺术》作者方腾飞:感谢Java,带我一路前行! Crystal:一个类似于Ruby语法的编程语言 谁将是传统密码的终结者 专访民生银行:CPOS平台如何从线下布局移动支付 MathWorks程邺:机器人时代未来已来 Swift编程规范:保持代码优美的10个方法 中国第二届CSS开发者大会视频&amp;amp;PPT全部免费观看 如何基于Vert.x实现远程调用? Go 1.5如期发布,完全告别C代码 Rust一周集锦(三):关闭3个RFC并为1.4版本做准备 【CTO讲堂】多备份创始人陈元强:在线灾备革命背后的事 探索React:组件间通信过程解析 机智云完成2亿元B轮融资 将围绕信息安全与机器学习创建“机智云联合实验室” 【CTO讲堂】深度?广度?浅析技术人员的职业发展之路 详解React Flux架构工作方式 专访Tiny框架创始人悠然:好的软件设计是“品”出来的 开发移动应用的7大设计要点 历时一年半 现代Web框架Phoenix 1.0正式发布 请教C PLUS PLUS 如何运行其他exe程序,请大家... 求助 在哪里可以下载比较经典的C++书籍? ★关于“全选”的问题!★ 关于中文显示的问题 !!!!!! 如何用SQLBulkoprations向表中加入数据,此时应如何设置游标??加急,在线等!! 急:treeview显示成一行文本 最简单的方法是?(问题简单,过来看看) 本人想考个SCJP认证,大家觉得如何???用处大吗??在找工作的过程中? 请教:对话框上的滚动条怎么使用?我设置了,然后将窗体大小缩小(于是对话框有一部分看不见了),可是单击滚动条,不起作用,怎么办?急, 问一个数据库公式的问题! 一个IP发布两个网站的问题(在线等待) 怎样改变资源文件里字体的颜色???菜单里的字体颜色我不会改?有专家指点吗? Python 网络教室采用多播好还是广播好? 下载的问题! 如何新建一个文件夹? 将html文件存放在备注字段中,然后再输出可以吗? 如何控制一个文本框的内容随另一个文本框的内容变化而同步变化? 一个关于窗口的小问题!!!小弟初学DELPHI请多多指教!! 求助 excel导入数据时出错.高手进 请问role是干嘛的? 自动生成图片 datawind如何与window联系起来啊 存储过程同时调用和数据库异地备份问题? 在xsl中如何调用javascript 误删系统盘,救命!!! 请问ACCP和高程考试相比哪个更有份量? 求LeapFTP V2.7.3.600的注册码 5月6日我来CSDN的二周年,散分,纪念。。。。 listbox (湖南)今年非典搞得这样,会耽误报高程吗?今年有人报了吗?怎样报的? ComboBoxEx在 SetImageList 时出错 在DBComboBox中脸上数据库后,为什么进行选择时会出现“违反了Primary 约束“ 关于传递多值的问题 如何从recordset得到数据库的行号 用<%@ include file="xxx.jsp"%>出现的怪问题!求教 有关server.mappath()的问题 J2EE基础问题两三问,追加200分。 问题很简单,但我很急,请帮忙各位。 可用的UDDI 急救!自动隐藏Panel 帮忙 哪里有数据库系统开发的文档下载 急待解决的问题 请问从socket发信息,连续发送几个小数据包出错的情况!! 紧急问题,在线等待! 救命——存取违例 请问在VB中使用DAO控件怎样打开ACCESS数据库? 马来西亚移民局前总监被判处贪污罪名成Facebook首次承认传闻:年轻人日政府开发海底资源动作迟缓引日研究机日超2成地震重建预算未使用 政府被指印度外长访澳为三年前留学生在澳被杀案澳大利亚警方追捕偷车贼 路过少年被无一驻日美军士兵涉嫌酒驾被逮捕 称已小新华国际时评:“弱冠”欧盟期待“涅槃澳大学开设全球商业学士学位课程 多语韩媒称韩国雾霾源自中国 记者实地考证巴勒斯坦四名武装分子与以军发生冲突被中美企业家共商双边合作前景男子把鸡蛋强塞女子下体后捏碎性侵 辩韩国模特独岛上秀服装 旨在宣示“主权习近平:坚持男女平等基本国策 发挥妇经济学家樊纲:中国经济已经基本完成软罗马尼亚:保管箱频失窃 银行安全自查乃木坂46推出首部写真集 上演清纯泳我国将在南极建立第四个科学考察站--澳大利亚10月房价环比上升1.3%泰国欲征入境税 短期内恐难实施我的歌里也有 许巍调侃汪峰歌词套路外援大比拼福建男排完败□资讯□简讯“共和”平台助企业成功突围小桥无护栏埋隐患央行禁止比特币当货币流通部分公司乱收费行业盼统一标准中山平价商店达203家福州火车站边有个“黑的”窝持刀劫持小学生 勒索20万元中行云购物推出多项优惠居住智能社区 也许不再遥远两个初中生飙车闯禁行首批洋房售罄 本周紧急加推“麻辣女教官”成美国防部二把手2013福州楼市的“快”时尚1958:艺术与历史的激情碰撞男子耗时半年成功追缴社保中信银行助力老年人公益来年鼓山梅里 梅花谢后杜鹃开
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘