Code archives/File Utilities/File Date/Time/Attr functions for b+

This code has been declared by its author to be Public Domain code.

Download source code

File Date/Time/Attr functions for b+ by Snarkbait2008
Uses kernel32 functions to get file date/time information, also you can get file attribute information.

GetFileDateStringFromType() function returns date in US format, apologies to those from elsewhere... could easily be altered to your local accepted date/time format.
; filetime.bb include file
; File Date & Time, Attributes functions 
; by snarkbait
; snarkbait66@gmail.com
;
; typical Microsoft - it takes no less than FIVE api function calls to get the proper date!
;
; add the following to kernel32.decls
; .lib "kernel32.dll"
;
;api_GetFileTime%(hFile%,lpCreationTime*,lpLastAccessTime*,lpLastWriteTime*):"GetFileTime"
;api_CreateFile%(FileName$, dwDesiredAccess%, dwShareMode%, lpSecurity%, dwCreationDsp%, dwFlagsAndAttr%, hTemplate%):"CreateFileA"
;api_FileTimeToSystemTime%(lpFileTime*, lpSystemTime*):"FileTimeToSystemTime"
;api_CloseHandle%( hObject% ):"CloseHandle"
;api_FileTimeToLocalFileTime%(lpFileTime*, lpLocalFileTime*):"FileTimeToLocalFileTime" 
;
;; also, to get file attributes, add
; api_GetFileAttributes%( lpFilename$ ):"GetFileAttributesA"
;


Type SYSTEMTIME
	Field wYear%
	Field wMonth%
	Field wDayOfWeek%
	Field wDay%
	Field wHour%
	Field wMinute%
	Field wSecond%
	Field wMilliseconds%
End Type

; API constants

; CreateFile:Desired Access
Const GENERIC_WRITE = $40000000
Const GENERIC_READ = $80000000
; CreateFile:FlagsAndAttributes
Const FILE_ATTRIBUTE_NORMAL = $80
; CreateFile:CreationDisposition
Const OPEN_EXISTING = 3
; CreateFile:ShareMode
Const FILE_SHARE_READ = 1
Const FILE_SHARE_WRITE = 2

; other constants
Const FILETIMESIZE = 8
Const SYSTEMTIMESIZE = 16
Const GET_CREATION = 0
Const GET_LASTACCESS = 1
Const GET_LASTMODIFIED = 2
Const ATTR_STRING$ = "RHSVDALC"

;==========================================================================
; FUNCTION: FileDateTime()
; PARAMS:
;			filename$ : valid filename/path string
;			[returnType] : default GET_LASTMODIFIED, or GET_CREATION, GET_LASTACCESS
;						Specifies if you want the file creation, last modified, or last accessed date/time
;						Last Modified is the generally used 'file date'
; CALLS:
;			FileExists()
;			api_CreateFile() : kernel32.dll function - returns handle for subsequent i/o ops
;			api_GetFileTime() : kernel32.dll function - fills passed banks with 64-bit UTC date/time value
;			api_FileTimeToLocalTime : kernel32.dll function - converts from 64bit UTC to systemtime struct
;			api_FileTimeToSystemTime : kernel32.dll function - converts sytemtime struct to same with localized date/time values
;			api_CloseHandle : kernel32.dll - Closes file handle opened with api_CreateFile()
;			GetFileDateFromBank() : constructor method for type SYSTEMTIME, creates instance and
;									fills it with values from the passed bank
;
; RETURNS:
;	Instance of type SYSTEMTIME 
; OTHER: If you do not specify dwShareMode for CreateFile, and filename is already opened, WILL CAUSE CRASH.
;		Keep sharemode to 'FILE_SHARE_READ Or FILE_SHARE_WRITE'
Function FileDateTime.SYSTEMTIME( filename$, returnType = GET_LASTMODIFIED )
	Local hFile%
	Local success%
	Local retValue%
	Local bankCreationFileTime = CreateBank(FILETIMESIZE)
	Local bankLastAccessFileTime = CreateBank(FILETIMESIZE)
	Local bankLastModifiedFileTime = CreateBank(FILETIMESIZE)
	Local bankLocalFileTime = CreateBank(FILETIMESIZE)
	Local bankSystemTime = CreateBank(SYSTEMTIMESIZE)
	
	; check file
	If Not FileExists( filename$ )
		Return Null
	EndIf
	
	; get api file handle
	hFile = api_CreateFile( filename$, GENERIC_WRITE Or GENERIC_READ, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
	If hFile > 0
		; get 64-bit UDT, for all three options
		success = api_GetFileTime(hFile, bankCreationFileTime, bankLastAccessFileTime, bankLastModifiedFileTime)
		If success
			; convert selected return type to local time
			Select returnType
				Case GET_CREATION
					success = api_FileTimeToLocalFileTime( bankCreationFileTime, bankLocalFileTime )
				Case GET_LASTACCESS
					success = api_FileTimeToLocalFileTime( bankLastAccessFileTime, bankLocalFileTime )
				Case GET_LASTMODIFIED
					success = api_FileTimeToLocalFileTime( bankLastModifiedFileTime, bankLocalFileTime )
				Default
					success = False
			End Select
			If success
				; convert to structured time info ( & free unused banks)
				FreeBank bankCreationFileTime
				FreeBank bankLastModifiedFileTime
				FreeBank bankLastAccessFileTime
				success = api_FileTimeToSystemTime(bankLocalFileTime, bankSystemTime)
				If success
					; create type object and fill with bank values
					FreeBank bankLocalFileTime
					this.SYSTEMTIME = GetFileDateFromBank( bankSystemTime )
					FreeBank bankSystemTime
					; didn't create type properly
					If this.SYSTEMTIME = Null
						retValue = False
					Else
						; everything OK
						retValue = True
					EndIf
				Else
					; error, but needs close file
					retValue = False
				EndIf
			Else
				; error, but needs close file
				retValue = False
			EndIf
		Else
			; error, but needs close file
			retValue = False
		EndIf
	Else
		; error
		Return Null
	EndIf
	
	If retValue
		; everything OK, close file and return Object
		api_CloseHandle( hFile)
		Return this
	Else
		; SNAFU, close file and return null
		api_CloseHandle( hFile)
		Return Null
	EndIf
End Function

;==========================================================================
; FUNCTION: GetFileDateFromBank()
; PARAMS:
;			inBank : 16-byte bank in the SYSTEMTIME format
; CALLS:
; RETURNS:
;	Instance of type SYSTEMTIME, filled with values from bank
; OTHER:
;

Function GetFileDateFromBank.SYSTEMTIME( inBank )

	; check bank is the right size
	If BankSize( inBank ) < SYSTEMTIMESIZE Return Null
	
	; create instance
	Local this.SYSTEMTIME = New SYSTEMTIME
	
	; peek 2-byte values from bank
	this\wYear = PeekShort( inBank, 0 )
	this\wMonth = PeekShort( inBank, 2 )
	this\wDayOfWeek = PeekShort( inBank, 4 )
	this\wDay = PeekShort( inBank, 6 ) 
	this\wHour = PeekShort( inBank, 8 ) 
	this\wMinute = PeekShort( inBank, 10 )
	this\wSecond = PeekShort( inBank, 12 )
	this\wMilliseconds = PeekShort( inBank, 14 )
	
	; return Object
	Return this
End Function

;==========================================================================
; FUNCTION: GetFileDateStringFromType()
; PARAMS:
;			this.SYSTEMTIME : object of type SYSTEMTIME
; CALLS:
; RETURNS:
;	String in American date format, i.e. "MM/DD/YYYY HH:MM:SS {AM/PM}"
; OTHER:		
;

Function GetFileDateStringFromType$( this.SYSTEMTIME )
	Local retStr$
	Local AMPM$
	Local hrs
	Local strMin$
	Local strSec$
	
	; meridiem
	If this\wHour > 11
		AMPM$ = "PM"
	Else
		AMPM$ = "AM"
	EndIf
	
	; convert from military time
	hrs = this\wHour Mod 12
	If hrs = 0 hrs = 12
	
	; fix minute/second strings to 2 places
	If this\wMinute < 10
		strMin = "0" + this\wMinute
	Else
		strMin = Str(this\wMinute)
	EndIf
	If this\wSecond < 10
		strSec = "0" + this\wSecond
	Else
		strSec = Str(this\wSecond)
	EndIf
	
	;concatenate
	retStr = Str(this\wMonth) + "/" + Str(this\wDay) + "/" + Str(this\wYear) + " " + Str(hrs) + ":" + strMin + ":" + strSec + " " + AMPM$
	
	Return retStr
	
End Function

;==========================================================================
; FUNCTION: GetFileAttributesStr()
; PARAMS:
;			filename$ : valid filename/path string
; CALLS:
;			FileExists()
;			api_GetFileAttributes() : kernel32.dll function - returns Long value with file attribute bit flags
; RETURNS:
;	String with accumulated file attributes, i.e. "A" for Archive, "D" for folder, "HSA" for Hidden, System and Archive
;
; OTHER:	N = normal, R = read only, H = hidden S = system V = volume
;           	D = directory, A = archive, L = alias, C = compressed
;	If you want just the integer value, just use the api function api_GetFileAttributes( filename$ ) by itself

Function GetFileAttributesStr$( filename$ )
	If Not FileExists( filename$ )
		Return ""
	EndIf
	
	Local fAttr
	Local retStr$
	Local a
	
	fAttr = api_GetFileAttributes( filename$ )
	
	; mask to 8-bits
	fAttr = fAttr And $FF
	
	; attribute normal
	If fAttr = 0 Then
      	  	retStr$ = "N"
    	Else
      ; loop thru byte to see which bits are set
        	For a = 1 To 8
            		If fAttr And 1 Shl (a - 1) Then
				; bit is set, add proper code from string
                		retStr = retStr + Mid$(ATTR_STRING, a, 1)
            		End If
        	Next
    	End If

	Return retStr
End Function

;==========================================================================
; FUNCTION: FileExists()
; PARAMS:
;			filename$ : valid filename/path string
; CALLS:
; RETURNS:
;	True if file exists, False if not
; OTHER:		
;

Function FileExists( filename$ )
	Local retValue
	If FileType( filename$ ) = 1
		retValue = True
	Else
		retValue = False
	EndIf
	Return retValue
End Function

Comments

Andres2008
Very good. I definately need it at some point.


markcw2008
Example code to test out the functions with.
;Main

Graphics 640,480,0,2
SetBuffer BackBuffer()

filename$=RequestFile("Any file..","",False)

pDate.SYSTEMTIME=FileDateTime(filename$)
USdate$=GetFileDateStringFromType(pDate)
Attr$=GetFileAttributesStr(filename$)

Date$="Date="+pDate\wDay+"/"+pDate\wMonth+"/"+pDate\wYear
Date$=Date$+", Time="+pDate\wHour+":"+pDate\wMinute+":"+pDate\wSecond

Text 0,0,"filename="+filename$
Text 0,12,"USdate="+USdate$
Text 0,24,Date$+" DayOfWeek="+pDate\wDayOfWeek
Text 0,36,"Attr="+Attr$

While Not KeyHit(1)
Wend


And kernel32.decls to just copy+paste.
.lib "kernel32.dll"

Api_GetFileTime%(hFile%,lpCreationTime*,lpLastAccessTime*,lpLastWriteTime*):"GetFileTime"
Api_CreateFile%(FileName$, dwDesiredAccess%, dwShareMode%, lpSecurity%, dwCreationDsp%, dwFlagsAndAttr%, hTemplate%):"CreateFileA"
Api_FileTimeToSystemTime%(lpFileTime*, lpSystemTime*):"FileTimeToSystemTime"
Api_CloseHandle%( hObject% ):"CloseHandle"
Api_FileTimeToLocalFileTime%(lpFileTime*, lpLocalFileTime*):"FileTimeToLocalFileTime" 

;also, to get file attributes, add
Api_GetFileAttributes%( lpFilename$ ):"GetFileAttributesA"



Snarkbait2008
Thx, markcw... you don't need the
pDate.SYSTEMTIME=New SYSTEMTIME


as the FileDateTime function instantiates it for you, call it like

pDate.SYSTEMTIME = FileDateTime( filename$ )



markcw2008
Oops, thanks. Code updated.


Code Archives Forum