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
Related
I have 3 variables of type DateTime or string type, in the form hh:mm:ss.
For example:
dT1="00:00:00"
dT2="20:59:59"
dT3="18:04:21"
How can I perform the following comparison?
dT1<= dT3 <= dT2 ??
Your example show String not DateTime. I put your strings in and array called TimeStrings. Then I created a List of TimeSpan. Looping through the strings I split each string on the colon, then created a new TimeSpan and added it to the list. I used the .Max method of the list to get the highest value in the list.
Private Sub OpCode()
'Constructor TimeSpan(Int32, Int32, Int32)
Dim dT1 = "00:00:00"
Dim dT2 = "20:59:59"
Dim dT3 = "18:04:21"
Dim TimeStrings = {dT1, dT2, dT3}
Dim Spans As New List(Of TimeSpan)
For Each s In TimeStrings
Dim Splits = s.Split(":"c)
Dim span As New TimeSpan(CInt(Splits(0)), CInt(Splits(1)), CInt(Splits(2)))
Spans.Add(span)
Next
Dim HighestValue = Spans.Max
MessageBox.Show(HighestValue.ToString)
End Sub
You can use the TimeSpan.Parse(), ParseExact(), TryParse() or TryParseExact() to convert the string to a TimeSpan value. The comparison is straightforward after that:
Add your string values to a collection (an Array or List of strings).
Dim dTs As String() = {"00:00:00", "23:59:59", "20:59:59", "23:10:21", "18:04:21"}
Dim max As TimeSpan = dTs.Select(
Function(s) TimeSpan.ParseExact(s, "hh\:mm\:ss", CultureInfo.InvariantCulture)).Max()
max will be 23:59:59
Of course you can order the TimeSpan value, in ascending order here:
Dim orderedTimeSpans =
dTs.Select(Function(s) TimeSpan.ParseExact(s, "hh\:mm\:ss", CultureInfo.InvariantCulture)).
OrderBy(Function(ts) ts).ToList()
orderedTimeSpans.ForEach(Sub(ts) Console.WriteLine(ts))
Which prints:
00:00:00
18:04:21
20:59:59
23:10:21
23:59:59
With TryParseExact(), if you're not sure whether the format is may not be correct (possibly, because the source of the values is not reliable - User input, for example):
Dim parsed As TimeSpan
Dim max As TimeSpan =
dTs.Select(Function(s) TimeSpan.TryParseExact(s, "hh\:mm\:ss",
CultureInfo.InvariantCulture, parsed)).Max(Function(t) parsed)
This also returns 23:59:59.
If one of the values cannot be parsed, it won't be evaluated by the Max() method.
E.g., if this is the input string "23.59:59", InvariantCulture and the format specified won't allow to return a valid TimeSpan, so the max value will be 23:10:21 instead.
The same, using TryParseExact(), but in extended form (using a loop):
Dim maxValue As TimeSpan = New TimeSpan()
Dim parsed As TimeSpan = New TimeSpan()
For Each value As String In dTs
If TimeSpan.TryParseExact(value, "hh\:mm\:ss", CultureInfo.InvariantCulture, parsed) Then
maxValue = If(TimeSpan.Compare(maxValue, parsed) > 0, maxValue, parsed)
End If
Next
You can try something like this:
Dim dT1 As DateTime = New DateTime(2020, 1, 1, 0, 0, 0) ' 00:00:00
Dim dT2 As DateTime = New DateTime(2020, 1, 1, 20, 59, 59) ' 20:59:59
Dim dT3 As DateTime = New DateTime(2020, 1, 1, 18, 04, 21) ' 18:04:21
If dT1 <= dT3 <= dT2 Then
'your code
End If
Hope, it helps :)
I need to get a local timezone datetime from the following XML elements:
<TransactionDate>20191202</TransactionDate>
<TransactionTime>234026</TransactionTime>
<TransactionTimezone>UTC-06:00:00</TransactionTimezone>
My local UTC offset is -05:00:00. After getting TransactionDate and TransactionTime into td and tt Date variables, I can build a Datetime like this:
Dim ldDate As New Date(td.Year, td.Month, td.Day, tt.Hour, tt.Minute, tt.Second)
I could parse out the '-06' from TransactionTimeZone and determine that I need to add 1 hour to ldDate, but there must be a more elegant way. Any ideas?
I wrote a small procedure that returns a DateTime in the local TimeZone from a DateTime in an originating TimeZone:
Public Function P_ConvertToLocalDatetime(ByVal aOriginDateTime As Date,
ByVal aOriginTimeZone As String,
ByRef aLocalDateTime As Date) As Boolean
Try
Dim liHour As Integer = CInt(Strings.Mid(aOriginTimeZone, 4, 3))
Dim liMinute As Integer = CInt(Strings.Mid(aOriginTimeZone, 8, 2))
Dim liSecond As Integer = CInt(Strings.Right(aOriginTimeZone, 2))
With aOriginDateTime
Dim offset As New DateTimeOffset(.Year, .Month, .Day, .Hour, .Minute, .Second, New TimeSpan(liHour, liMinute, liSecond))
aLocalDateTime = offset.LocalDateTime
End With
Return True
Catch ex As Exception
Return False
End Try
End Function
I'm calling it with this:
Dim lLocalDateTime as Date
If Not P_ConvertToLocalDatetime(aTransactionDatetime,
aTransactionTimezone,
aLocalDateTime) Then
Throw New Exception("Unable to convert TransactionDatetime to local time")
End If
... where aTransactionTimezone is of type String with a value like "UTC-6:00:00".
If you have transactions from all the world this might help you to use as a base and working on to improve.
Private Function FromWorldTimeToMyLocalTime(noSpacesDateTimeTransaction As String, transactionZoneString As String) As Date
Dim transactionDtTime As Date = Date.ParseExact(noSpacesDateTimeTransaction, "yyyyMMddHHmmss", Globalization.CultureInfo.InvariantCulture)
Return DateAndTime.DateAdd(DateInterval.Hour, TimeZoneInfo.FindSystemTimeZoneById(transactionZoneString).BaseUtcOffset.TotalHours, transactionDtTime)
End Function
Usage (Here the example shows a transaction is done by Hawai):
‘Here is your complete string as you have in your xml tags (date + time) it’s presumed the transaction is come by Hawai
Dim myDateTimeFromTransactionTime As String = FromWorldTimeToMyLocalTime("20191202234026", "Hawaiian Standard Time").ToString
Console.WriteLine("MyTime from transaction is " & myDateTimeFromTransactionTime)
To get all timezone infos you can use this to have an idea.
Dim timeZones As ReadOnlyCollection(Of TimeZoneInfo) = TimeZoneInfo.GetSystemTimeZones()
For Each timeZoneInfo As TimeZoneInfo In timeZones
Console.WriteLine(CStr(timeZoneInfo.Id) & " " & CStr(timeZoneInfo.BaseUtcOffset.TotalHours))
Next
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 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.
I'm trying to list all the mondays and their dates in, let's say, 2014. I don't know what's wrong with my code below (probably the loop). When I execute these, the program crashes.
Dim d1 As DateTime = #1/1/2014#
Dim d2 As DateTime = d1.AddDays(-(d1.DayOfWeek - DayOfWeek.Monday))
Do
ListBox1.Items.Add(d2.ToString("MMM - dd - yyyy ddd"))
d2.AddDays(7)
Loop While (d2.Year < 2015)
A DateTime instance is immutable, meaning that it cannot be changed. The d2.AddDays(7) expression creates a new instance with a different value, which you can assign back to d2:
d2 = d2.AddDays(7)
So why does your program crash? Since the date never changes, it will never hit 2015, and your program will try to add infinitely many items to the listbox. Obviously you will run out of memory before that happens, which makes the program crash.
You need to reassign the value from the AddDays to the variable used to test the exist condition
d2 = d2.AddDays(7)
Without this, the loop never ends because the exit condition is never met.
Looking at the MSDN documentation
Returns a new DateTime that adds the specified number of days to the
value of this instance
By the way, your code lists also a date for 2013, I suggest to start with the initial value set to
Dim d1 As DateTime = #1/7/2014#
Here's a method that might work for you:
Private Function GetAllWeekdays(inYear As Integer, dayOfWeek As System.DayOfWeek) As List(Of Date)
Dim currDate As New Date(inYear, 1, 1) 'start jan 1st
GetAllWeekdays = New List(Of Date)
For i = 1 To (New Date(inYear, 12, 31) - New Date(inYear, 1, 1)).Days
currDate = currDate.AddDays(1)
If (currDate.DayOfWeek = dayOfWeek) Then GetAllWeekdays.Add(currDate)
Next
End Function
It loops through all the days in the provided year and returns just the days with the System.DayOfWeek that you provide.
You can use it like this:
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.ListBox1.DataSource = GetAllWeekdays(2014, DayOfWeek.Monday)
End Sub
How about using a iterator block?
Private Iterator Function DateSequence( _
start As DateTime, _
step As TimeSpan) As IEnumerable(Of DateTime)
While True
start = start.Add(step)
Yield start
End While
End Function
Which allows you to do some linq,
Dim firstDay = 'excercise for reader
Dim step = TimeSpan.FromDays(7)
var days = DateSequence(firstDay, step).Take(53) _
.Where(Function(d) d.Year = firstDay.Year)