I need to convert time from 14:54 to a double 14+54/60. And i do this with the following code:
Private Function Omzetten(ByVal time As String) As Double
Dim min As Integer, hours As Integer, datum As Date
datum = CDate(time)
min = DatePart("n", datum)
hours = DatePart("h", datum)
Omzetten = hours + min / 60
End Function
But when the time is 26:00 he only gives 2 because 26-24 is 2. So I thought to ad day = DatePart("d", datum), but then he always gives day = 30. Does anyone has a solution?
if its always in the format hours : mins then use the below:
Dim str As String
Dim strSplit() As String
Dim Val As Double
str = "26:00"
strSplit = Split(str, ":")
Val = CInt(strSplit(0)) + CInt(strSplit(1)) / 60
Try the following, I used VB.Net which from above looks like it must be compatible with the newer VBA variants:
Private Function Omzetten(ByVal time As String) As Double
Dim Hours As Integer = CInt(time.Substring(0, time.IndexOf(":")))
Dim Minutes As Integer = CInt(time.Substring(time.IndexOf(":") + 1))
Return Hours + Minutes / 60
End Function
Just as a note you might want to add some extra checks, the above code will for example fail on non-numeric input or if the time doesn't contain a colon. You might want something more like the following to cope with varying inputs:
Private Function Omzetten(ByVal time As String) As Double
Dim Hours As Integer = 0
Dim Minutes As Integer = 0
Dim HoursStr As String
If time.IndexOf(":") = -1 Then
HoursStr = time
Else
HoursStr = time.Substring(0, time.IndexOf(":"))
End If
If IsNumeric(HoursStr) Then
Hours = CInt(HoursStr)
End If
If time.IndexOf(":") >= 0 Then
Dim MinutesStr As String = time.Substring(time.IndexOf(":") + 1)
If IsNumeric(MinutesStr) Then
Minutes = CInt(MinutesStr)
End If
End If
Return Hours + Minutes / 60
End Function
I think you can achieve this with basic Excel formulas.
As times are stored as numbers if you divide any time by 1/24 (i.e. an hour) you'll get the answer as a double.
Note - if you want to use times over 24 hrs (e.g. 26:00) then set the cell custom format to [h]:mm:ss
Examples
A B
1 14:54 =A1/(1/24) // = 14.9
2 26:00 =A1/(1/24) // = 26.0
Does this help?
Related
I'm having difficulty getting my function to work right.
This function is supposed to estimate how many points per hour the user would get but instead it shows way too many numbers.
Dim now As DateTime = DateTime.Now
Private Function PointsPerHour(gainedpoints As String, totalpoints As String)
Dim firstvalue = gainedpoints
Dim secondvalue = firstvalue
Dim thirdvalue = totalpoints
Dim varJWG0 As String = "Points: "
Dim varJWG1 As String = thirdvalue
Dim varJWG2 As String = " Points Per Hour: "
Dim varJJM0 As Double = Double.Parse(thirdvalue.Replace(",", String.Empty)) - Double.Parse(secondvalue.Replace(",", String.Empty))
Dim timeSpan As TimeSpan = Now - DateTime.Now.ToLocalTime
Dim dbl_ As Double = varJJM0 / timeSpan.TotalHours * -1.0
Return (Convert.ToString(varJWG0 & varJWG1) & varJWG2) + dbl_.ToString("0.00")
End Function
Even if I do PointsPerHour(9, 91) it still outputs more than 1000.
What am I doing wrong?
So I am not entirely certain what it is that this method is trying to achieve in your current implementation.
Firstly the values firstValue and secondValue are the same, also firstValue does not seem to be used apart from assigning to secondValue, which just seems redundant to me.
The first problem I can see is that you have no time in this function. The timeSpan you are using to hold presumably the totalHours is not holding a useful value. you are subtracting Now from Now.ToLocalTime. You will either get 0 or your timezone offset from this equation.
Basically; assuming your 9, 91 example; you are getting ((91-9)/timeSpan) * -1).
If 9 is the points you are earning per hour, and 91 is total points, then 91/9 = hours. or if you give the hours 9 * hours = 91 (in this case 10.1).
I am trying to make a small helper app to assist in reading SCCM logs. Parsing the dates has been pretty straightforward until I get to the timezone offset. It is usually in the form of "+???". literal example: "11-01-2016 11:44:25.630+480"
DateTime.parse() handles this well most of the time. But occasionally I run into a time stamp that throws an exception. I cannot figure out why. This is where I need help. See example code below:
Dim dateA As DateTime = Nothing
Dim dateB As DateTime = Nothing
Dim dateStr_A As String = "11-07-2016 16:43:51.541+600"
Dim dateStr_B As String = "11-01-2016 11:44:25.630+480"
dateA = DateTime.Parse(dateStr_A)
dateB = DateTime.Parse(dateStr_B)
MsgBox(dateA.ToString & vbCrLf & dateB.ToString)
IF run it would seem dateStr_B is an invalid time stamp? Why is this? I've tried to figure out how to handle the +480 using the 'zzz' using .ParseExact() format as shown here Date Formatting MSDN
Am I missing something with the timezone offset? I've searched high and low but these SCCM logs seem to use a non standard way of representing the offset. Any insight would be greatly appreciated
The problem is that +480 is indeed an invalid offset. The format of the offset from UTC (as produced when using the "zzz" Custom Format Specifier) is hours and minutes. +600 is 6 hours and 0 minutes ahead of UTC, which is valid. +480 would be 4 hours and 80 minutes ahead of UTC, which is invalid as the number of minutes can't be more than 59.
If you have some external source of date and time strings that uses an offset that is simply a number of minutes (i.e. +600 means 10 hours and +480 means 8 hours), you will need to adjust the offset before using DateTime.Parse or DateTime.ParseExact.
[Edit]
The following function takes a timestamp with a positive or negative offset (of any number of digits) in minutes, and returns a DateTime. It throws an ArgumentException if the timestamp is not in a valid format.
Public Function DateTimeFromSCCM(ByVal ts As String) As DateTime
Dim pos As Integer = ts.LastIndexOfAny({"+"c, "-"c})
If pos < 0 Then Throw New ArgumentException("Timestamp must contain a timezone offset", "ts")
Dim offset As Integer
If Not Integer.TryParse(ts.Substring(pos + 1), offset) Then
Throw New ArgumentException("Timezone offset is not numeric", "ts")
End If
Dim hours As Integer = offset \ 60
Dim minutes As Integer = offset Mod 60
Dim timestamp As String = ts.Substring(0, pos + 1) & hours.ToString & minutes.ToString("00")
Dim result As DateTime
If Not DateTime.TryParse(timestamp, result) Then
Throw New ArgumentException("Invalid timestamp", "ts")
End If
Return result
End Function
Thank you for the insight. I had a feeling I would need to handle this manually. I just wanted to make sure I wasn't missing something simple in the process. My knowledge of the date and time formatting is a bit lacking.
As such, I have altered my code so that it handles the offset. Granted I will have to add some more input validation in the final product.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dateA As DateTime = Nothing
Dim dateB As DateTime = Nothing
Dim dateStr_A As String = correctOffset("11-07-2016 16:43:51.541+600")
Dim dateStr_B As String = correctOffset("11-07-2016 16:43:51.541+480")
dateA = DateTime.Parse(dateStr_A)
dateB = DateTime.Parse(dateStr_B)
MsgBox(dateA.ToString & vbCrLf & dateB.ToString)
End Sub
Public Function correctOffset(ByVal ts As String)
Dim offset As Integer = CInt(ts.Substring(ts.Length - 3))
Dim offHour As Integer = offset / 60
Dim offMin As Integer = offset - (offHour * 60)
Dim strhour As String = Nothing
Dim strmin As String = Nothing
If offHour <= 9 Then
strhour = "0" & CStr(offHour)
Else
strhour = CStr(offHour)
End If
If offMin <= 9 Then
strmin = "0" & CStr(offMin)
Else
strmin = CStr(offMin)
End If
Return ts.Substring(0, ts.Length - 3) & strhour & ":" & strmin
End Function
I am trying to subtract hours and minutes from a DateTime variable and I have found other posts that show that you should be able to use the .AddHours(-3) in order to achieve this but it is not working for me. I am grabbing the datetime from a DateTimePicker control in vb.net. say the time is 10:00 AM, I want to subtract 3 hours from this to make it 7:00 AM. My hours variable evaluates to -3 but even when I just literally put the number -3 inside the .AddHours it still does not subtract the time. Heres the code
Dim ApptTime As DateTime = Convert.ToDateTime(DateTimePicker2.Value)
Dim travelTime As String = Label60.Text
Dim newtime As Double
Dim split() As String = travelTime.Split(" ")
If split.Length = 2 Then
Dim Minutes As String = split(0).Replace("mins", "")
Else
Dim Hours As Double = split(0).Replace("Hours", "")
Dim Minutes As Double = split(2).Replace("mins", "")
Hours = -Hours
Minutes = -Minutes
ApptTime.AddHours(Hours)
ApptTime.AddMinutes(Minutes)
Label62.Text = (ApptTime.ToString)
It's simple error ...
Dim ApptTime As DateTime = Now
'ApptTime.Subtract(New TimeSpan(1, 60, 60)) 'won't work
ApptTime = ApptTime.Subtract(New TimeSpan(1, 60, 60)) '1h , 60m , 60s
Try this:
Dim NowMinusThreeHours = DateAdd(DateInterval.Hour, -3, Now)
With reference to this question,
Changing Row Colour according to condition
I got familiar with Conditional formatting. However I still face this problem.
I am using this code to convert time into Time in Minutes.
Dim TestString As String
TestString = Me.Duration
Dim TestArray() As String
TestArray = Split(TestString, ":")
Dim Hours As String
Dim Minutes As String
Dim Seconds As String
Dim HoursMinutes As Integer
Dim MinutesMinutes As Integer
Dim SecondsMinutes As Integer
Hours = TestArray(0)
Minutes = TestArray(1)
Seconds = TestArray(2)
HoursMinutes = CInt(TestArray(0)) * 60
MinutesMinutes = CInt(TestArray(1))
SecondsMinutes = CInt(TestArray(2)) / 60
Dim TimeInMinutes As Integer
TimeInMinutes = HoursMinutes + MinutesMinutes + SecondsMinutes
Me.Duration = TimeInMinutes
However, for some reason this is not working.
Have you any ideas how can I do this for seperate rows?
Thanks in advance
ADD:
I tried creating a field for Minutes, the problem is that they will get all the same number.
the below code has a String variable called dateTime which stores the current date and time in this format: 27/08/2013 10:55:52
The dateTime String is getting split into a Variant arr array
Split(dateTime, Chr(32))(1) returns the time 10:55:52 part of the dateTime variable
then Split(Split(dateTime, Chr(32))(1), ":") splits the time into 3 numbers using : (colon) as delimiter
So you end up with with arr holding # of hrs, # of minutes, # of seconds.
The CLng((arr(0) * 60) + arr(1) + (arr(2) / 60)) returns an Integer/Long representation of the calculated time value
Stick the below sub in a fresh module and run it
Sub Convert()
Dim dateTime As String
dateTime = now
Dim arr
arr = Split(Split(dateTime, Chr(32))(1), ":")
MsgBox "The time " & Split(dateTime, Chr(32))(1) & vbCrLf & _
" as Integer is equal to " & CLng((arr(0) * 60) + arr(1) + (arr(2) / 60))
End Sub
I have a situation where I want to add hours to a date and have the new date wrap around the work-day. I cobbled up a function to determine this new date, but want to make sure that I'm not forgetting anything.
The hours to be added is called "delay". It could easily be a parameter to the function instead.
Please post any suggestions. [VB.NET Warning]
Private Function GetDateRequired() As Date
''// A decimal representation of the current hour
Dim hours As Decimal = Decimal.Parse(Date.Now.Hour) + (Decimal.Parse(Date.Now.Minute) / 60.0)
Dim delay As Decimal = 3.0 ''// delay in hours
Dim endOfDay As Decimal = 12.0 + 5.0 ''// end of day, in hours
Dim startOfDay As Decimal = 8.0 ''// start of day, in hours
Dim newHour As Integer
Dim newMinute As Integer
Dim dateRequired As Date = Now
Dim delta As Decimal = hours + delay
''// Wrap around to the next day, if necessary
If delta > endOfDay Then
delta = delta - endOfDay
dateRequired = dateRequired.AddDays(1)
newHour = Integer.Parse(Decimal.Truncate(delta))
newMinute = Integer.Parse(Decimal.Truncate((delta - newHour) * 60))
newHour = startOfDay + newHour
Else
newHour = Integer.Parse(Decimal.Truncate(delta))
newMinute = Integer.Parse(Decimal.Truncate((delta - newHour) * 60))
End If
dateRequired = New Date(dateRequired.Year, dateRequired.Month, dateRequired.Day, newHour, newMinute, 0)
Return dateRequired
End Sub
Note: This will probably not work if delay is more than 9 hours long. It should never change from 3, through.
EDIT:
The goal is find the date and time that you get as a result of adding several hours to the current time. This is used to determine a default value for a due date of a submission. I want to add 3 hours to the current time to get the due date time. However, I don't want due dates that go beyond 5pm on the current day. So, I tried to have the hours split between (today, up to 5pm) and (tomorrow, from 8am on), such that adding 3 hours to 4pm would give you 19am, because 1 hour is added to the end of today and 2 hours are added to the beginning of tomorrow.
Okay, how about these? The difference between the approaches should speak for themselves.
Also, this is tested about as far as I can throw it. The warranty lasts until... now.
Hope it helps!
Module Module1
Public Function IsInBusinessHours(ByVal d As Date) As Boolean
Return Not (d.Hour < 8 OrElse d.Hour > 17 OrElse d.DayOfWeek = DayOfWeek.Saturday OrElse d.DayOfWeek = DayOfWeek.Sunday)
End Function
Public Function AddInBusinessHours(ByVal fromDate As Date, ByVal hours As Integer) As Date
Dim work As Date = fromDate.AddHours(hours)
While Not IsInBusinessHours(work)
work = work.AddHours(1)
End While
Return work
End Function
Public Function LoopInBusinessHours(ByVal fromDate As Date, ByVal hours As Integer) As Date
Dim work As Date = fromDate
While hours > 0
While hours > 0 AndAlso IsInBusinessHours(work)
work = work.AddHours(1)
hours -= 1
End While
While Not IsInBusinessHours(work)
work = work.AddHours(1)
End While
End While
Return work
End Function
Sub Main()
Dim test As Date = New Date(2008, 8, 8, 15, 0, 0)
Dim hours As Integer = 5
Console.WriteLine("Date: " + test.ToString() + ", " + hours.ToString())
Console.WriteLine("Just skipping: " + AddInBusinessHours(test, hours))
Console.WriteLine("Looping: " + LoopInBusinessHours(test, hours))
Console.ReadLine()
End Sub
End Module
You should probably write some automated tests for each condition you can think of, and then just start brainstorming more, writing the tests as you think of them. This way, you can see for sure it will work, and will continue to work if you make further changes. Look up Test Driven Development if you like the results.
I've worked with the following formula (pseudocode) with some success:
now <- number of minutes since the work day started
delay <- number of minutes in the delay
day <- length of a work day in minutes
x <- (now + delay) / day {integer division}
y <- (now + delay) % day {modulo remainder}
return startoftoday + x {in days} + y {in minutes}