[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]