'===========================================================================
' Subject: GET/SET FILES DATE/TIME            Date: 07-10-95 (00:00)       
'  Author: Christy Gemmell                    Code: QB, PDS                
'  Origin: GET,SET,FILE,DATE,TIME           Packet: DOS.ABC
'===========================================================================
' FILEDATE.BAS  get and set a files date and time stamps.
'
'   Author:     Christy Gemmell
'   Date:       10/7/1995
'   Language:   QuickBASIC
'
'   $INCLUDE: 'QB.BI'
'
	DECLARE FUNCTION GetDateFormat% ()
	DECLARE FUNCTION GetFileDate$ (FileName$)
	DECLARE FUNCTION Sint% (Num&)
	DECLARE FUNCTION UInt& (Num%)
	DECLARE SUB SetFileDate (FileName$, FileDate$, Fmt%, Done%)

	DIM SHARED Regs AS RegTypeX

	CLS : PRINT : FileName$ = "QB.EXE"
	OldDate$ = GetFileDate$(FileName$)
	IF OldDate$ <> "" THEN
	   PRINT FileName$; " is currently dated "; OldDate$
	   PRINT
	   NewDate$ = LEFT$(DATE$, 6) + MID$(DATE$, 9, 2) + "  " + TIME$
	   PRINT "Setting file to current date and time... ";
	   SetFileDate FileName$, NewDate$, 0, Done%
	   IF Done% THEN
		  PRINT "done"
		  NewDate$ = GetFileDate$(FileName$)
		  PRINT
		  PRINT FileName$; " is now dated "; NewDate$
		  PRINT
		  PRINT "Now reverting back to previous setting... ";
		  SetFileDate FileName$, OldDate$, -1, Done%
		  IF Done% THEN
			 PRINT "done"
			 DateNow$ = GetFileDate$(FileName$)
			 PRINT
			 PRINT FileName$; " is now dated "; DateNow$
		  ELSE
			 PRINT "failed!"
		  END IF
	   ELSE
		  PRINT "failed!"
	   END IF
	END IF
END

'Thanks to Derek Sim who gave me algorithms for inserting and extracting
'the years, months, days, hours, minutes and seconds from the encoded
'bits of the various registers. It made me wish that Microsoft had given
'us a SHIFT statement like PowerBASIC.

'   Returns a code indicating the national date format.
'
'   Return values:  0 = MM-DD-YY   (USA)
'                   1 = DD/MM/YY   (Europe)
'                   2 = YY-MM-DD   (Japan)
'
'   Depends on COUNTRY = setting in CONFIG.SYS (default = USA)
'
FUNCTION GetDateFormat%
	B$ = SPACE$(64)                     ' To hold country information
	Regs.ds = VARSEG(B$)                ' DS = segment of buffer
	Regs.dx = SADD(B$)                  ' DX = offset of buffer
	Regs.ax = &H3800                    ' DOS Service 56
	INTERRUPTX &H21, Regs, Regs         ' - get country information
	GetDateFormat% = ASC(B$)            ' Date format is first byte
END FUNCTION

'   Returns date and time a file was last updated.
'
'   The date and time are returned as a string in one of these formats:
'
'       --123456789012345678--
'
'         MM-DD-YY  HH:MM:SS    (for USA)
'         DD/MM/YY  HH:MM:SS    (for Europe)
'         YY-MM-DD  HH:MM:SS    (for Japan)
'
'   (there are two blank spaces between the date and time
'
FUNCTION GetFileDate$ (FileName$)
	Dt$ = ""                            ' Assume failure
	F$ = FileName$ + CHR$(0)            ' Make filespec ASCIIZ
	Regs.ds = VARSEG(F$)                ' DS = segment of filespec
	Regs.dx = SADD(F$)                  ' DX = offset of filespec
	Regs.ax = &H3D00                    ' DOS Service 61
	INTERRUPTX &H21, Regs, Regs         ' - open file for reading
	Carry% = Regs.flags AND 1           ' Check carry flag
	IF Carry% = 0 THEN                  ' If no error occurred..
	   Handle% = Regs.ax                ' Get handle from AX
	   Regs.bx = Handle%                ' Transfer it to BX
	   Regs.ax = &H5700                 ' DOS Service 87
	   INTERRUPTX &H21, Regs, Regs      ' - get file date and time
	   Carry% = Regs.flags AND 1        ' Check carry flag
	   IF Carry% = 0 THEN               ' If no error occurred..
		  FlTime& = UInt&(Regs.cx)      ' Bit-encoded time from CX
		  FlDate& = UInt&(Regs.dx)      ' Bit-encoded date from DX
		  Yr% = (FlDate& \ 512) + 1980  ' Get year
		  FlDate& = FlDate& AND &H1FF   ' Isolate day and month
		  Mth% = FlDate& \ 32           ' Get month
		  Day% = FlDate& AND &H1F       ' Get day
		  Hrs% = FlTime& \ 2048         ' Get hours
		  FlTime& = FlTime& AND &H7FF   ' Isolate minutes and seconds
		  Mins% = FlTime& \ 32          ' Get hours
		  Sex% = (FlTime& AND &H1F) * 2 ' Get seconds
		  Y$ = RIGHT$("0" + LTRIM$(RTRIM$(STR$(Yr%))), 2)
		  M$ = RIGHT$("0" + LTRIM$(RTRIM$(STR$(Mth%))), 2)
		  D$ = RIGHT$("0" + LTRIM$(RTRIM$(STR$(Day%))), 2)
		  Fmt% = GetDateFormat%         ' Get national date format
		  SELECT CASE Fmt%
			  CASE 0                    ' USA
				   Dt$ = M$ + "-" + D$ + "-" + Y$
			  CASE 1                    ' Europe
				   Dt$ = D$ + "/" + M$ + "/" + Y$
			  CASE 2                    ' Japan
				   Dt$ = Y$ + "-" + M$ + "-" + D$
			  CASE ELSE
		  END SELECT
		  H$ = RIGHT$("0" + LTRIM$(RTRIM$(STR$(Hrs%))), 2)
		  M$ = RIGHT$("0" + LTRIM$(RTRIM$(STR$(Mins%))), 2)
		  S$ = RIGHT$("0" + LTRIM$(RTRIM$(STR$(Sex%))), 2)
		  Dt$ = Dt$ + "  " + H$ + ":" + M$ + ":" + S$
	   END IF
	   Regs.bx = Handle%                ' File handle to BX
	   Regs.ax = &H3E00                 ' DOS Service 62
	   INTERRUPTX &H21, Regs, Regs      ' - close the file
	END IF
	GetFileDate$ = Dt$                  ' Return date and time as string
END FUNCTION

'   Sets the last-access date and time of the specified file.
'
'   Note: FileDate$ must be in one of the following formats:
'
'       --123456789012345678--
'
'         MM-DD-YY  HH:MM:SS    (for USA)
'         DD/MM/YY  HH:MM:SS    (for Europe)
'         YY-MM-DD  HH:MM:SS    (for Japan)
'
'   (there are two blank spaces between the date and time
'
'   If Fmt% is TRUE (non-zero) then the procedure uses the date
'   format for the country corresponding to the COUNTRY= setting
'   in the computers CONFIG.SYS file (default = USA)
'
'   If Fmt% is FALSE (zero) then USA format is used.
'
SUB SetFileDate (FileName$, FileDate$, Fmt%, Done%)
	Done% = 0                           ' Assume failure
	F$ = FileName$ + CHR$(0)            ' Make filespec ASCIIZ
	Regs.ds = VARSEG(F$)                ' DS = segment of filespec
	Regs.dx = SADD(F$)                  ' DX = offset of filespec
	Regs.ax = &H3D00                    ' DOS Service 61
	INTERRUPTX &H21, Regs, Regs         ' - open file for reading
	Carry% = Regs.flags AND 1           ' Check carry flag
	IF Carry% = 0 THEN                  ' If no error occurred..
	   Handle% = Regs.ax                ' Get handle from AX
	   IF Fmt% THEN
		  Fmt% = GetDateFormat%         ' Get national date format
	   END IF
	   SELECT CASE Fmt%
		   CASE 0                       ' USA
				Day% = VAL(MID$(FileDate$, 4, 2))
				Mth% = VAL(LEFT$(FileDate$, 2))
				Yr% = VAL(MID$(FileDate$, 7, 2))
		   CASE 1                       ' Europe
				Mth% = VAL(MID$(FileDate$, 4, 2))
				Day% = VAL(LEFT$(FileDate$, 2))
				Yr% = VAL(MID$(FileDate$, 7, 2))
		   CASE 2                       ' Japan
				Mth% = VAL(MID$(FileDate$, 4, 2))
				Yr% = VAL(LEFT$(FileDate$, 2))
				Day% = VAL(MID$(FileDate$, 7, 2))
		   CASE ELSE
	   END SELECT
	   Hrs% = VAL(MID$(FileDate$, 11, 2))
	   Mins% = VAL(MID$(FileDate$, 14, 2))
	   Sex% = VAL(MID$(FileDate$, 17, 2))
	   IF Yr% < 80 THEN Yr% = Yr% + 100 ' Remember the 21st Century
	   FlDate& = ((Yr% - 80) * 512) + (Mth% * 32) + Day%
	   Regs.dx = Sint%(FlDate&)         ' Load result into DX
	   FlTime& = (Hrs% * 2048&) + (Mins% * 32) + (Sex% \ 2)
	   Regs.cx = Sint%(FlTime&)         ' Load result into CX
	   Regs.bx = Handle%                ' File handle to BX
	   Regs.ax = &H5701                 ' DOS Service 87
	   INTERRUPTX &H21, Regs, Regs      ' - set file date and time
	   Carry% = Regs.flags AND 1        ' Check carry flag
	   IF Carry% = 0 THEN               ' If no error occurred..
		  Done% = -1                    '   report success
	   END IF
	   Regs.bx = Handle%                ' File handle to BX
	   Regs.ax = &H3E00                 ' DOS Service 62
	   INTERRUPTX &H21, Regs, Regs      ' - close the file
	END IF
END SUB

FUNCTION Sint% (Num&)
	Sint% = -((Num& > 32767) * (Num& - 65536)) - ((Num& < 32767) * Num&)
END FUNCTION

FUNCTION UInt& (Num%)
	UInt& = -((Num% < 0) * (65536 + Num%) + ((Num% >= 0) * Num%))
END FUNCTION

