Ver Fonte

* refactored duplicated code for epoch to datetime and vice versa conversion
between the dos and sysutils units for the WASI platform

Nikolay Nikolov há 3 anos atrás
pai
commit
65d8c3d7eb
3 ficheiros alterados com 139 adições e 197 exclusões
  1. 7 92
      rtl/wasi/dos.pp
  2. 5 105
      rtl/wasi/sysutils.pp
  3. 127 0
      rtl/wasi/wasiutil.pp

+ 7 - 92
rtl/wasi/dos.pp

@@ -110,8 +110,6 @@ var
 begin
   if __wasi_clock_time_get(__WASI_CLOCKID_REALTIME,10000000,@NanoSecsPast)=__WASI_ERRNO_SUCCESS then
   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 }
     WasiDateToDT(NanoSecsPast,DT);
     Year:=DT.Year;
     Month:=DT.Month;
@@ -170,103 +168,20 @@ end;
 
 
 Function DTToWasiDate(DT: DateTime): UInt64;
-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 Word =
-    ((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;
+  res: Int64;
 begin
-  if (DT.year<1970) or (DT.month<1) or (DT.month>12) or (DT.day<1) or (DT.day>31) or
-     (DT.hour>=24) or (DT.min>=60) or (DT.sec>=60) then
-  begin
-    DTToWasiDate:=0;
-    exit;
-  end;
-  leap:=((DT.year mod 4)=0) and (((DT.year mod 100)<>0) or ((DT.year mod 400)=0));
-  if DT.day>days_in_month[leap,DT.month] then
-  begin
-    DTToWasiDate:=0;
-    exit;
-  end;
-  DTToWasiDate:=0;
-  for y:=1970 to DT.year-1 do
-    if ((y mod 4)=0) and (((y mod 100)<>0) or ((y mod 400)=0)) then
-      Inc(DTToWasiDate,366)
-    else
-      Inc(DTToWasiDate,365);
-  Inc(DTToWasiDate,days_before_month[leap,DT.month]);
-  Inc(DTToWasiDate,DT.day-1);
-  DTToWasiDate:=((((DTToWasiDate*24+DT.hour)*60+DT.min)*60)+DT.sec)*1000000000;
+  res:=WasiUtil.LocalToEpoch(DT.year,DT.month,DT.day,DT.hour,DT.min,DT.sec);
+  if res<0 then
+    DTToWasiDate:=0
+  else
+    DTToWasiDate:=res*1000000000;
 end;
 
 
 Procedure WasiDateToDt(NanoSecsPast: UInt64; Var Dt: DateTime);
-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
-  { todo: convert UTC to local time, as soon as we can get the local timezone
-    from WASI: https://github.com/WebAssembly/WASI/issues/239 }
-  NanoSecsPast:=NanoSecsPast div 1000000000;
-  Dt.Sec:=NanoSecsPast mod 60;
-  NanoSecsPast:=NanoSecsPast div 60;
-  Dt.Min:=NanoSecsPast mod 60;
-  NanoSecsPast:=NanoSecsPast div 60;
-  Dt.Hour:=NanoSecsPast mod 24;
-  NanoSecsPast:=NanoSecsPast div 24;
-  Dt.Year:=1970;
-  leap:=false;
-  days_in_year:=365;
-  while NanoSecsPast>=days_in_year do
-  begin
-    Dec(NanoSecsPast,days_in_year);
-    Inc(Dt.Year);
-    leap:=((Dt.Year mod 4)=0) and (((Dt.Year mod 100)<>0) or ((Dt.Year mod 400)=0));
-    if leap then
-      days_in_year:=366
-    else
-      days_in_year:=365;
-  end;
-  Dt.Month:=1;
-  Inc(NanoSecsPast);
-  while NanoSecsPast>days_in_month[leap,Dt.Month] do
-  begin
-    Dec(NanoSecsPast,days_in_month[leap,Dt.Month]);
-    Inc(Dt.Month);
-  end;
-  Dt.Day:=Word(NanoSecsPast);
+  WasiUtil.EpochToLocal(NanoSecsPast div 1000000000,Dt.Year,Dt.Month,Dt.Day,Dt.Hour,Dt.Min,Dt.Sec);
 End;
 
 

+ 5 - 105
rtl/wasi/sysutils.pp

@@ -56,123 +56,23 @@ 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 Word =
-    ((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;
+  Result:=WasiUtil.UniversalToEpoch(year,month,day,hour,minute,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);
+  Result:=WasiUtil.LocalToEpoch(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);
+begin
+  WasiUtil.EpochToUniversal(epoch,year,month,day,hour,minute,second);
 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);
+  WasiUtil.EpochToLocal(epoch,year,month,day,hour,minute,second);
 end;
 
 { Include platform independent implementation part }

+ 127 - 0
rtl/wasi/wasiutil.pp

@@ -44,6 +44,10 @@ function FNMatch(const Pattern,Name:rawbytestring):Boolean;
 function WasiFindFirst(const Path: RawByteString; Attr: Word; var f: TWasiSearchRec): longint;
 function WasiFindNext(var f: TWasiSearchRec): longint;
 procedure WasiFindClose(var f: TWasiSearchRec);
+Function UniversalToEpoch(year,month,day,hour,minute,second:Word):int64;
+Function LocalToEpoch(year,month,day,hour,minute,second:Word):int64;
+Procedure EpochToUniversal(epoch:int64;var year,month,day,hour,minute,second:Word);
+Procedure EpochToLocal(epoch:int64;var year,month,day,hour,minute,second:Word);
 
 implementation
 
@@ -402,4 +406,127 @@ Begin
    end;
 End;
 
+
+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 Word =
+    ((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;
+
 end.