Formatting an idiomatically pronounceable time string - vb.net

I have programmed a form in Visual Basic which displays the current system time (hh:mm:ss) in a label called "DigitalTime".
Now for the hard part: How do I program a second label ("WordTime") to use the current time (from "DigitalTime") and show it in the "WordTime" label in words like this:
Example 1: (time is 22:50) I want label "WordTime" to show "10 minutes to 11".
Example 2: (time is 13:15) I want label "WordTime" to show "15 minutes past 1".
For the minutes 0-30 I want it to display "... minutes past ...". For the minutes 31-59 I want it to display "... minutes to ...".

It turns out that it isn't that hard thanks to the wonderful ToString formatters available for DateTime in .NET and using String.Format. The DateTime structure in general has all you need to know on this stuff. One caveat and a gotcha, to subtract time from a current DateTime we Add negative amounts of time. There is no SubtractMinutes method on DateTime, only AddMinutes, so you add negative time.
With all that said something like this below. Ideally you'd just make it a function, but I left it fairly basic so it wouldn't get confusing.
10 minutes to 11:
Dim _textToMinute As String = String.Empty
If DateTime.Now().Minute > 30 Then
_TextToMinute = "Past"
Else
_textToMinute = "To"
End If
Dim _minutesTillNextHour = (DateTime.Now().AddHours(1).AddMinutes(-DateTime.Now().Minute) - dateTime.Now).Minutes
Dim _nextHour = DateTime.Now().AddHours(1).ToString("%h")
label1.Text = String.Format("{0} minutes {1} {2}", _minutesTillNextHour, _textToMinute, _nextHour)
15 minutes past 1
label1.Text = String.Format("{0} minutes {1} {2}", DateTime.Now().Minute, _textToMinute, DateTime.Now().ToString("%h"))

When the minutes is 30,it is common practice to use the word "half", as in "half past 6". Here's a simple little function that takes that into account and returns a formatted string that can be assigned wherever you need it:
Function TimeInCommonLang(ByVal input As DateTime) As String
Dim minutes As String = ""
Dim indicator As String = ""
If input.Minute <= 30 Then
indicator = "past"
If input.Minute = 30 Then
minutes = "half"
Else
minutes = input.Minute.ToString & " minutes"
End If
Else
indicator = "to"
minutes = (60 - input.Minute).ToString & " minutes"
input = input.AddHours(1)
End If
Return String.Format("{0} {1} {2}", minutes, indicator, input.ToString("%h"))
End Function

Related

How to convert song duration (String) to time where duration is more than 24 hours

The song duration which I'm reading from excel will exist in the range between "000:00:00" to "999:59:59".
When I try to parse the string to DataTime, if the hours are less than 24 it is working. But for hours greater than 23 it is throwing error like 'incorrect format'.
How can we parse the duration string to time, so that I can make sure the time is greater than 0 sec and less than 999 hours.
You can use TimeSpan as follows.
Split the string by the colon. Then create a new TimeSpan by converting each portion of the string to an Integer.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Dim spanString = "024:26:35" 'produces 1.00:26:35 or 1 day, no hours, 26 minutes, 35 seconds
Dim spanString = "999:59:59" 'produces 41.15:59:59 or 41 days, 15 hours, 59 minutes, 59 seconds
Dim splits = spanString.Split(":"c)
Dim ts As New TimeSpan(CInt(splits(0)), CInt(splits(1)), CInt(splits(2)))
Debug.Print(ts.ToString)
End Sub
Use TimeSpan instead of DateTime.
Note: The parsed string must conform to the expected format. This means that the hours component ("999" in the example) is invalid as it must not exceed 23 (or 24 is the subsequent components are all "0").
So "23:59:59" is valid but "24:00:01" is not. So we need to pre-parse the string to obtain a number of days (and remainder hours) if the TOTAL time component exceeds 24 hours.
Dim SongLengthString As String = "999:59:59"
Dim SongLengthArray As String() = SongLengthString.Split(":"c)
If CInt(SongLengthArray(0)) > 23 AndAlso (SongLengthArray(1) <> "00" OrElse SongLengthArray(2) <> "00") Then SongLengthString = String.Join(":", CInt(SongLengthArray(0)) \ 24, CInt(SongLengthArray(0)) Mod 24, SongLengthArray(1), SongLengthArray(2))
Dim SongLength As TimeSpan
If Not TimeSpan.TryParse(SongLengthString, SongLength) Then MessageBox.Show("Song Length is invalid.")
(I'm sure you can do better than my rubbish pre-parsing line!)
This yields the expected maximum SongLength of 41.15:59:59. (I think only Neil Young has songs longer than this!) You can then validate the result against your specification.

How to get the difference between 2 times in SSRS

I want to get the difference between 2 columns that have a time datatype in SSRS
FormatDateTime(dateadd(DateInterval.Minute, datediff(DateInterval.Minute, Fields!TimeFrom.Value, Fields!TimeTo.Value), 0) ,"hh:mm")
I tried this but it didn't work and is there a way to sum it up ?
You can use a custom code for it. You can refer this article for more detail about it.
Using custome code in SSRS
The following custom code will be help to handle your issue
Public Function GetFormatedTime(byval dblSeconds as double) as String
Dim result as String
Dim Hours, Minutes, Seconds As Integer
Seconds = dblSeconds
Hours = Seconds / 3600
Seconds = Seconds Mod 3600
Minutes = Seconds / 60
Seconds = Seconds Mod 60
result=Hours.ToString.PadLeft(2, "0"c) & ":" & Minutes.ToString.PadLeft(2, "0"c) & ":" & Seconds.ToString.PadLeft(2, "0"c)
return result
End Function
This function takes second as parameter. For example ;
code.GetFormatedTime(3699)
expresion returns
01:02:09

Looping (?) and setting values Access VBA

I am writing a medication administration app. The main table name is ResidentMedications. The second table name is Resident24HourTable. My main form is ResidentMedicationsExtended, with a subform Resident24HourPeriod. Resident24HourPeriod contains 24 check boxes, one for each hour in the day. (12A, 1A, 2A, 3A etc).
Within the ResidentMedicationsExtended form is a combo box [Frequency]. For simplicity sake, let's say "Q4H" is selected, for "4 times per day". Another field [First Dose] allows the user to enter the time the resident will receive their first daily dose. We'll say 6:00 AM.
I have a command button that I want to check the appropriate times in the subform based on the Frequency and First Dose fields. So far, I have written the following:
Private Sub Command90_Click()
If Me.FirstDose = "12:00:00 AM" Then
Forms!ResidentMedicationsExtended.Form.Resident24HourTable![12A] = True
ElseIf Me.FirstDose = "1:00:00 AM" Then
Forms!ResidentMedicationsExtended.Form.Resident24HourTable![1A] = True
ElseIf Me.FirstDose = "2:00:00 AM" Then
Forms!ResidentMedicationsExtended.Form.Resident24HourTable![2A] = True
ElseIf Me.FirstDose = "3:00:00 AM" Then
Forms!ResidentMedicationsExtended.Form.Resident24HourTable![3A] = True
and so on and so forth - many many lines. I know I can write separate lines for each time, write more to make checkboxes False, etc. Obviously, doing it this way will result in a zillion or so lines of code, and I have yet to calculate the rest of the days medication times.
Is there a Loop or something I can use instead? I've read loads of posts and haven't been able to come up with a solution.
I thank you in advance for your time!
4 times in a day means [once every 6 hours]. In your dropdown boxes, you should display the text description, but for the key, use values that make it easier to do the math. Use the period between occurrances, in terms of hours. Then it will be easier to use a loop to run through the occurrances (until you have covered a 24-hour period).
Another alternative would be to use date calculation functions like CDate(), DateAdd() and DatePart() to calculate time values.
So, for your example: 4 times a day. Your list value would be 6 (6 hour intervals)
Private Sub Command30_Click()
Dim totalHours as integer
Dim interval as integer
interval = *** the value from your interval dropdown, eg 6 (hours) ***
Dim nextDose as integer
nextDose = Me.FirstDose ' text was 12 am, but stored in 24 hour format as 0
While totalHours < 24
Forms!ResidentMedicationsExtended.Form.Resident24HourTable![nextDose] = True
nextDose = nextDose + interval
totalHours = totalHours + interval
Wend 'or End While
Use Hour() and TimeValue() to convert "1:00:00 AM" to 1, etc., then use this number to identify the Control:
Dim hrFirst As Integer
hrFirst = Hour(TimeValue(Me.FirstDose)) 'returns 0 for 12am, 1 for 1am
hrFirst = IIF(hrFirst = 0, 12, hrFirst)
Forms!ResidentMedicationsExtended.Form.Resident24HourTable.Controls(hrFirst & "A") = True

How can I check string in textbox as integer in Visual Basic?

I have 3 textboxes (day, month, year) and I want to check if input is e.g. day has to be from 1 to 31 and so on.
My code is:
If InputDan.Text < "1" Or InputDan > "31" Then Warning.Text = "Not a valid day input." Else Warning.Text = ""
Also I have day and month input limited to 2 characters and year to 4.
It works fine with numbers from 10 to 31 and it properly puts an warning message when input is 0 or 32 and on.
Here's the problem...
When I put in numbers from 4 to 9 it puts on a warning message, as I figured out later that program considers empty space after one character input as 0.
So if I enter 4 the program will read it as 40, and so on.
Can I solve this problem with converting String input as Int somehow?
You need to parse the numbers to integer before you can compare them, otherwise >"11" will compare them alphabetically and not by their numerical order.
Dim day As Integer
Dim valid As Boolean = Int32.TryParse(InputDan.Text, day)
Now you know if that input was a correct number and you could show a warning if it was not.
I would suggest a different approach to check whether or not the input was a correct day since you must take the number of days in that month into account(also leap years, different calendars etc). So use the current culture's calendar and look if the number of days is correct for the given month in this way:
Dim daysInMonth = CultureInfo.CurrentCulture.Calendar.GetDaysInMonth(year, month)
If day > daysInMonth OrElse day < 1 Then
' show warning '
End If
(assuming you have already checked the year and month part with Int32.TryParse)
Better than doing this from the code behind, asp.net has already validations here is an example of a textbox that represents the day, and it has to be between 1 and 31:
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<asp:RangeValidator ID="RangeValidator1" runat="server"
ErrorMessage="You have to insert a valid day" ControlToValidate="TextBox2" MaximumValue="31" MinimumValue="1"></asp:RangeValidator>
check it out
Your problem is, that "9" (the string) IS "larger" than "31". Because sorting is done on the first char, then the second and so on.
Dim Value As Integer
' is there an (integer) NUMBER in the textbox?
If Integer.TryParse(InputDan.Text, Value) Then
If Value > 0 AndAlso Value < 31 Then
' do something
Else
MessageBox.Show("please enter a number!")
End If
Else
MessageBox.Show("please enter a number!")
End If
With "TryParse" you can test if a String can be converted to an Integer (or Double, Single, whatever implements a TryParse method) and if it can be converted, the value is stored in the second parameter.
You should use Strict on" to avoid the coding problems - basically you are comparing strings against each other. They do NOT behave like Integers for comparisons.
Try like this: (Assuming framework above/or 3.5)
If Not IsNumeric(InputDan.Text) OrElse _
Not Enumerable.Range(1, 31).Contains(CInt(InputDan.Text)) Then
Warning.Text = "Not a valid day input."
Else
Warning.Text = ""
End If
It will first validate the input must be a number and then will validate if it lies within range of 1 and 31. I assume Days can not be 1.5 so I called CInt.
OrElse is what we call ShortCircuit. The second condition will not evaluate if the first one failed.

Excel: macro to auto-format time (without date)

I'm looking for a simple macro to specify cells as being of type "time" and typing only numbers (for example "955") will format that (and recognise as) "hh:mm" time. In other words, by typing "955", the cell would interpret to "09:55", whereas all I can have it do right now is interpret to "1902-08-12 00:00:00" (most likely 955 is the day number for 1902-08-12).
EDIT:
Part of the need for this is to allow calculation of times post typing (for example, substract two time values to get a timespan, or add several timespans to get a total).
VBA code:
Dim val As String
val = myCell.Value
Dim newval As String
If Len(val) = 2 Then
newval = "00:" & val
ElseIf Len(val) = 3 Then
newval = "0" & Left(val, 1) & ":" & Right(val, 2)
ElseIf Len(val) = 4 Then
newval = Left(val, 2) & ":" & Right(val, 2)
Else
newval = "Not a valid time"
End If
myCell.Value = newval
This code does not detect if the last two digits are a valid time (greater than 59 minutes), but otherwise it should handle most cases.
You'll also need to add a case if someone types in 1 digit, ie. 1 thru 9 minutes after midnight.
If you want it to be formatted as an actual time (date-time type), then change the formatting of the cell to hh:mm.
The value typed in, for example 955, must be manipulated to produce a fraction of a day.
pseudocode:
(left(myCell,len(myCell)-2) + (right(myCell,2)/60)) / 24
This produces the proper decimal value for how much of the day has elapsed and thus will display as a proper 'Time' in the cell with hh:mm formatting.
This isn't the VBA, but a formula that will change the formatting. You could incorporate this into VBA if you wanted to, but should help as a jumping point.
=TIMEVALUE(IF(LEN(A5)=3,"0"&LEFT(A5,1)&":",LEFT(A5,2)&":")&RIGHT(A5,2))
(If A5 is the cell where you enter 955)
(Also, make sure to format the formula cell as your desired time formatting.)
I can help with the code if needed. Just post back.
For some reason Excel does not allow to use ":" in your custom format.
But if you OK with another delimiter, say dash "-", then you can simply create a custom format like this: ##-##
Of course your time has to be in 24 hours format.
Alternatively, you may first enter all your times just like numbers (or better as text if you don't want to lose trailing zeros). And then run your script to insert semicolons between hours and minutes.