VB .NET comparing strings - vb.net

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

Related

How to convert DateTime to 64 bit representation?

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.

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)

Conversion from string "M" to type 'Integer' is not valid

I am having an issues with conversion of values that I am trying to reference via a field that I want to format from an ERP System. I am unable to convert all of my values because they are being pulled out as strings, no matter if variables are set to integer or string. What am I doing that would cause this error, should variables be defined a different way?
Public Class Class1
Inherits erp.Rule
Public Overrides Function Execute() As erp.RuleResult
Dim Result As New RuleResult
Try
Dim date_recieved As Date
Dim month As String
Dim period As String
Dim Year1 As String
Dim Year As String
date_recieved = Data.Fields.GetFieldByAlias("date_received").FieldValue
month = Format(date_recieved, "M").ToString
Year = Data.Fields.GetFieldByAlias("yearAR").FieldValue
period = Data.Fields.GetFieldByAlias("periodAR").FieldValue
If period = month Then
If Year = Year1 Then
Exit Function
Else
MessageBox.Show("Date received does not match year", "Invalid Input")
End If
Else
MessageBox.Show("Date received does not match period", "Invalid Input")
End If
Catch ex As Exception
Result.Message = ex.Message
End Try
Result.Success = True
Return Result
End Function
Format does not accept a string parameter, by you passing "M" it is trying to convert the datatype you supply to the datatype the function accepts and since a string does not implicitly cast to an integer an error occurs
To format a Date type to various formats of string you just use your date variable and its subsequent .ToString() method with your formatting rules as an argument of .ToString()
Here is a link to the msdn explaining all the possible formatting options: https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

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

How can I convert two strings to DateTimes and compare them in VB.NET?

String comes back from the database with a format: '00/00/0000' I need to then compare it to a date that the user has entered in the same format. How do I make the conversion and compare the two dates?
Use the static ParseExact method on the DateTime structure to convert the string. You will also pass the format you want, either dd/MM/yyyy or MM/dd/yyyy depending on what format you want (the example of 00/00/0000 doesn't give any indication of what format applies for you).
You can use
Dim dateA = DateTime.ParseExact(firstDateString, #"dd\/MM\/yyyy", Null)
Dim dateB = DateTime.ParseExact(secondDateString, #"dd\/MM\/yyyy", Null)
Dim areEqual = (dateA = dateB);
Assuming that your date format is day/month/year.
If it's month/day/year just swap dd and MM
Try something like this:
String.Compare("00/00/0000", dateTime.ToString("MM/dd/yyyy"))
But perhaps a better approach would be to do this:
DateTime.Equals(yourDateTime, DateTime.Parse(databaseDateTime));
Try the following
Dim date1 = CDate(firstDateString)
Dim date2 = CDate(secondDateString)
Dim comp = date1 = date2
When you say compare, are you trying to analysis if the dates are the same (to the day) or within a period of a few days ? If to compare if the dates are the same then you can just compare the string or use the date.equals (as mentioned in posts before this one) , if you are trying to determine with a range you will have to use date compare
Dim lDate1 As String = "29/03/2009"
Dim lDate2 As String = "30/03/2009"
Dim lPeriod As Int16 = 7
If lDate1 = lDate2 Then
'** Dates the same
End If
If Date.Equals(Date.ParseExact(lDate1, "dd/MM/yyyy", Nothing), Date.ParseExact(lDate2, "dd/MM/yyyy", Nothing)) Then
'** The same
End If
If Date.Compare(Date.ParseExact(lDate1, "dd/MM/yyyy", Nothing), Date.ParseExact(lDate2, "dd/MM/yyyy", Nothing)) > (lPeriod * -1) And Date.Compare(Date.ParseExact(lDate1, "dd/MM/yyyy", Nothing), Date.ParseExact(lDate2, "dd/MM/yyyy", Nothing)) < lPeriod Then
'** Within the period
End If