DOS date and time stamps are stored as an integer, here are some functions I wrote to convert them.
DOS date to human readable date
Public Function DOSDate2Date(ByVal value As Long) As String
Dim BinaryDate As String, Month As String, Day As String, Year As String
Dim temp As String
If value = 0 Then GoTo NoDate:
BinaryDate = Dec2Bin(value)
If Len(BinaryDate) 10 Then GoTo BadFormat:
Year = Dec2Bin((Val(Right(value, 4) - 1980)))
Month = Dec2Bin(Val(Left(value, 2)))
Day = Dec2Bin(Val(Right(Left(value, 5), 2)))
If Len(Year) 7 Then Year = "1111111"
If Len(Month) > 4 Then Month = "1111"
If Len(Day) > 5 Then Day = "11111"
Date2DOSDate = Bin2Dec(Year & Month & Day)
Exit Function
NoDate:
Date2DOSDate = 0
Exit Function
BadFormat:
MsgBox "Incorrect Date format!", vbExclamation
Date2DOSDate = -1
Exit Function
error:
MsgBox "Incorrect Date format!", vbExclamation
HandleError
Date2DOSDate = -1
End Function
Human readable time to DOS time
Public Function Time2DOSTime(ByVal value As String) As Long
On Error GoTo error:
Dim BinaryTime As String, Hour As String, Minute As String, Second As String
Dim temp As String
If value = "00:00:00" Then GoTo NoTime:
If Len(value) 8 Then GoTo BadFormat:
Hour = Dec2Bin(Val(Left(value, 2)))
Minute = Dec2Bin(Val(Right(Left(value, 5), 2)))
Second = Dec2Bin((Val(Right(value, 2)) / 2))
If Len(Hour) 5 Then Hour = "11111"
If Len(Minute) > 6 Then Minute = "111111"
If Len(Second) > 5 Then Second = "11111"
Time2DOSTime = Bin2Dec(Hour & Minute & Second)
Exit Function
NoTime:
Time2DOSTime = 0
Exit Function
BadFormat:
MsgBox "Incorrect time format!", vbExclamation
Time2DOSTime = -1
Exit Function
error:
MsgBox "Incorrect time format!", vbExclamation
HandleError
Time2DOSTime = -1
End Function
Binary to Decimal conversion function (not written by me)
Public Function Bin2Dec(ByVal BinValue As String) As Long
Dim lngValue As Long
Dim x As Long
Dim k As Long
k = Len(BinValue) ' will only work with 32 or fewer "bits"
For x = k To 1 Step -1 ' work backwards down string
If Mid$(BinValue, x, 1) = "1" Then
If k - x > 30 Then ' bit 31 is the sign bit
lngValue = lngValue Or -2147483648# ' avoid overflow error
Else
lngValue = lngValue + 2 ^ (k - x)
End If
End If
Next x
Bin2Dec = lngValue
End Function
Decimal to Binary conversion function (not written by me)
Public Function Dec2Bin(ByVal mynum As Variant) As String
Dim loopcounter As Integer
If mynum >= 2 ^ 31 Then
Dec2Bin = "Number too big"
Exit Function
End If
Do
If (mynum And 2 ^ loopcounter) = 2 ^ loopcounter Then
Dec2Bin = "1" & Dec2Bin
Else
Dec2Bin = "0" & Dec2Bin
End If
loopcounter = loopcounter + 1
Loop Until 2 ^ loopcounter > mynum
End Function
Error Handler
Public Sub HandleError()
MsgBox Err.Source & vbCrLf & "Error " & Err.Number & ": " & Err.Description, vbExclamation
Err.Clear
End Sub
VB6 - DOS Date/Time Conversions [Archive] - ForumsHQ
-
Locke Cole
- Posts: 0
- Joined: Fri Jun 21, 2002 5:00 am
Re: VB6 - DOS Date/Time Conversions [Archive] - ForumsHQ
I forget, but does VB support shift left and shift right operators? I'm pretty sure it supports binary 'and' and binary 'or'. But if it supports those, you can do the conversion much more simply (and faster) by using those rather than going from an integer to a string then back to integers.
Re: VB6 - DOS Date/Time Conversions [Archive] - ForumsHQ
I forget, but does VB support shift left and shift right operators? I'm pretty sure it supports binary 'and' and binary 'or'. But if it supports those, you can do the conversion much more simply (and faster) by using those rather than going from an integer to a string then back to integers.
i believe you are right, but i'm not all too sure how and when to use 'and' in those ways. have a good doc on it?
i believe you are right, but i'm not all too sure how and when to use 'and' in those ways. have a good doc on it?
-
Locke Cole
- Posts: 0
- Joined: Fri Jun 21, 2002 5:00 am
Re: VB6 - DOS Date/Time Conversions [Archive] - ForumsHQ
i believe you are right, but i'm not all too sure how and when to use 'and' in those ways. have a good doc on it?
Well the more important commands are shift left and shift right, you can mimic those by using division (to shift right by one, divide by 2, to shift right by two, divide by 4, to shift right by three, divide by 8, and so on) and multiplication (same scenario as division except you multiply by powers of 2).
I'll see if I can come up with something you could use as a guide of sorts.
Actually, here's the Date decoding code. I don't have routines that deal with the full 32-bit date/time integer as a whole, because in Delphi I split them into their seperate 16-bit component date and time parts. But still, you should get the idea. I've also included the ASM code that can be optionally used for completness sake--
procedure DecodeDOSDate(Date: word; var Year, Month, Day: word); register;
{$IFDEF PUREPASCAL}
begin
Year := ((Date and $FE00) shr 9) + 1980;
Month := ((Date and $1E0) shr 5);
Day := Date and $1F;
// perform some validation perhaps? Month is 4-bits, that allows for 0 to
// 15, and there are only 12 months
end;
{$ELSE}
asm
{ EAX Date }
{ EDX ^Year }
{ ECX ^Month }
{ [EBP+8] ^Day }
PUSH EBX
MOV EBX, Day
PUSH EAX
AND EAX, $0000FE00
SHR EAX, 9
ADD EAX, 1980
MOV [EDX], EAX
MOV EAX, [ESP]
MOV EDX, 1
AND EAX, $000001E0
SHR EAX, 5
JNZ @@1
MOV EAX, EDX
// CMOVZ EAX, EDX
@@1:
CMP EAX, 12
JNA @@2
MOV EAX, 12
@@2:
MOV [ECX], EAX
POP EAX
AND EAX, $0000001F
JNZ @@3
MOV EAX, EDX
// CMOVZ EAX, EDX
@@3:
MOV [EBX], EAX
POP EBX
end;
{$ENDIF}
Just look at the code between {$IFDEF PUREPASCAL} and {$ELSE}, that's the non-assembly Pascal code. As stated in the comments, there might be some arguement for some validation code-- especially if you use the month as an index into an array of 12 month names, if the value was outside the range of array elements you could conceivably end up with a run-time error.
Well the more important commands are shift left and shift right, you can mimic those by using division (to shift right by one, divide by 2, to shift right by two, divide by 4, to shift right by three, divide by 8, and so on) and multiplication (same scenario as division except you multiply by powers of 2).
I'll see if I can come up with something you could use as a guide of sorts.
Actually, here's the Date decoding code. I don't have routines that deal with the full 32-bit date/time integer as a whole, because in Delphi I split them into their seperate 16-bit component date and time parts. But still, you should get the idea. I've also included the ASM code that can be optionally used for completness sake--
procedure DecodeDOSDate(Date: word; var Year, Month, Day: word); register;
{$IFDEF PUREPASCAL}
begin
Year := ((Date and $FE00) shr 9) + 1980;
Month := ((Date and $1E0) shr 5);
Day := Date and $1F;
// perform some validation perhaps? Month is 4-bits, that allows for 0 to
// 15, and there are only 12 months
end;
{$ELSE}
asm
{ EAX Date }
{ EDX ^Year }
{ ECX ^Month }
{ [EBP+8] ^Day }
PUSH EBX
MOV EBX, Day
PUSH EAX
AND EAX, $0000FE00
SHR EAX, 9
ADD EAX, 1980
MOV [EDX], EAX
MOV EAX, [ESP]
MOV EDX, 1
AND EAX, $000001E0
SHR EAX, 5
JNZ @@1
MOV EAX, EDX
// CMOVZ EAX, EDX
@@1:
CMP EAX, 12
JNA @@2
MOV EAX, 12
@@2:
MOV [ECX], EAX
POP EAX
AND EAX, $0000001F
JNZ @@3
MOV EAX, EDX
// CMOVZ EAX, EDX
@@3:
MOV [EBX], EAX
POP EBX
end;
{$ENDIF}
Just look at the code between {$IFDEF PUREPASCAL} and {$ELSE}, that's the non-assembly Pascal code. As stated in the comments, there might be some arguement for some validation code-- especially if you use the month as an index into an array of 12 month names, if the value was outside the range of array elements you could conceivably end up with a run-time error.
-
Locke Cole
- Posts: 0
- Joined: Fri Jun 21, 2002 5:00 am
Re: VB6 - DOS Date/Time Conversions [Archive] - ForumsHQ
Actually, it probably looks better and makes more sense if it's syntax highlighted. I'll attach an image.
-
zarus
Re: VB6 - DOS Date/Time Conversions [Archive] - ForumsHQ
I was searching the web for a way to convert 16-bit DOS file date and time to conventional date and time when I came upon this thread. I've accessed files on my machine and observed the file name, dates, time etc. Dates and times are in 16 DOS format. I wrote a C code to convert the date and time to conventional format(using bit mask). However I cannot figure out how to do the reverse, conventional to DOS. Do you have a C version (not C++) of the above code ?.
The DOS file dates 12367 converted to 15/2/2004, and 11341 converted to 13/2/2002.
Thanks for your help.
:punch:
The DOS file dates 12367 converted to 15/2/2004, and 11341 converted to 13/2/2002.
Thanks for your help.
:punch: