[Back to DATETIME SWAG index] [Back to Main SWAG index] [Original]

    (***************************************************************************)
    (* UNIX DATE Version 1.01                                                  *)
    (* This unit provides access to UNIX date related functions and procedures *)
    (* A UNIX date is the number of seconds from January 1, 1970. This unit    *)
    (* may be freely used. If you modify the source code, please do not        *)
    (* distribute your enhancements.                                           *)
    (* (C) 1991-1993 by Brian Stark.                                           *)
    (* This is a programming release from Digital Illusions                    *)
    (* FidoNet 1:289/27.2 + Columbia, MO - USA                                 *)
    (* Revision History                                                        *)
    (* ----------------------------------------------------------------------- *)
    (* 06-13-1993 1.02 | Minor code cleanup                                    *)
    (* 05-23-1993 1.01 | Added a few more routines for use with ViSiON BBS     *)
    (* ??-??-1991 1.00 | First release                                         *)
    (* ----------------------------------------------------------------------- *)
    (***************************************************************************)

    INTERFACE

    Uses
       DOS;

    Function  GetTimeZone : ShortInt;
      {Returns the value from the enviroment variable "TZ". If not found, UTC is
       assumed, and a value of zero is returned}
    Function  IsLeapYear(Source : Word) : Boolean;
      {Determines if the year is a leap year or not}
    Function  Norm2Unix(Y, M, D, H, Min, S : Word) : LongInt;
      {Convert a normal date to its UNIX date. If environment variable "TZ" is
       defined, then the input parameters are assumed to be in **LOCAL TIME**}
    Procedure Unix2Norm(Date : LongInt; Var Y, M, D, H, Min, S : Word);
      {Convert a UNIX date to its normal date counterpart. If the environment
       variable "TZ" is defined, then the output will be in **LOCAL TIME**}

    Function  TodayInUnix : LongInt;
      {Gets today's date, and calls Norm2Unix}
    {
     Following returns a string and requires the TechnoJock totSTR unit.
    Function  Unix2Str(N : LongInt) : String;
    }
    Const
      DaysPerMonth :
        Array[1..12] of ShortInt = (031,028,031,030,031,030,031,031,030,031,030,031);
      DaysPerYear  :
        Array[1..12] of Integer  = (031,059,090,120,151,181,212,243,273,304,334,365);
      DaysPerLeapYear :
        Array[1..12] of Integer  = (031,060,091,121,152,182,213,244,274,305,335,366);
      SecsPerYear      : LongInt  = 31536000;
      SecsPerLeapYear  : LongInt  = 31622400;
      SecsPerDay       : LongInt  = 86400;
      SecsPerHour      : Integer  = 3600;
      SecsPerMinute    : ShortInt = 60;

    IMPLEMENTATION

    Function GetTimeZone : ShortInt;
    Var
      Environment : String;
      Index : Integer;
    Begin
      GetTimeZone := 0;                            {Assume UTC}
      Environment := GetEnv('TZ');       {Grab TZ string}
      For Index := 1 To Length(Environment) Do
        Environment[Index] := Upcase(Environment[Index]);
    (*
      NOTE: I have yet to find a complete list of the ISO table of time zone
            abbreviations. The following is excerpted from the Opus-Cbcs
            documentation files.
    *)
      If Environment =  'EST05'    Then GetTimeZone := -05; {USA EASTERN}
      If Environment =  'EST05EDT' Then GetTimeZone := -06;
      If Environment =  'CST06'    Then GetTimeZone := -06; {USA CENTRAL}
      If Environment =  'CST06CDT' Then GetTimeZone := -07;
      If Environment =  'MST07'    Then GetTimeZone := -07; {USA MOUNTAIN}
      If Environment =  'MST07MDT' Then GetTimeZone := -08;
      If Environment =  'PST08'    Then GetTimeZone := -08;
      If Environment =  'PST08PDT' Then GetTimeZone := -09;
      If Environment =  'YST09'    Then GetTimeZone := -09;
      If Environment =  'AST10'    Then GetTimeZone := -10;
      If Environment =  'BST11'    Then GetTimeZone := -11;
      If Environment =  'CET-1'    Then GetTimeZone :=  01;
      If Environment =  'CET-01'   Then GetTimeZone :=  01;
      If Environment =  'EST-10'   Then GetTimeZone :=  10;
      If Environment =  'WST-8'    Then GetTimeZone :=  08; {Perth, Western Austrailia}
      If Environment =  'WST-08'   Then GetTimeZone :=  08;
    End;

    Function IsLeapYear(Source : Word) : Boolean;
    Begin
    (*
      NOTE: This is wrong!
    *)
      If (Source Mod 4 = 0) Then
        IsLeapYear := True
      Else
        IsLeapYear := False;
    End;

    Function Norm2Unix(Y,M,D,H,Min,S : Word) : LongInt;
    Var
      UnixDate : LongInt;
      Index    : Word;
    Begin
      UnixDate := 0;                                                 {initialize}
      Inc(UnixDate,S);                                              {add seconds}
      Inc(UnixDate,(SecsPerMinute * Min));                          {add minutes}
      Inc(UnixDate,(SecsPerHour * H));                                {add hours}
      (*************************************************************************)
      (* If UTC = 0, and local time is -06 hours of UTC, then                  *)
      (* UTC := UTC - (-06 * SecsPerHour)                                      *)
      (* Remember that a negative # minus a negative # yields a positive value *)
      (*************************************************************************)
      UnixDate := UnixDate - (GetTimeZone * SecsPerHour);            {UTC offset}

      If D > 1 Then                                 {has one day already passed?}
        Inc(UnixDate,(SecsPerDay * (D-1)));

      If IsLeapYear(Y) Then
        DaysPerMonth[02] := 29
      Else
        DaysPerMonth[02] := 28;                             {Check for Feb. 29th}

      Index := 1;
      If M > 1 Then For Index := 1 To (M-1) Do    {has one month already passed?}
        Inc(UnixDate,(DaysPerMonth[Index] * SecsPerDay));

      While Y > 1970 Do
      Begin
        If IsLeapYear((Y-1)) Then
          Inc(UnixDate,SecsPerLeapYear)
        Else
          Inc(UnixDate,SecsPerYear);
        Dec(Y,1);
      End;

      Norm2Unix := UnixDate;
    End;

    Procedure Unix2Norm(Date : LongInt; Var Y, M, D, H, Min, S : Word);
    {}
    Var
      LocalDate : LongInt;
      Done      : Boolean;
      X         : ShortInt;
      TotDays   : Integer;
    Begin
      Y   := 1970;
      M   := 1;
      D   := 1;
      H   := 0;
      Min := 0;
      S   := 0;
      LocalDate := Date + (GetTimeZone * SecsPerHour);         {Local time date}
     (*************************************************************************)
     (* Sweep out the years...                                                *)
     (*************************************************************************)
      Done := False;
      While Not Done Do
      Begin
        If LocalDate >= SecsPerYear Then
        Begin
          Inc(Y,1);
          Dec(LocalDate,SecsPerYear);
        End
        Else
          Done := True;

        If (IsLeapYear(Y+1)) And (LocalDate >= SecsPerLeapYear) And
           (Not Done) Then
        Begin
          Inc(Y,1);
          Dec(LocalDate,SecsPerLeapYear);
        End;
      End;
      (*************************************************************************)
      M := 1;
      D := 1;
      Done := False;
      TotDays := LocalDate Div SecsPerDay;
      If IsLeapYear(Y) Then
      Begin
        DaysPerMonth[02] := 29;
        X := 1;
        Repeat
          If (TotDays <= DaysPerLeapYear[x]) Then
          Begin
            M := X;
            Done := True;
            Dec(LocalDate,(TotDays * SecsPerDay));
            D := DaysPerMonth[M]-(DaysPerLeapYear[M]-TotDays) + 1;
          End
          Else
            Done := False;
          Inc(X);
        Until (Done) or (X > 12);
      End
      Else
      Begin
        DaysPerMonth[02] := 28;
        X := 1;
        Repeat
          If (TotDays <= DaysPerYear[x]) Then
          Begin
            M := X;
            Done := True;
            Dec(LocalDate,(TotDays * SecsPerDay));
            D := DaysPerMonth[M]-(DaysPerYear[M]-TotDays) + 1;
          End
          Else
            Done := False;
          Inc(X);
        Until Done = True or (X > 12);
      End;
      H := LocalDate Div SecsPerHour;
        Dec(LocalDate,(H * SecsPerHour));
      Min := LocalDate Div SecsPerMinute;
        Dec(LocalDate,(Min * SecsPerMinute));
      S := LocalDate;
    End;

    Function  TodayInUnix : LongInt;
    Var
      Year, Month, Day, DayOfWeek: Word;
      Hour, Minute, Second, Sec100: Word;
    Begin
      GetDate(Year, Month, Day, DayOfWeek);
      GetTime(Hour, Minute, Second, Sec100);
      TodayInUnix := Norm2Unix(Year,Month,Day,Hour,Minute,Second);
    End;

    Function  Unix2Str(N : LongInt) : String;
    Var
      Year, Month, Day, DayOfWeek  : Word;
      Hour, Minute, Second, Sec100 : Word;
      T : String;
    Begin
      Unix2Norm(N, Year, Month, Day, Hour, Minute, Second);
      T := PadRight(IntToStr(Month),2,'0')+'-'+PadRight(IntToStr(Day),2,'0')+'-'+
           PadRight(IntToStr(Year),2,'0')+' '+ PadRight(IntToStr(Hour),2,'0')+':'+
           PadRight(IntToStr(Minute),2,'0')+':'+PadRight(IntToStr(Second),2,'0');
      If Hour > 12 Then
        T := T + ' PM'
      Else
        T := T + ' AM';
      Unix2Str := T;
    End;

    END.

[Back to DATETIME SWAG index] [Back to Main SWAG index] [Original]