{$IFDEF WtrGate}{$IFDEF UseOvr}{$O+,F+}{$ENDIF}{$ENDIF}
UNIT UnixTime;

{$i platform.inc}

{ UnixDate                                                                  }
{                                                                           }
{ Een C style unixdate bestaat uit het aantal seconden sinds 1970           }
{ Deze unit kan ze omrekenen in beide richtingen, ofwel van een Dos datum   }
{ naar seconden en visa versa.                                              }
{                                                                           }
{ MD 03-08-93  Test progje omgezet naar een Unit                            }

INTERFACE

USES Dos;

CONST SEC_Dag              = 60*60*24;
      SEC_Uur    : LONGINT = 60*60;
      SEC_Minuut : LONGINT = 60;

PROCEDURE UnixToDos (Invoer : LONGINT; VAR Result : DateTime);
FUNCTION  DosDateTime2UnixDateTime (VAR DT : DateTime) : LONGINT;
FUNCTION  GetCurrentUnixTime : LONGINT;
FUNCTION  UnixTimeToString (Invoer : LONGINT) : STRING;

PROCEDURE FidoDateTimeStr2DosDateTime (S : STRING; VAR DT : DateTime);
FUNCTION  DosDateTime2FidoDateTimeStr (DT : DateTime) : STRING;

FUNCTION  UnixDateTime2PackedDosDateTime (UnixDT : LONGINT) : LONGINT;
FUNCTION  PackedDosDateTime2UnixDateTime (PackedDosDT : LONGINT) : LONGINT;


IMPLEMENTATION

USES Ramon,
     Globals,
     Logs,
     Fido;

CONST SEC_Jaar   : ARRAY[FALSE..TRUE] OF LONGINT = (365*SEC_Dag,{Schrikkel}366*SEC_Dag);
      SEC_Maand  : ARRAY[1..12] OF LONGINT =
                       (31*SEC_Dag,   { Januari  }
                        28*SEC_Dag,   { Februari }
                        31*SEC_Dag,   { Maart    }
                        30*SEC_Dag,   { April    }
                        31*SEC_Dag,   { Mei      }
                        30*SEC_Dag,   { Juni     }
                        31*SEC_Dag,   { Juli     }
                        31*SEC_Dag,   { Augustus }
                        30*SEC_Dag,   { SeptemBer}
                        31*SEC_Dag,   { Oktober  }
                        30*SEC_Dag,   { November }
                        31*SEC_Dag);  { December }

{--------------------------------------------------------------------------}
{ IsSchrikkel                                                              }
{                                                                          }
{ Standaard, is dit jaar een schrikkeljaar?                                }
{                                                                          }
FUNCTION IsSchrikkel (Year : WORD) : BOOLEAN;
BEGIN
     IsSchrikkel:=(Year MOD 400 = 0) OR
                   (NOT (Year MOD 100 = 0) AND (Year MOD 4 = 0));
END;


{--------------------------------------------------------------------------}
{ UnixToDos                                                                }
{                                                                          }
{ Converteerd een Unix-Style datum naar een standaard DateTime structure   }
{                                                                          }
{ Een unix time bestaat uit het aantal seconden verlopen sinds 1 jan 1970. }
{                                                                          }
PROCEDURE UnixToDos (Invoer : LONGINT; VAR Result : DateTime);

VAR MaandNr  : WORD;
    MaandLen : LONGINT;
    DagNr    : WORD;

BEGIN
     { Unix date begint op 1 january 1970 }
     WITH Result DO
     BEGIN
          Year:=1970;

          WHILE (Invoer >= SEC_Jaar[IsSchrikkel (Year)]) DO
          BEGIN
               Invoer:=Invoer-SEC_Jaar[IsSchrikkel (Year)];
               Inc (Year);
          END;

          Month:=1; { January }
          { tel nu de maanden ervanaf }
          { RWI 950318: MaandLen en WHILE TRUE ingevoerd ipv }
          {             vijfdubbele bepaling.                }
          WHILE TRUE DO
          BEGIN
               MaandLen:=SEC_Maand[Month];
               IF (Month = 2) AND IsSchrikkel (Year) THEN
                  MaandLen:=MaandLen+SEC_Dag;

               IF (Invoer >= MaandLen) THEN
               BEGIN
                    Inc (Month);
                    Invoer:=Invoer-MaandLen;
               END ELSE
                   Break;
          END;

          Day:=(Invoer DIV SEC_Dag); { altijd 1 dag }
          Invoer:=(Invoer-Day*SEC_Dag);
          Inc (Day); { RWI 950318: dag nummer is 1-gebaseerd }

          Hour:=(Invoer DIV SEC_Uur);
          Invoer:=(Invoer-Hour*SEC_Uur);

          Min:=Invoer DIV SEC_Minuut;
          Invoer:=(Invoer-Min*SEC_Minuut);

          Sec:=Invoer;
     END; { with }
END;


{--------------------------------------------------------------------------}
{ DosDateTime2UnixDateTime                                                 }
{                                                                          }
{ Converts a dos date/time structure to a unix date/time stamp.            }
{                                                                          }
FUNCTION DosDateTime2UnixDateTime (VAR DT : DateTime) : LONGINT;

VAR JaarLp  : WORD;
    MaandLp : BYTE;
    Result  : LONGINT;

BEGIN
     Result:=0;

     WITH DT DO
     BEGIN
          { doorloop het aantal jaren naar 1970 }
          FOR JaarLp:=1970 TO (Year-1) DO
              Result:=Result+SEC_Jaar[IsSchrikkel (JaarLp)];

          IF (Month = 0) OR (Month > 12) THEN
          BEGIN
               LogMessage (liTrivial,'Invalid month in date: '+Byte2String (Month));

               IF (Month = 0) THEN
                  Month:=1;

               IF (Month > 12) THEN
                  Month:=12;
          END;

          { doorloop het aantal maanden naar de huidige }
          FOR MaandLp:=1 TO (Month-1) DO
          BEGIN
               Result:=Result+SEC_Maand[MaandLp];
               IF (MaandLp = 2) AND IsSchrikkel (Year) THEN
                  Result:=Result+SEC_Dag;
          END;

          { tel hierbij het aantal dagen op }
          Result:=Result+SEC_Dag*(Day-1);

          { tel hierbij het aantal uren op }
          Result:=Result+SEC_Uur*Hour;

          { tel hierbij het aantal minuten }
          Result:=Result+SEC_Minuut*Min;

          { en uiteindelijk het aantal seconden }
          Result:=Result+Sec;
     END; { with }

     DosDateTime2UnixDateTime:=Result;
END;


{--------------------------------------------------------------------------}
{ GetCurrentUnixTime                                                       }
{                                                                          }
{ Converteert de huidige tijd naar Unix Tijd stempel.                      }
{                                                                          }
FUNCTION GetCurrentUnixTime : LONGINT;

VAR DT        : DateTime;
    h,mi,s,x,
    y,mo,d,o  : WordLong;

BEGIN
     GetTime (h,mi,s,x);
     GetDate (y,mo,d,o);

     WITH DT DO
     BEGIN
          Year:=y;
          Month:=mo;
          Day:=d;
          Hour:=h;
          Min:=mi;
          Sec:=s;
     END;

     GetCurrentUnixTime:=DosDateTime2UnixDateTime (DT);
END;


{--------------------------------------------------------------------------}
{ UnixTimeToString                                                         }
{                                                                          }
{ Deze routine conveert een UnixTime in een string.                        }
{                                                                          }
FUNCTION UnixTimeToString (Invoer : LONGINT) : STRING;

VAR DT : DateTime;

BEGIN
     IF (Invoer = 0) THEN
     BEGIN
          UnixTimeToString:='Never';
          Exit;
     END;

     UnixToDos (Invoer,DT);

     UnixTimeToString:=Byte2String (DT.Day)+' '+
                       Month[DT.Month]+' '+
                       Word2String (DT.Year)+' '+
                       AddUpWithPre0s (2,Byte2String (DT.Hour))+':'+
                       AddUpWithPre0s (2,Byte2String (DT.Min))+':'+
                       AddUpWithPre0s (2,Byte2String (DT.Sec));
END;


{--------------------------------------------------------------------------}
{ FidoDateTimeStr2DosDateTime                                              }
{                                                                          }
{ This routine converts a Fido date/time string like "01 jan 93  19:15:50" }
{ to the DateTime structure and makes sure the values valid.               }
{                                                                          }
PROCEDURE FidoDateTimeStr2DosDateTime (S : STRING; VAR DT : DateTime);

VAR Lp  : BYTE;
    Nop : ValNop;
    R   : WordLong;

BEGIN
     { 01 Jan 98  10:20:30 }
     { 1234567890123456789 }

     IF (Length (S) <> 19) THEN
     BEGIN
          LogMessage (liTrivial,'Incorrect length: "'+S+'"');
          S:=AddUpWithSpaces (19,S);
     END;

     Val (Copy (S,1,2),DT.Day,Nop);
     IF (Nop > 0) THEN
     BEGIN
          DT.Day:=1;
          LogMessage (liTrivial,'Invalid Day in "'+S+'"; assuming 1');
     END;

     Val (Copy (S,8,2),DT.Year,Nop);
     IF (Nop <> 0) THEN
     BEGIN
          GetDate (DT.Year,R,R,R); { returns 1980..2099 }
          LogMessage (liTrivial,'Invalid Year in "'+S+'"; assuming '+Word2String (DT.Year));
     END ELSE
     BEGIN
          {## correct this so it supports the window method }
          { year was only two digits; correct into 1980.. }
          IF (DT.Year > 79) THEN
             Inc (DT.Year,1900)
          ELSE
              Inc (DT.Year,2000);
     END;

     Val (Copy (S,12,2),DT.Hour,Nop);
     Val (Copy (S,15,2),DT.Min,Nop);
     Val (Copy (S,18,2),DT.Sec,Nop);

     DT.Month:=0;
     FOR Lp:=1 TO 12 DO
         IF CaselessMatch (Month[Lp],Copy (S,4,3)) THEN
         BEGIN
              DT.Month:=Lp;
              Break;
         END;

     IF (DT.Month = 0) THEN
     BEGIN
          LogMessage (liTrivial,'Invalid Month in "'+S+'"; assuming January');
          DT.Month:=1;
     END;
END;


{--------------------------------------------------------------------------}
{ DosDateTime2FidoDateTimeStr                                              }
{                                                                          }
{ This routine converts the dos date/time format to a string formatted     }
{ according to the FTN date/time string format like "01 Jan 99 23:20:45".  }
{                                                                          }
FUNCTION DosDateTime2FidoDateTimeStr (DT : DateTime) : STRING;
BEGIN
     DosDateTime2FidoDateTimeStr:=FidoTime2Str (DT.Day,DT.Month,DT.Year,DT.Hour,DT.Min,DT.Sec);
END;


{--------------------------------------------------------------------------}
{ UnixDateTime2PackedDosDateTime                                           }
{                                                                          }
{ This routine converts a unix date/time stamp into a packed dos date/time }
{ stamp.                                                                   }
{                                                                          }
FUNCTION UnixDateTime2PackedDosDateTime (UnixDT : LONGINT) : LONGINT;

VAR DT : DateTime;
    L  : LONGINT;

BEGIN
     UnixToDos (UnixDT,DT);
     PackTime (DT,L);
     UnixDateTime2PackedDosDateTime:=L;
END;


{--------------------------------------------------------------------------}
{ PackedDosDateTime2UnixDateTime                                           }
{                                                                          }
{ This routine converts the packed dos date/time format to the unix        }
{ date/time stamp format.                                                  }
{                                                                          }
FUNCTION PackedDosDateTime2UnixDateTime (PackedDosDT : LONGINT) : LONGINT;

VAR L  : LONGINT;
    DT : DateTime;

BEGIN
     UnpackTime (PackedDosDT,DT);
     PackedDosDateTime2UnixDateTime:=DosDateTime2UnixDateTime (DT);
END;


END.
