Need help getting my points per hour function to work properly - vb.net

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).

Related

How to use substring() function to get middle string with relative index?

I want to extract characters from a string. However, the string doesn't have the same length every time.
Basically I get data from a database and I want extract the value I need in it. But I'm stuck on step where I have to extract the right value.
So first I get data like that :
infoDataset2 = accessRequet_odbc("select st_astext(st_snaptogrid(geom, 0.01)) from netgeo_point_tech", myConnection)
The result is something like : POINT(921021.98 6671778.45). What I need are the 2 figures, but their length is not fixed. I just want to remove POINT( and ).
Then I work on each line of the DataSet I get to cast each lines into a string with only the value needed.
For i = 0 To infoDataset2.Tables(0).Rows.Count - 1
geomPt = infoDataset2.Tables(0).Rows(i).ItemArray(0).Substring(geomPt = infoDataset2.Tables(0).Rows(i).ItemArray(0).Substring(1 + infoDataset2.Tables(0).Rows(i).ItemArray(0).LastIndexOf("(")))
Console.WriteLine(geomPt)
Next
This was my last try, where I was able to remove POINT( but I'm struggling with the length to cut ).
I want to learn from this, so, if possible, explain to me what I'm doing wrong here, or if my approach is lacking insight.
It will be horrible to debug that one long line. It makes no difference to the computer if you split it up into easy-readable parts. Here's some code to get the x- and y-coordinates from a string formatted as shown in the question:
Dim s = "POINT(921021.98 6671778.45)"
Dim b1 = s.IndexOf("("c) + 1
Dim b2 = s.IndexOf(")"c, b1) - 1
Dim parts = s.Substring(b1, b2 - b1 + 1).Split({" "c})
Dim x As Decimal = Decimal.Parse(parts(0))
Dim y As Decimal = Decimal.Parse(parts(1))
Another way of parsing the string is to use a regular expression, which can be more flexible. In this example, I used named capture groups to make it easy to see which parts are for the x and y:
Dim s = "POINT(921021.98 6671778.45)"
Dim x As Decimal
Dim y As Decimal
Dim re = New Regex("\((?<x>[0-9-.]+) (?<y>[0-9-.]+)\)")
Dim m = re.Match(s)
If m.Success Then
x = Decimal.Parse(m.Groups("x").Value)
y = Decimal.Parse(m.Groups("y").Value)
Else
' Could not parse point. Do something about it if required.
End If
Andrew Morton has given a nice answer, i upvoted that one, if you need an even easier way and that was still complicated use this
Dim s = "POINT(921021.98 6671778.45)"
Dim part1 As String = s.Remove(0, 6)
Dim part2 As String = part1.Substring(0, part1.Length - 1)
Dim split() As String = part2.Split(" ")
Dim x = split(0)
Dim y = split(1)
Here is an even probably easier to understand solution:
Dim s as String = "POINT(921021.98 6671778.45)"
Dim coordinate() as String = s.Replace("POINT(", "").Replace(")", "").Split(" ")
Enjoy!

Strange Date Parsing Results

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

Converting a string to a DateTime in VB.net

I am writing an application to take SNMP data from an APC UPS and I want to do something with that data.
A few of the bits of information that I'm getting come in this format:
0d 2h 5m 45s 0ms
I want to be able to do something if that value goes under 30 minutes (total time - including the days and hours).
If I can get that string to be converted into a DateTime, then I can perform calculations on it.
I guess I'm looking to add that string to Now()... that way I can query how far in the future it is.
I hope that makes sense?
In my head the code looks something like this:
Dim timeNow As DateTime = Now
Dim snmpRuntimeRemaining As DateTime = Now + snmpDataTime
Dim runtimeRemaining As TimeSpan = snmpRuntimeRemaining - timeNow
If runtimeRemaining.TotalMinutes >= 30 Then Do Something
To add to .Now():
var t = new TimeSpan(days, hours, minutes, seconds, milliseconds);
var d = DateTime.Now + t;
Days, hours etc. you can get using a named Regex groups:
var r = new Regex(#"(?<days>\d+)d (?<hours>\d+)h...");
var m = r.Match(input);
var days = m.Groups["days"].Value;
PS You don't need to actually add to .Now, you can just do:
var t1 = (as above)
var t2 = Timespan.FromMinutes(30);
if(t1 < t2) doSth(); // if timespan from string is less (shorter) than 30 minutes
Code is in C#, but I think you can adapt it easily :)
I went a slightly different route away from Regex, and it needs tidying up - but this here is how I did it:
Dim snmpTimeDate As String = "0d 2h 5m 45s 0ms"
Dim split() As String = snmpTimeDate.Split(" ")
Dim days As String = split(0).Replace("d", "")
Dim hours As String = split(1).Replace("h", "")
Dim minutes As String = split(2).Replace("m", "")
Dim seconds As String = split(3).Replace("s", "")
Dim miliseconds As String = split(4).Replace("ms", "")
Dim snmpToTimeSpan = New TimeSpan(days, hours, minutes, seconds, miliseconds)
Dim snmpDateTime = DateTime.Now + snmpToTimeSpan
Dim runtimeRemaining As TimeSpan = snmpDateTime - DateTime.Now
If runtimeRemaining.TotalMinutes >= 30 Then Do Something
Thanks to Gerino for his help!

Checking Row by Row in a report

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

VBA convert time

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?