123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2020 Karoly Balogh, Free Pascal Development team
- Amiga utility.library legacy (OS 1.x/2.x) support functions
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {
- This unit implements some of the utility.library functions for OS 1.x,
- where this library is missing, so the legacy OS support can be implemented
- with minimal changes to the normal system unit and common Amiga-like code
- Please note that this code doesn't aim to be API feature complete, just
- functional enough for the RTL code.
- }
- const
- // Start day of every month (without leap)
- StartOfMonth: array[0..11] of LongInt = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
- SecsPerMin = 60;
- SecsPerHour = 60 * SecsPerMin;
- SecsPerDay = 24 * SecsPerHour;
- SecsPerYear = 365 * SecsPerDay;// without leap
- AmigaStartYear = 1978; // Amiga starts @1978;
- DaysPerYear = 365;
- DaysPerLeapYear = DaysPerYear + 1;
- Daysof4Years = DaysPerLeapYear + 3 * DaysPerYear;
- Daysof100Years = 24 * DaysPerLeapYear + 76 * DaysPerYear;
- Daysof400Years = 97 * DaysPerLeapYear + 303 * DaysPerYear;
- procedure Amiga2Date(seconds: Cardinal;
- result : PClockData); public name '_fpc_amiga_amiga2date';
- var
- IsLeap: boolean;
- d, y, i: LongWord;
- begin// how many days are passed
- d := seconds div SecsPerDay;
- // the easier time part
- Result^.wday := d mod 7;
- Result^.sec := seconds mod 60;
- seconds := seconds div 60;
- Result^.min := seconds mod 60;
- seconds := seconds div 60;
- Result^.hour := seconds mod 24;
- // the leap year correction part
- IsLeap := True;
- //
- // before 2100 easier case (function mostly used for now(), so its usually in this range)
- if d < 92 * DaysPerYear + 30 * DaysPerLeapYear then // 1978 - 2100 = 92 non leap, 30 leap years
- begin
- d := d + DaysPerLeapYear + DaysPerYear; // we want to start from 1976 (a leap year) so we add 2 more years to the nubmer we have
- y := 4 *(d div Daysof4Years) + 1976; // how many 4 year spans (1 leap + 3 non leap) are there?
- d := d mod Daysof4Years; //( get the day in the 4 year span)
- // the first yoear of such a 4 year span, is always a leap year, all other not (thats the reason we want to start at 1976)
- if d > DaysPerLeapYear then
- begin
- IsLeap := False;
- d := d - 1;
- y := y + d div DaysPerYear;
- d := d mod DaysPerYear;
- end;
- end
- else
- begin
- // more complicated way for dates > 2100 (not tested until now!)
- // we do the same as before but not 4 years together but 400 (because of the special years which are not leap even divided by 4)
- // and we start at 2000
- d := d - 17 * DaysPerYear + 5 * DaysPerLeapYear;
- y := 400 * (d div Daysof400Years) + 2000;
- d := d mod Daysof400Years;
- // first is always NOT leap year.. other we have to test
- if d >= DaysPerLeapYear then
- begin
- // we do the same again, and test for 100 year spans
- d := d - 1; // not a leap year one day down
- IsLeap := False;
- y := y + 100 * (d div Daysof100Years);
- d := d mod Daysof100Years;
- if d >= DaysPerYear then
- begin
- d := d + 1; // a leap year, one day up
- IsLeap := True;
- // and the same as we did before 4 years span
- y := y + 4 * (d div Daysof4Years);
- d := d mod Daysof4Years;
- if d >= DaysPerLeapYear then
- begin
- d := d - 1;
- IsLeap := False;
- y := y + d div DaysPerYear;
- d := d mod DaysPerYear;
- end;
- end;
- end;
- end;
- // the current year is a leap year and we are after Februar
- if IsLeap and (d >= StartOfMonth[2]) then
- d := d + 1;
- // get the actual month
- for i := 1 to High(StartOfMonth) do
- begin
- if StartOfMonth[i] > d then
- begin
- Result^.Month := i;
- d := d - (StartOfMonth[i - 1] + 1);
- break;
- end;
- end;
- Result^.year := y;
- Result^.mday := d;
- end;
- function Date2Amiga(date: PClockData): Cardinal; public name '_fpc_amiga_date2amiga';
- var
- Y: LongInt;
- Leaps, LeapsBefore1978, Res: LongWord;
- begin
- // the easy time part
- Res := date^.hour * SecsPerHour + date^.min * SecsPerMin + date^.sec;
- Res := Res + ((date^.mday - 1) + StartOfMonth[date^.month - 1]) * SecsPerDay;
- Res := Res + (date^.year - AmigaStartYear) * SecsPerYear;
- // leap year correction ;)
- // current year
- y := date^.year;
- // from IsLeapYear dos.pp
- if (y mod 400 = 0) or ((y mod 4 = 0) and (y mod 100 <> 0)) then
- begin
- // add a day if its after feb in a leap year
- if date^.month > 2 then
- Res := Res + SecsPerDay;
- end;
- // previous years
- y := date^.year - 1;
- Leaps := (y div 4) - (y div 100) + (y div 400);
- // exclude the ones before 1978
- LeapsBefore1978 := (AmigaStartYear div 4) - (AmigaStartYear div 100) + (AmigaStartYear div 400);
- Date2Amiga := Res + (leaps - leapsBefore1978) * SecsPerDay;
- end;
|