線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1024
推到 Plurk!
推到 Facebook!

DELPHI AND THE YEAR 2000 PROBLEM

 
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-05-30 13:44:08 IP:61.64.xxx.xxx 未訂閱
The Unofficial Newsletter of Delphi Users - by Robert Vivrette      http://www.undu.com/Articles/990111a.html    DELPHI AND THE YEAR 2000 PROBLEM     by Clay Shannon - ClaySCS@aol.com     Y2K. The Year 2000 problem. The Millenium Bug. The mother of all software projects. However you feel about the potential problems associated with the year 2000 and the impact it will have on your work and life, you will surely admit that it is important for your software projects to be "Year 2000 compliant".     Computer programs are viewed by the "ungeeky masses" as generating cold, hard, rigid results. It seems a conundrum to them that there could be ambiguity connected with a date stored in a computer file or database table. But, as we all know, ambiguity can be the result if the date was entered using two digits rather than four, in which case an assumption has to be made about the century intended by the person entering the data.     This is not just a COBOL/mainframe problem. Our beloved Delphi also accepts a two-digit entry for the year portion of a date and will by default encode the date as belonging in the century in which the user entered made the entry. For example, if sometime in 1998 you enter the date "10/10/99" in a DBEdit connected to a date field, the date will be interpreted and stored as October 10th, 1999. However, if you enter "10/10/99" in the year 2000, it will be interpreted and stored as October 10th, 2099.     WAYS TO ENFORCE ENTRY OF FOUR DIGITS FOR YEARS     How to prevent the application from making assumptions which may or may not be what is intended? The optimal solution is to force the user to always enter four digits for the year. This could be coded into the OnValidate event of the TField descendent (TDateField or TDateTimeField), like this:     procedure TForm1.Table1DobValidate(Sender: TField);  begin    if Length(dobEdit.Text) < 10 then      begin        MessageDlg('Please enter a date in the format                    mm/dd/yyyy',mtInformation,[mbOK],0);        dobEdit.SetFocus;      end;  end; In order to do have access to a TField's OnValidate event via the Object Inspector's events page, you must first instantiate the date field(s) in your dataset. To do so, use the Fields Editor by right-clicking on the TDataset (TTable, TQuery, TStoredProc in all versions of Delphi; TClientDataSet in Client/Server versions 3 and 4; TNestedTable in Delphi 4) component and selecting Fields Editor, or by double-clicking the TDataset. See "Fields Editor" and "Persistent Field Components" in Delphi help for more information.  If for some reason you do not want to instantiate the field(s) at design time, you can adapt the above code and attach it to the TDBEdit's OnExit event:     procedure TForm1.dobEditExit(Sender: TObject);  begin    if Length(dobEdit.Text) < 10 then      begin        MessageDlg('Please enter a date in the format                    mm/dd/yyyy',mtInformation,[mbOK],0);        dobEdit.SetFocus;      end;  end; Another option that can be employed to programmatically require the entry of four digits to represent the year portion of a date is to use a TMaskEdit component with the EditMask property's value set to !99/99/0000;1; and then assign the value to the database field desired. For example:  Table1DOB.AsDateTime := StrToDate(MaskEdit1.Text); Similarly, you can use the TDateTimePicker component, which, when clicked, drops down a calendar from which you can select a date. You can then assign its value to a database field like this:  Table1DOB.AsDateTime := DateTimePicker1.Date; Note: If you are using Delphi 4, there is a new standalone calendar component, TMonthCalendar, which can be used in a manner similar to TDateTimePicker.  DEALING WITH TWO-DIGIT YEAR ENTRIES     If you do not want to force the user to enter four digits in each date field, you can set a pivot number that determines the century to be assumed by the program. Numbers above your pivot number are assumed to be in the 21st Century, numbers below your pivot number are assumed to be in the 1900s. For example, you may determine that users will only intend to enter values between 1950 and 2049. In this case, you can make 50 the pivot year. You then attach code to each dataset's BeforePost event, which passes all date fields to a function that returns a date corresponding to the rules you have built in via your choice of pivot year. The example below showing how this could be done uses a TTable's BeforePost event, but will work also for other TDataset descendents (TQuery, TClientDataSet, TStoredProc, TNestedTable).     . . .  const    CenturyPivot = 1950;  var    Form1: TForm1;     implementation     {$R *.DFM}       function TForm1.CenturyWindow(const Value: TDateTime): TDateTime;    var      Year, Month, Day : Word;    begin      Result := Value;      DecodeDate(Result, Year, Month, Day);      if Year < CenturyPivot then        Result:= EncodeDate(Year+100, Month, Day);    end;     procedure TForm1.Table1BeforePost(DataSet: TDataSet);  var    DateValue: TDateTime;    DateTypes: set of TFieldType;    i: Integer;  begin    DateTypes := [ftDate, ftDateTime];    for i:=0 to DataSet.FieldCount-1 do      if (DataSet.FieldDefs[i].DataType in DateTypes) then        begin          DateValue := DataSet.Fields[i].AsDateTime;          DateValue := CenturyWindow(DateValue);          DataSet.Fields[i].AsDateTime := DateValue;        end;  end;       A MORE DYNAMIC SOLUTION  Delphi 4 provides an elegant solution to potential Year 2000 problems. Explicit entry of four-digit years is left unchanged. When two-digit years are entered, instead of relying on a constant pivot year, it determines the century to assume based on the current year less a number of years that you designate. The difference between this and the approach shown above is that if you assign a pivot year of 1950 using the aforementioned method, the pivot year will always remain 1950 until you (or someone after you) changes the value of that constant. It does not take much imagination to see that this may not always produce the desired results.     Delphi 4 provides this functionality via the new TwoDigitYearCenturyWindow system variable (declared in the SysUtils unit). The default value of this variable is 0, in which state Delphi will continue to expand ambiguous (two-digit) year entries according to the current century. In other words, if you enter "10/10/00" in 1998, it will be stored as October 10th, 1900; entering the same value on or after January 1, 2000 will store the date as October 10th, 2000). By setting this variable to a non-zero integer, the actual pivot year changes as the current year changes, but remains the same relative to the current year. The value you assign the TwoDigitYearCenturyWindow variable is subtracted from the current year to determine the pivot year. For example, if you set TwoDigitYearCenturyWindow to 50, the pivot year will be 1948 in 1998, 1950 in 2000, and 1982 in 2032. For example, if you set the TwoDigitYearCenturyWindow variable to 50 and enter a two-digit year value of 50 in 1998, it will be stored as 1950; entering the same value in 2000 will still store the year as 1950; however, in 2032, the year will be stored as 2050.     When an entry is made into a data control (such as TDBEdit) whose DataField property refers to a date field, the entry is implicitly converted from a string to a date value (Delphi uses the StrToDate and StrToDateTime conversion functions internally to accomplish this). Delphi 4 then checks for entry of four digits for the year portion of the date. If only two digits were entered, the value of the TwoDigitYearCenturyWindow variable is checked, and the appropriate century assigned based on the value you have assigned this variable (Again, it is 0 by default, in which state the current century is assumed).     Of course, if you do not want to upgrade to Delphi 4 (and there are many reasons why you should want to), you can always code your own function to provide the same support to your users. This is an exercise left to the readers (  ). CALL TO ARMS The year 2000 is fast approaching and will not be postponed. If you want to be part of the solution as opposed to being blamed for some of the problems, adopt a strategy now to either: Prevent ambiguity altogether by requiring explicit four-digit entry for years. Or, if this is not an option for you, at least deal with the ambiguity inherant in two-digit year entries intelligently by designating a pivot year based on the particular needs of your software's users. An excellent compromise of the two options is provided by Delphi 4’s support for Year 2000 compliancy.
stillalive
初階會員


發表:7
回覆:148
積分:41
註冊:2004-04-07

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-05-31 03:26:54 IP:211.75.xxx.xxx 未訂閱
記的 IBM AS400 千禧年解決方案有所謂 HALF WINDOW SOLUTION , 方法原理也是不脫上文所題 , 年份2位轉四位 , 1. XX >= 50 -> 19XX 2. XX < 50 -> 20XX 看起來實在很 DUMMING 發表人 - stillalive 於 2004/05/31 03:29:38
系統時間:2024-06-18 19:21:41
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!