I would like to convert a Unix time stamp to a VB.NET DateTime.
I have tried
Public Function UnixToDateTime(ByVal strUnixTime As String) As DateTime
Dim nTimestamp As Double = strUnixTime
Dim nDateTime As System.DateTime = New System.DateTime(1970, 1, 1, 0, 0, 0, 0)
nDateTime.AddSeconds(nTimestamp)
Return nDateTime
End Function
But when I feed it
strUnixTime = "1401093810"
I get the return value
nDateTime = #1/1/1970#
What am I doing wrong?
Thank you
This line of code
nDateTime.AddSeconds(nTimestamp)
does not modify nDateTime. It's like writing a + 3 on a line by it's own -- a won't be modified.
It does, however, return a new DateTime object that contains the incremented value. So, what you actually wanted to write is:
nDateTime = nDateTime.AddSeconds(nTimestamp)
PS: It appears that your code does not use Option Strict On. It is strongly recommended that you activate Option Strict and use explicit instead of implicit conversions.
Related
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.
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)
I've this simple function in VB.net
Private Function SBODateTime2DateTime2(SboTicks As Long) As DateTime
Dim str As String = Convert.ToString(SboTicks, 2)
str = str.Substring(0, str.Length - 8)
If str.Length = &H38 Then
str = str.Substring(1, &H37)
End If
Dim num As Long = Convert.ToInt64(str, 2)
Dim time As New DateTime(&H7B2, 1, 1, 0, 0, 0, DateTimeKind.Utc)
Return time.AddMilliseconds(CDbl(num) / 1000.0)
End Function
That takes a SAP tick number like 444447614733000184 and it returns the Datetime, in this example is 06/01/2025 00:31:35
The problem is that I don't know how to do the inverse of this procedure in VB.net mostly because there isn't a lot of documentation about SAP DateTime around.
Does anybody knows if it's possible to do the Datetime to SAP Datetime conversion?
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
For converting number of seconds to DateTime, in VB .NET, I use the following code:
Dim startDate As New DateTime(1970, 1, 1)
Dim targetDate As DateTime
Dim noOfSeconds As Integer = DataInSeconds
targetDate = startDate.AddSeconds(noOfSeconds)
where DataInSeconds is an Integer containing the number of seconds (starting from 1/1/1970)
This works good. But I don't know how make the inverse conversion. (from DateTime to number of seconds). Anyone can help me?
When you subtract DateTime instances from each other, you get a TimeSpan - you can use this to get the number of seconds:
Dim startDate As New DateTime(1970, 1, 1)
Dim noOfSeconds As Integer
noOfSeconds = (currentDate - startDate).TotalSeconds
1/1/1970 is the Unix epoch. Beware that it is a UTC date, you cannot ignore that in conversions. Thus:
Module DateConversion
Public ReadOnly Property Epoch() As DateTime
Get
Return New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
End Get
End Property
Public Function FromUnix(ByVal seconds As Integer, local As Boolean) As DateTime
Dim dt = Epoch.AddSeconds(seconds)
If local Then dt = dt.ToLocalTime
Return dt
End Function
Public Function ToUnix(ByVal dt As DateTime) As Integer
If dt.Kind = DateTimeKind.Local Then dt = dt.ToUniversalTime
Return CInt((dt - Epoch).TotalSeconds)
End Function
End Module
Watch out for ToUnix(), the DateTimeKind may be unspecified, as it was in your snippet. Consider using DateTimeOffset instead to make it unambiguous. And be sure to do something reasonable in 2038 when all of this comes tumbling down.
Label1.Text = New DateTime(1970, 1, 1, 0, 0, 0,
DateTimeKind.Utc).AddSeconds(CLng(TextBox1.Text) / 1000)
Make a textbox and a button and a label, put this code into the button and depending if you're using microseconds (keep the /1000) or seconds (delete the /1000) will show you the date/time etc.
Public Function Date2Unix(ByVal vDate As Date) As Long
Return (vDate - #1970/01/01#).TotalSeconds
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MsgBox(Date2Unix(Now()))
End Sub