+ implemented SysUtils.FileGetDate for WASI

This commit is contained in:
Nikolay Nikolov 2021-10-11 15:08:48 +03:00
parent 2a93340bcc
commit 8f95c14827
2 changed files with 140 additions and 12 deletions

View File

@ -1258,7 +1258,7 @@ Var YY,MM,DD,H,m,s,msec : Word;
begin
Decodedate (DateTime,YY,MM,DD);
DecodeTime (DateTime,h,m,s,msec);
{$ifndef unix}
{$if not defined(unix) and not defined(wasi)}
If (YY<1980) or (YY>2099) then
Result:=0
else
@ -1266,24 +1266,24 @@ begin
Result:=(s shr 1) or (m shl 5) or (h shl 11);
Result:=Result or longint(DD shl 16 or (MM shl 21) or (word(YY-1980) shl 25));
end;
{$else unix}
{$else unix or wasi}
Result:=LocalToEpoch(yy,mm,dd,h,m,s);
{$endif unix}
{$endif unix or wasi}
end;
Function UniversalToFileDate(DateTime : TDateTime) : int64;
{$ifndef unix}
{$if not defined(unix) and not defined(wasi)}
begin
Result := DateTimeToFileDate(UniversalTimeToLocal(DateTime));
end;
{$else unix}
{$else unix or wasi}
Var YY,MM,DD,H,m,s,msec : Word;
begin
Decodedate (DateTime,YY,MM,DD);
DecodeTime (DateTime,h,m,s,msec);
Result:=UniversalToEpoch(yy,mm,dd,h,m,s);
end;
{$endif unix}
{$endif unix or wasi}
function CurrentYear: Word;
var
@ -1295,7 +1295,7 @@ end;
Function FileDateToDateTime (Filedate : Int64) : TDateTime;
{$ifndef unix}
{$if not defined(unix) and not defined(wasi)}
Var Date,Time : Word;
begin
@ -1304,29 +1304,29 @@ begin
Result:=ComposeDateTime(EncodeDate((Date shr 9) + 1980,(Date shr 5) and 15, Date and 31),
EncodeTime(Time shr 11, (Time shr 5) and 63, (Time and 31) shl 1,0));
end;
{$else unix}
{$else unix or wasi}
var
y, mon, d, h, min, s: word;
begin
EpochToLocal(FileDate,y,mon,d,h,min,s);
Result:=ComposeDateTime(EncodeDate(y,mon,d),EncodeTime(h,min,s,0));
end;
{$endif unix}
{$endif unix or wasi}
Function FileDateToUniversal (Filedate : Int64) : TDateTime;
{$ifndef unix}
{$if not defined(unix) and not defined(wasi)}
begin
Result := LocalTimeToUniversal(FileDateToDateTime(Filedate));
end;
{$else unix}
{$else unix or wasi}
var
y, mon, d, h, min, s: word;
begin
EpochToUniversal(FileDate,y,mon,d,h,min,s);
Result:=ComposeDateTime(EncodeDate(y,mon,d),EncodeTime(h,min,s,0));
end;
{$endif unix}
{$endif unix or wasi}
function TryStrToDate(const S: ShortString; out Value: TDateTime): Boolean;
begin

View File

@ -51,6 +51,126 @@ implementation
{$DEFINE executeprocuni} (* Only 1 byte version of ExecuteProcess is provided by the OS *)
Function UniversalToEpoch(year,month,day,hour,minute,second:Word):int64;
const
days_in_month: array [boolean, 1..12] of Byte =
((31,28,31,30,31,30,31,31,30,31,30,31),
(31,29,31,30,31,30,31,31,30,31,30,31));
days_before_month: array [boolean, 1..12] of Byte =
((0,
0+31,
0+31+28,
0+31+28+31,
0+31+28+31+30,
0+31+28+31+30+31,
0+31+28+31+30+31+30,
0+31+28+31+30+31+30+31,
0+31+28+31+30+31+30+31+31,
0+31+28+31+30+31+30+31+31+30,
0+31+28+31+30+31+30+31+31+30+31,
0+31+28+31+30+31+30+31+31+30+31+30),
(0,
0+31,
0+31+29,
0+31+29+31,
0+31+29+31+30,
0+31+29+31+30+31,
0+31+29+31+30+31+30,
0+31+29+31+30+31+30+31,
0+31+29+31+30+31+30+31+31,
0+31+29+31+30+31+30+31+31+30,
0+31+29+31+30+31+30+31+31+30+31,
0+31+29+31+30+31+30+31+31+30+31+30));
var
leap: Boolean;
days_in_year: LongInt;
y,m: LongInt;
begin
if (year<1970) or (month<1) or (month>12) or (day<1) or (day>31) or
(hour>=24) or (minute>=60) or (second>=60) then
begin
result:=-1;
exit;
end;
leap:=((year mod 4)=0) and (((year mod 100)<>0) or ((year mod 400)=0));
if day>days_in_month[leap,month] then
begin
result:=-1;
exit;
end;
result:=0;
for y:=1970 to year-1 do
if ((y mod 4)=0) and (((y mod 100)<>0) or ((y mod 400)=0)) then
Inc(result,366)
else
Inc(result,365);
Inc(result,days_before_month[leap,month]);
Inc(result,day-1);
result:=(((result*24+hour)*60+minute)*60)+second;
end;
Function LocalToEpoch(year,month,day,hour,minute,second:Word):int64;
begin
{ todo: convert UTC to local time, as soon as we can get the local timezone
from WASI: https://github.com/WebAssembly/WASI/issues/239 }
result:=UniversalToEpoch(year,month,day,hour,minute,second);
end;
Procedure EpochToUniversal(epoch:int64;var year,month,day,hour,minute,second:Word);
const
days_in_month: array [boolean, 1..12] of Byte =
((31,28,31,30,31,30,31,31,30,31,30,31),
(31,29,31,30,31,30,31,31,30,31,30,31));
var
leap: Boolean;
days_in_year: LongInt;
begin
if epoch<0 then
begin
year:=0;
month:=0;
day:=0;
hour:=0;
minute:=0;
second:=0;
exit;
end;
second:=epoch mod 60;
epoch:=epoch div 60;
minute:=epoch mod 60;
epoch:=epoch div 60;
hour:=epoch mod 24;
epoch:=epoch div 24;
year:=1970;
leap:=false;
days_in_year:=365;
while epoch>=days_in_year do
begin
Dec(epoch,days_in_year);
Inc(year);
leap:=((year mod 4)=0) and (((year mod 100)<>0) or ((year mod 400)=0));
if leap then
days_in_year:=366
else
days_in_year:=365;
end;
month:=1;
Inc(epoch);
while epoch>days_in_month[leap,month] do
begin
Dec(epoch,days_in_month[leap,month]);
Inc(month);
end;
day:=Word(epoch);
end;
Procedure EpochToLocal(epoch:int64;var year,month,day,hour,minute,second:Word);
begin
{ todo: convert UTC to local time, as soon as we can get the local timezone
from WASI: https://github.com/WebAssembly/WASI/issues/239 }
EpochToUniversal(epoch,year,month,day,hour,minute,second);
end;
{ Include platform independent implementation part }
{$i sysutils.inc}
@ -324,7 +444,15 @@ end;
Function FileGetDate (Handle : THandle) : Int64;
var
res: __wasi_errno_t;
Info: __wasi_filestat_t;
begin
res:=__wasi_fd_filestat_get(Handle,@Info);
if res=__WASI_ERRNO_SUCCESS then
result:=Info.mtim div 1000000000
else
result:=-1;
end;