How to read Date from VB binary-file in another language? - vb.net

I get a binary file from a VB-application which consists of about 1400 records of a Timestamp in Date format followed by 19 Long values.
I am able to read the data in VBA with this function:
Dim myDate As Date
Dim myLong As Long
iFileNum = FreeFile
Open "C:\test.bin" For Binary Access Read As #iFileNum
Do While Not EOF(iFileNum)
Get iFileNum, , myDate
MsgBox(myDate)
For i = 1 To 19
Get iFileNum, , myLong
Next i
Loop
Now i want to read the Date-timestamps from the file (I am already able to read the Long-values) within java, but i cannot find any information on how to interpret the 8 bytes of the Date-type.
As an example, the first timestamp in binary form is c5 b3 a2 11 80 7b e4 40.
VB output for this is 2014-11-05 0:03:06 AM.
To clarify, I am not looking for a java implementation, but for information of the binary representation of data type 'Date' from VB.
(for which i wasn't able to find any more information as than this http://msdn.microsoft.com/en-us/library/3eaydw6e.aspx , which doesn't help much)

As #RBarryYoung mentions in his comment to the question, VBA stores Date/Time values internally as floating-point Double values. The integer part is the number of days since 1899-12-30 and the fractional part is the time (e.g., 0.25 = 6 AM, 0.5 = Noon, 0.75 = 6 PM).
In the example you gave, the Date/Time (Double) value is stored in bytes as c5 b3 a2 11 80 7b e4 40. Windows has always been a little-endian environment, so by reversing the order of the bytes we know that it corresponds to the 64-bit binary value 0x40e47b8011a2b3c5.
A Binary-to-IEEE_Double convertor like this one tells us that the decimal Double value is 4.19480021527777789742685854435E4, and if we ask VBA what the corresponding Date/Time value is we get
?CDate(41948.0021527777789742685854435)
2014-11-05 00:03:06

Related

How to compute custom timestamp in COBOL85 Tandem?

I want to calculate timestamp for custom date and time.
E.g 23/09/2022 4:30:45
To calculate Julian Timestamp of current date and time you can use JULIANTIMESTAMP using ENTER TAL but for Custom timestamp we have COMPUTETIMESTAMP GPC .
Syntax from GPC Reference manual
jval := COMPUTETIMESTAMP ( date-n-time,
[error-mask] );
Data types
jval is 64-bit Fixed Julian timestamp .
date-n-time is an integer array of date and time [YYYY,MM,DD,HH,,MM,SS,MIL,MIC] all elements of array are compulsory.
error-mask is integer array of bits 1 or 0 of length 8.
So let's Jump to the main Question how to Calculate Custom timestamp in COBOL85 . I have small example .
?ANSI
?save param
?symbols
?inspect
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 USER-FLD-CUST PIC X(50).
01 ARR.
03 DT PIC S9(4) COMP OCCURS 8 TIMES.
01 VAL PIC 9(16).
01 JTIME PIC S9(18) VALUE 0.
01 CER.
03 ERR PIC S9(1) COMP OCCURS 8 TIMES.
PROCEDURE DIVISION.
PROGRAM-BEGIN.
MOVE 2022 TO DT(1).
MOVE 99 TO DT(2).
MOVE 30 TO DT(3).
MOVE 10 TO DT(4).
MOVE 00 TO DT(5).
MOVE 00 TO DT(6).
MOVE 000 TO DT(7).
MOVE 000 TO DT(8).
ENTER TAL "COMPUTETIMESTAMP" USING ARR , CER
GIVING JTIME.
IF JTIME = -1
DISPLAY "INVALID DATE"
ELSE
DISPLAY JTIME.
STOP RUN.

Convert character variable to numeric variable in SAS

I'm trying to convert a character variable to a numeric variable, but unfortunately i'm really struggeling. Help would be appreciated!
I keep getting the following error: 'Invalid argument to function INPUT at line 3259 column 17'
Syntax:
Data want;
Set have;
Dosis_num = input(Dosis, best12.);
run;
I have also tried multiplying the variable by 1. This doesnt work either.
The variable looks like this:
Dosis
155
201
2.1
0.8
123.80
12.0
3333.4
00.6
Want:
Dosis_num
155.0
201.0
2.1
0.8
123.8
12.0
333.4
0.6
Thanks alot!
The code will work with the data you show. So either the values in the character variable are not what you think or you are not using the right variable name for the variable.
The code is trying to only use the first 12 bytes of the character variable. Normally you don't need to restrict the number of characters you ask the INPUT() function to use. In fact the INPUT() function does not care if the width of the informat used is larger than the length of the string being read. So just use 32. as the informat since 32 is the maximum width that the normal numeric informat can read. Note that BEST is the name of a FORMAT, if you use it as the name of informat it is just an alias for the normal numeric informat.
If the variable has a length longer than 12 then perhaps there are leading spaces in the variable (note the ODS output displays do not properly display leading spaces) then use the LEFT() function to remove them.
Dosis_num = input(left(Dosis), 32.);
The typical thing to do here is to find out what's actually in the character variable. There is likely something in there that is causing the issue.
Try this:
data have;
input #1 Dosis $8.;
datalines;
155
201
2.1
0.8
123.80
12.0
3333.4
00.6
;;;;
run;
data check;
set have;
put dosis hex32.;
run;
What I get is this:
83 data check;
84 set have;
85 put dosis hex32.;
86 run;
3135352020202020
3230312020202020
322E312020202020
302E382020202020
3132332E38302020
31322E3020202020
333333332E342020
30302E3620202020
NOTE: There were 8 observations read from the data set WORK.HAVE.
NOTE: The data set WORK.CHECK has 8 observations and 1 variables.
NOTE: DATA statement used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
All those 2020202020 are spaces, which should be there (all strings are space-padded to full length). Period/Decimal Point is 2E, Digits are 3x where x is the digit (because the ASCII for 0 is 30, not because of any other reason). So for example for the last one, 00.6, 30 means zero, 30 means zero, 2E means period, and 36 means 6.
Check to make sure that you don't have any other characters other than digits (3x) and period (2e) and space (20).
The other thing to verify is that your system is set to use . as the decimal separator and not , as many European systems are - otherwise this requires the commaw. informat. You can actually just try the commaw. informat (comma12. is sufficient if 12 is plenty - and don't include anything after the period) as anything that 12. can read in also can be read in by commaw..

FormatNumber replacing number with 0

Not understanding this:
Number returned from DataReader: 185549633.66000035
We have a requirement to maintain the number of decimal places per a User Choice.
For example: maintain 7 places.
We are using:
FormatNumber(dr.Item("Field"), 7, TriState.false, , TriState.True)
The result is: 185,549,633.6600000.
We would like to maintain the 3 (or 35) at the end.
When subtracting two numbers from the resulting query we are getting a delta but trying to show these two numbers out to 6,7,8 digits is not working thus indicating a false delta to the user.
Any advice would be appreciated.
Based on my testing, you must be working with Double values rather than Decimal. Not surprisingly, the solution to your problem can be found in the documentation.
For a start, you should not be using FormatNumber. We're not in VB6 anymore ToTo. To format a number in VB.NET, call ToString on that number. I tested this:
Dim dbl = 185549633.66000035R
Dim dec = 185549633.66000035D
Dim dblString = dbl.ToString("n7")
Dim decString = dec.ToString("n7")
Console.WriteLine(dblString)
Console.WriteLine(decString)
and I saw the behaviour you describe, i.e. the output was:
185,549,633.6600000
185,549,633.6600004
I read the documentation for the Double.ToString method (note that FormatNumber would be calling ToString internally) and this is what it says:
By default, the return value only contains 15 digits of precision although a maximum of 17 digits is maintained internally. If the value of this instance has greater than 15 digits, ToString returns PositiveInfinitySymbol or NegativeInfinitySymbol instead of the expected number. If you require more precision, specify format with the "G17" format specification, which always returns 17 digits of precision, or "R", which returns 15 digits if the number can be represented with that precision or 17 digits if the number can only be represented with maximum precision.
I then tested this:
Dim dbl = 185549633.66000035R
Dim dblString16 = dbl.ToString("G16")
Dim dblString17 = dbl.ToString("G17")
Console.WriteLine(dblString16)
Console.WriteLine(dblString17)
and the result was:
185549633.6600004
185549633.66000035

Efficient way to store FilePath

Currently I have a table with the following format/Desc:
ColumnName ColID PK IndexPos Null DataType
ID 1 1 N VARCHAR2 (1 Byte)
FILEPATH 2 N VARCHAR2 (127 Byte)
As you can see the length of ID Column is only 1 Byte we can store only 36 different file paths. I have more than 35 different file paths that has to be stored and retrieved. I know increasing the length of ID solves the issue but I want to also know/suggestion that is there any Efficient way to handle this.
Thanks!
The assertion that you can store only 35 different values in the table is incorrect, because varchar2 characters are not limited to letters and digits (even if they were you'd have 26 letters + 10 digits + 1 empty string = 37, not 35 possibilities).
If you need to store few more paths, say, 40 or 50, you could make your keys mixed case, so 'a' and 'A' would reference different paths. This would instantly give you 26 extra possibilities.
Expanding past the limit of 63 is a little harder, because you need to bring special characters into the mix. However, the theoretical maximum for a single character is 256 plus one combination for an empty string.

How to display the numeric numbers

Here's the content of my DataGrid
id
1
2
3A
4
5
6A
..
...
10V1
I want to get the max number from the datagrid. Then, I want to
display the next number (In this case: 11) in the textbox beside the grid
Expected Output
id
1
2
3A
4
5
6A
..
...
10V1
11
I tried the following code:
textbox1.text = gridList.Rows(gridlist.RowCount() - 1).Cells(1).Value + 1
It works if the previous row values is entirely numeric. However, if the value is alpahnumeric, I am getting the following error:
Conversion from string "10V1" to type 'Double' is not valid.
Can someone help me solve this problem? I am looking for a solution in VB.Net
You may want to look into Regex to do that (based on what I understand from your question)
Here's a related question on this.
Regex.Match will return the part of the string that will match the expression... In your case, you want the first number in your string (Try "^\d+" as your expression, it will find any serie of numbers at the beginning of your string). You can then convert the result string into an int and add 1 to it.
Hope this helps!
Edit: Here's more info on regex expressions.