How to convert DateTime to 64 bit representation? - vb.net

In another question, I asked how to convert 64 bit _ComObject to native DateTime. I would like to also be able to do the reverse.
The code to convert 64 bit _ComObject to DateTime:
<DirectoryProperty("lastLogonTimestamp")>
Public Property LastLogonTimestamp() As Date?
Get
'Dim valueArray = GetProperty("whenChanged")
Dim valueArray = ExtensionGet("lastLogonTimestamp") 'ExtensionGet("LastLogon")
If valueArray Is Nothing OrElse valueArray.Length = 0 Then Return Nothing
Dim lastLogonDate = valueArray(0)
Dim lastLogonDateType = lastLogonDate.GetType()
Dim highPart = CType(lastLogonDateType.InvokeMember("HighPart", Reflection.BindingFlags.GetProperty, Nothing, lastLogonDate, Nothing), Int32)
Dim lowPart = CType(lastLogonDateType.InvokeMember("LowPart", Reflection.BindingFlags.GetProperty Or Reflection.BindingFlags.Public, Nothing, lastLogonDate, Nothing), Int32)
Dim longDate = CLng(highPart) << 32 Or CLng(lowPart)
Dim result = IIf(longDate > 0, CType(DateTime.FromFileTime(longDate), DateTime?), Nothing)
Return result
'Return DateTime.FromFileTimeUtc(valueArray(0))
End Get
Set(value As Date?)
ExtensionSet("lastLogonTimestamp", value)
End Set
End Property
Working with an example DateTime value of #2/19/2018 8:17:20 AM#, I need a conversion to come back with 64 bit representing both date and time parts. I believe that value should be 131635198405088370, and the reason I think so is because AD says so when I inspect the datetime value.
I have tried this..
Dim my64bitDate = DateTime.Parse("#2/19/2018 8:17:20 AM#").ToFileTime
... which returns 131635198400000000, which is only part of the value I expect.
UPDATE:
Based on HansPrassant's input, I tried more precise datetime value of 2/19/2018 8:17:21 0000001 AM (adding 1 second and 1 nanosecond?), and this resulted in value 131635198410000001 so I believe this is working and correct.

This works... Dim my64bitDate = DateTime.Parse("#2/19/2018 8:17:20 AM#").ToFileTime
Originally, I had been using a value from Active Directory property lastLogonTimestamp that contained more precise value. This precision is not required to use as a filter on the property. A good thing because it is lost during the above parse.
If the original question, and comments don't clear things up, ask a question in the comments below - and I will do my best to answer. Thanks.

Related

How to convert time in string format into datetime format in VB.Net

The following string was generated by this code:
myString = 12:44:44.6111472
myString = Date.Now.TimeOfDay.ToString
I want to add 16.1234567 seconds and the value of myString and assign the resulting value to a new string called myNewString.
Every function I have tried looses the 7 decimal places.
Is there another method I can use that doesn't require me to break apart the entire string value, modify the desired parts, account for carry's, then re-assemble?
If not, then so-be-it.
But, I would like think there is some method, and I'm just not finding it!
Thanks!
Datetime has some parsing functions that you can use. For example:
Dim mystring As String = "12:44:44.6111472"
Dim dt As System.DateTime = System.DateTime.Parse(mystring)
dt += New TimeSpan(16.1234567 * TimeSpan.TicksPerSecond)
mystring = dt.TimeOfDay.ToString()
'now mystring = "12:45:00.7346039"
Here's another approach similar to Ben J's without the use of timespan (which may make things look simpler):
Dim myString = Date.Now.TimeOfDay.ToString
' parse datetime string and add seconds
Dim myDate = DateTime.Parse(myString).AddSeconds(16.1234567)
' outputs 16.123000 so you still lose a few decimal points but not all 7,
' is this close enough precision for you?
Dim ts = String.Format("{0:N6}", (New TimeSpan(myDate.Ticks) - New TimeSpan(DateTime.Parse(myString).Ticks)).TotalSeconds)

TryCast for string to integer in VB.NET

I do not understand at all how to use TryCast in my code, but it is something I need to use for validating user input. I have done various searches and looked at various questions on here, but no one seems to actually say how to use it, and the MSDN website doesn't seem to help at all.
Function ValidateInput(Var_In As String) As Integer
If TryCast(Var_In, Integer) = Nothing Then
Return vbNull
Else
Return Var_In
End If
End Function
The error says that
The operand must be of reference type but Integer is of value type
What is the explanation of what I have done wrong?
TryParse doesn't accept more than 10 digits so for example, an input of "12345678901" won't be accepted. How do I fix this?
Let's try to understand the differences between TryCast, Convert and TryParse.
TryCast
This function will attempt to convert one object into another type, as long as it is a reference type.
Dim MyNewObject = TryCast(MyObject, MyReferenceClass)
If IsNothing(MyNewObject) Then
MessageBox.Show("Impossible to cast")
End If
Since Integer is a value type, it will not work, so we have to figure something out...
Convert
Convert Class on MSDN
From MSDN:
Converts a base data type to another base data type.
So we can try:
Dim myInt = Convert.ToInt32(MyObject)
The problem is that it will generate an exception InvalidCastException if it's impossible to do the conversion.
TryParse
This function is trying to convert a String into something you want. And it will not generate an exception:
Dim myInt As Integer = 0
If Not Integer.TryParse(MyString, myInt) Then
MessageBox.show("This is not an integer")
End If
Limitation
Converting a String into a Integer can sometimes be tricky... If the String represents a number that is greater or lesser than Integer.MaxValue and Integer.MinValue, you will end up with no conversion...
So you can go with a Double:
Double.TryParse(MyString, MyDouble)
Or personally, if you know that it will be a number, use Decimal:
Decimal.TryParse(MyString, MyDecimal)
See Decimals on MSDN
Decimal still has a Max and Min value, according to MSDN:
The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The Decimal value type is appropriate for financial calculations that require large numbers of significant integral and fractional digits and no round-off errors.
Convert.ChangeType
This one is also interesting, but is a bit weird...
You are attempting to perform TryCast against an Integer, which is a value type. TryCast works only on reference types, such as (but not limited to) a Class, Object, or String type.
If you are trying to convert the input parameter to an Integer, you might try one of the methods in the Convert class, such as Convert.ToInt32() or Integer.TryParse.
Instead of TryCast, use TryParse:
Function ValidateInput(Var_In As String) As Integer
Dim iNum As Integer
If (Integer.TryParse(Var_In, iNum)) Then
Return iNum
Else
Return vbNull
End If
End Function
Much better is to use TryParse:
Function ValidateInput(Var_In As String) As Integer
Dim num as Integer
If Not Integer.TryParse(Var_In, num) Then
Return vbNull
Else
Return num
End If
End Function
I'm late to the discussion, but if anyone lands here (like I did) looking for a quick & dirty solution, here a function I'm using for simple cell validation in a DataGridView control.
Function TryTypeFit(theString As String, theType As Type, ShowError As Boolean) As Boolean
Dim TempReturn As Boolean = False
Dim TempObject As Object
Try
TempObject = Convert.ChangeType(theString, theType)
TempReturn = True
Catch ex As Exception
' didn't work
TempReturn = False
If ShowError Then
Dim eMessage As String = "Error: Value must be castable to a " & CStr(theType.Name)
MsgBox(eMessage)
End If
End Try
100:
Return TempReturn
End Function

VB .NET comparing strings

I don't get what's going on. The method equals doesn't work, and neither comparing the strings with the '=' operator or with 'string.compare'. thetruth is always set as "false".
Public Function ProcessLabel(myValue As Object) As String
If ((myValue Is DBNull.Value) = False) Then
Dim thetruth As Boolean
Dim myValueStr As String
myValueStr = CStr(myValue)
thetruth = String.Equals(myValueStr, "01/01/1900")
End If
Return myValue.ToString
End Function
I cannot attach images but I assure you, in myValueStr I have "01/01/1900".
I'm pretty sure that myValue is a Date object and not a string and that a database is involved where the minimum value is 01/01/1900, for example the SMALLDATETIME datatype. If you look at it in debugger you see it like 01/01/1900. But if you execute ToString( internally used on CStr(myValue)) you get the localized representation including the time portion, so something like 01.01.1900 00:00:00 (f.e. in germany).
Instead compare the right types:
If Not myValue Is DBNull.Value AndAlso Not myValue Is Nothing Then
Dim date = DirectCast(myValue, Date)
If date = New Date(1900, 01, 01) Then
End If
End If

Visual Studio 2012 Custom CompareTo Method slow when debugging

I have a DataTable that I'm sorting ascending by 3 columns. Tricky part is that the column can contain numeric and non-numeric values. Because of that, we see if we can cast this field, if so, we do numeric compare, otherwise we do a string compare.
This works very good in compiled version, but in Visual Studio 2012 this goes extremly slow ... Some how the comparing takes more then 5 minutes in debugging mode, in compiled mode it takes less than a second.
I deleted all breakpoints, but still only this part of my code goes to slow in debugging mode.
The comparing code:
Public Function CompareValues(ByVal sThis As String, ByVal sOther As String) As Integer
Dim bFirstNumeric As Boolean = IsNumeric(sThis)
Dim bOtherNumeric As Boolean = IsNumeric(sOther)
If bFirstNumeric AndAlso bOtherNumeric Then
Return Integer.Parse(sThis).CompareTo(Integer.Parse(sOther))
ElseIf bFirstNumeric And Not bOtherNumeric Then
Return -1
ElseIf Not bFirstNumeric And bOtherNumeric Then
Return 1
Else
Return sThis.CompareTo(sOther)
End If
End Function
I would do the IsNumeric check like this and then proceed, from here. It is cleaner.
Dim Value1 As Object
Dim Value2 As Object
Dim V1 As Integer
Dim V2 As Integer
Public Function IsNumeric(ByVal Expression As Object) As Boolean
If IsNumeric(Value1) = True And IsNumeric(Value2) = True Then
V1 = Integer.Parse(Value1)
V2 = Integer.Parse(Value2)
End If
Return True
End Function
Let me know, if you need more help.

Why can't I check if a 'DateTime' is 'Nothing'?

In VB.NET, is there a way to set a DateTime variable to "not set"? And why is it possible to set a DateTime to Nothing, but not possible to check if it is Nothing? For example:
Dim d As DateTime = Nothing
Dim boolNotSet As Boolean = d Is Nothing
The second statement throws this error:
'Is' operator does not accept operands of type 'Date'. Operands must be reference or
nullable types.
This is one of the biggest sources of confusion with VB.Net, IMO.
Nothing in VB.Net is the equivalent of default(T) in C#: the default value for the given type.
For value types, this is essentially the equivalent of 'zero': 0 for Integer, False for Boolean, DateTime.MinValue for DateTime, ...
For reference types, it is the null value (a reference that refers to, well, nothing).
The statement d Is Nothing is therefore equivalent to d Is DateTime.MinValue, which obviously does not compile.
Solutions: as others have said
Either use DateTime? (i.e. Nullable(Of DateTime)). This is my preferred solution.
Or use d = DateTime.MinValue or equivalently d = Nothing
In the context of the original code, you could use:
Dim d As DateTime? = Nothing
Dim boolNotSet As Boolean = Not d.HasValue
A more comprehensive explanation can be found on Anthony D. Green's blog
DateTime is a value type, which is why it can't be null. You can check for it to be equal to DateTime.MinValue, or you can use Nullable(Of DateTime) instead.
VB sometimes "helpfully" makes you think it's doing something it's not. When it lets you set a Date to Nothing, it's really setting it to some other value, maybe MinValue.
See this question for an extensive discussion of value types vs. reference types.
DateTime is a value type, which means it always has some value.
It's like an integer - it can be 0, or 1, or less than zero, but it can never be "nothing".
If you want a DateTime that can take the value Nothing, use a Nullable DateTime.
Some examples on working with nullable DateTime values.
(See Nullable Value Types (Visual Basic) for more.)
'
' An ordinary DateTime declaration. It is *not* nullable. Setting it to
' 'Nothing' actually results in a non-null value.
'
Dim d1 As DateTime = Nothing
Console.WriteLine(String.Format("d1 = [{0}]\n", d1))
' Output: d1 = [1/1/0001 12:00:00 AM]
' Console.WriteLine(String.Format("d1 is Nothing? [{0}]\n", (d1 Is Nothing)))
'
' Compilation error on above expression '(d1 Is Nothing)':
'
' 'Is' operator does not accept operands of type 'Date'.
' Operands must be reference or nullable types.
'
' Three different but equivalent ways to declare a DateTime
' nullable:
'
Dim d2? As DateTime = Nothing
Console.WriteLine(String.Format("d2 = [{0}][{1}]\n", d2, (d2 Is Nothing)))
' Output: d2 = [][True]
Dim d3 As DateTime? = Nothing
Console.WriteLine(String.Format("d3 = [{0}][{1}]\n", d3, (d3 Is Nothing)))
' Output: d3 = [][True]
Dim d4 As Nullable(Of DateTime) = Nothing
Console.WriteLine(String.Format("d4 = [{0}][{1}]\n", d4, (d4 Is Nothing)))
' Output: d4 = [][True]
Also, on how to check whether a variable is null (from Nothing (Visual Basic)):
When checking whether a reference (or nullable value type) variable is null, do not use = Nothing or <> Nothing. Always use Is Nothing or IsNot Nothing.
In any programming language, be careful when using Nulls. The example above shows another issue. If you use a type of Nullable, that means that the variables instantiated from that type can hold the value System.DBNull.Value; not that it has changed the interpretation of setting the value to default using "= Nothing" or that the Object of the value can now support a null reference. Just a warning... happy coding!
You could create a separate class containing a value type. An object created from such a class would be a reference type, which could be assigned Nothing. An example:
Public Class DateTimeNullable
Private _value As DateTime
'properties
Public Property Value() As DateTime
Get
Return _value
End Get
Set(ByVal value As DateTime)
_value = value
End Set
End Property
'constructors
Public Sub New()
Value = DateTime.MinValue
End Sub
Public Sub New(ByVal dt As DateTime)
Value = dt
End Sub
'overridables
Public Overrides Function ToString() As String
Return Value.ToString()
End Function
End Class
'in Main():
Dim dtn As DateTimeNullable = Nothing
Dim strTest1 As String = "Falied"
Dim strTest2 As String = "Failed"
If dtn Is Nothing Then strTest1 = "Succeeded"
dtn = New DateTimeNullable(DateTime.Now)
If dtn Is Nothing Then strTest2 = "Succeeded"
Console.WriteLine("test1: " & strTest1)
Console.WriteLine("test2: " & strTest2)
Console.WriteLine(".ToString() = " & dtn.ToString())
Console.WriteLine(".Value.ToString() = " & dtn.Value.ToString())
Console.ReadKey()
' Output:
'test1: Succeeded()
'test2: Failed()
'.ToString() = 4/10/2012 11:28:10 AM
'.Value.ToString() = 4/10/2012 11:28:10 AM
Then you could pick and choose overridables to make it do what you need. Lot of work - but if you really need it, you can do it.
You can also use below just simple to check:
If startDate <> Nothing Then
your logic
End If
It will check that the startDate variable of DateTime datatype is null or not.
You can check this like below :
if varDate = "#01/01/0001#" then
' blank date. do something.
else
' Date is not blank. Do some other thing
end if
A way around this would be to use Object datatype instead:
Private _myDate As Object
Private Property MyDate As Date
Get
If IsNothing(_myDate) Then Return Nothing
Return CDate(_myDate)
End Get
Set(value As Date)
If date = Nothing Then
_myDate = Nothing
Return
End If
_myDate = value
End Set
End Property
Then you can set the date to nothing like so:
MyDate = Nothing
Dim theDate As Date = MyDate
If theDate = Nothing Then
'date is nothing
End If