I have the following sub in Access 2003 to return the hours elapsed bewteen two datetime fields.
Function DateDifferenceHour(dateStart As Date, dateEnd As Date) As String
'Outputs Hours from two dates
Dim age_hour As Double
age_hour = DateDiff("h", dateStart, dateEnd)
DateDifferenceHour = age_hour
End Function
If I have the following: DateDifferenceHour("07/23/2005","07/23/2005 7:30:00 PM").
It correctly returns 19 hours, but in reality, the time elapsed is 19 hours and 30 minutes.
How can I modify it so it can round off to 20 hours?
Edit:
My original suggestion was "Compute the difference in minutes, divide by 60, and round the quotient to zero decimal places". However, #Jean-François Corbett showed me the limitation of that approach.
? DateDifferenceHour("07/23/2005 7:00:59 PM","07/23/2005 7:30:00 PM")
1
IOW my first attempt rounded a duration of 29 minutes and 1 second up to 1 hour, which is no good. So instead I suggest using the difference in seconds and dividing by 3600.
Function DateDifferenceHour2(dateStart As Date, dateEnd As Date) As String
'Outputs Hours from two dates
DateDifferenceHour2 = _
Format(DateDiff("s", dateStart, dateEnd) / 3600, "0")
End Function
? DateDifferenceHour2("07/23/2005 7:00:59 PM","07/23/2005 7:30:00 PM")
0
There is still the issue of which rounding approach you want.
I chose Format() thinking you would want 2.5 hours rounded up to 3.
The VBA Round() function uses round-to-even, so Round(2.5, 0) would give you 2.
We don't know which you want; you can tell us. Also, dateStart and dateEnd imply dateStart will not be greater than dateEnd. However, if it can be, consider how you want a negative duration "rounded" to the nearest hour. Here are some examples copied from the Immediate Window.
? Round(-2.5, 0)
-2
? Round(-1.5, 0)
-2
? Format(-2.5, "0")
-3
? Format(-1.5, "0")
-2
This works, without any unexpected rounding (aside from the precision of the Date type itself).
Function DateDifferenceHour(dateStart As Date, dateEnd As Date) As String
' Rounds .5's to nearest even integer.
'DateDifferenceHour = CStr( Round( _
' CDbl(dateEnd - dateStart) * 24 ) )
' Rounds .5's up.
DateDifferenceHour = Format( _
CDbl(dateEnd - dateStart) * 24, "0" )
End Function
I put two rounding options so that it rounds to whole numbers; pick your favourite. It's way better programming practice to round explicitly and transparently than having DateDiff implicitly apply its unusual rounding.
Related
I am wondering if it is possible to control the time entered into MS Access textbox. Eg, only allow user to enter time in half hourly interval (08:30, 10:00, 13:30) as I do not want to end up with weird timing input.. (i.e 13:37, 16:42). Tried to use calculated control but doesn't seem to be working very well. Any suggestions or advice, please?
Calculated control in my textbox
=IIf((Minute([TxtStartTime1]) Mod 30=0),[TxtStartTime1],"00:00")
Below is a screen capture of my form.
Yes, that is possible, but it takes a little - actually that much, that I wrote an article on how-to:
Entering 24-hour time with input mask and full validation in Microsoft Access
It includes all the code needed to set the inputmask, validation, click and keypress events, as well as handling the form error - too much to post here.
Code is also on GitHub: VBA.TimeEntry
To round the time, you may include this function:
Public Function RoundTime( _
ByVal datDate As Date) _
As Date
Const cintMult As Integer = 24 '1 hour round
' Const cintMult As Integer = 48 '30 minute round
' Const cintMult As Integer = 96 '15 minute round
' Const cintMult As Integer = 144 '10 minute round
' Const cintMult As Integer = 288 '5 minute round
RoundTime = CVDate(Int(datDate * cintMult + 0.5) / cintMult)
End Function
You can round entered time for instance in BeforeUpdate event of your control. For rounding I use this VBA function:
Public Function TimeRoundMinutes(dtUnrounded As Date, Optional intRoundTo As Integer = 30, Optional intOption As Integer) As Date
'rounds time of provided date to specified in intRoundTo number of minutes. intOption:
'1 - down
'2 - up
'0 or anything else - to the nearest part
Dim intMins As Integer
If intRoundTo <= 0 Then
intRoundTo = 1
ElseIf intRoundTo > 60 Then
intRoundTo = 60
End If
intMins = Minute(dtUnrounded)
Select Case intOption
Case 1
intMins = Int(intMins / intRoundTo) * intRoundTo
Case 2
intMins = -Int(-intMins / intRoundTo) * intRoundTo
Case Else
intMins = Round(intMins / intRoundTo) * intRoundTo
End Select
If intMins = 60 Then
TimeRoundMinutes = DateAdd("h", 1, Int(dtUnrounded) + TimeSerial(Hour(dtUnrounded), 0, 0))
Else
TimeRoundMinutes = Int(dtUnrounded) + TimeSerial(Hour(dtUnrounded), intMins, 0)
End If
End Function
I'm looking to calculate the start date of the last quarter based on the current date.
Where
Q1 = Jan-Mar
Q2 = Apr-Jun
Q3 = Jul-Sep
Q4 = Oct-Dec
Hence, if the current date is 8th Jan 2018, the function would return the date 1st Oct 2017.
I have written the following code, however, this seems clunky and inelegant, and I have a feeling that there may be a better way to write it (for example, using dateadd).
Function LMLastQuarterStart() As Date
Dim mo As Integer
Dim yr As Integer: yr = Year(Date)
Select Case Month(Date)
Case 1 To 3: mo = 10: yr = yr - 1
Case 4 To 6: mo = 1
Case 7 To 9: mo = 4
Case Else: mo = 7
End Select
LMLastQuarterStart = DateSerial(yr, mo, 1)
End Function
I would appreciate any advice/suggestions offered, thanks.
The function you're looking for, with the DateAdd, is the following:
Public Function LastQuarter(theDate As Date) As Date
LastQuarter = DateAdd("q", DatePart("q", theDate) - 2, DateSerial(Year(theDate), 1, 1))
End Function
Explanation:
DateSerial(Year(theDate), 1, 1)) returns the first quarter of the current year.
DateAdd("q", DatePart("q", theDate), ThatDate) adds the current quarter, returning the next quarter (e.g. quarter 1 -> quarter 2). So the -2 substracts two quarters.
About clunkyness: this function may be shorter and possibly include less operations, but it's harder to understand. That may or may not be relevant.
And about parameters: I have made it take a date, to both make it easy to test and to let you keep it variable. You can do with that what you will.
Thanks to Gustav for making the suggestion to use DatePart instead of Format
I need to generate the time difference between tow dates in SSRS in HH:MM format. How can i achieve this? My data source is MS CRM FetchXML.
Eg : Date1 : 01/01/2016 04:05 AM
Date2 : 01/03/2016 02:15 PM
Time Differece Should be : 58:10
Regards,
Sandeep
I might be a little too late but was needing to calculate the elapsed time between two times. Hence I stumbled up this link
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/26d8b4fc-6862-42a0-ac7f-0caa93ba2fde/to-find-ellapse-time-in-ssrs-2008?forum=sqlreportingservices
The below expression worked for me. I also found it is simpler to do it in SSRS than SQL.
=Datediff("h",Fields!StartDate.value,Fields!EndDate.value) & ":" & Datediff("n",Fields!StartDate.value,Fields!EndDate.value) mod 60 & ":" & Datediff("s",Fields!StartDate.value,Fields!EndDate.value) mod 60
The result of the above will be HH:MM:SS
Try this:
=DateDiff(
DateInterval.Hour,CDATE("01/01/2016 04:05 AM"), CDATE("03/01/2016 02:15 PM")
) & ":" &
DateDiff(
DateInterval.Minute,CDATE("01/01/2016 04:05 AM"), CDATE("03/01/2016 02:15 PM")
) Mod 60
It will produce 58:10
Replace CDATE() by the field or parameter containing your date time value.
Let me know if this helps.
Write a custom code to calculate time difference between two dates and return a string as expecting HH:MM like
Public Function GetTimeDifference(ByVal dt1 AS DATETIME,ByVal dt2 AS DATETIME) AS String
Dim Mn AS Integer=DateDiff("n",dt1,dt2)
Dim HH AS Integer=Mn /60
Dim MM AS Integer=Mn Mod 60
Return HH.ToString() & ":" & MM.ToString()
End Function
Now call this function as an expression like
=Code.GetTimeDifference(Parameters!startDate.Value,Parameters!endDate.Value)
I am creating one SSRS report in which I have one Tablix the data of that Tablix shown as below,
One Parameter --> Balance = 100
firstamt SecondAmt ThirdAmt RunningTotal
10 15 20 145
02 05 01 153
-30 -20 -03 100
So basically my RunningTotal fields value should be
RunningTotal = Balance + firstAmt+SecondAmt+thirdAmt and then update
Balance = Balance + firstAmt+SecondAmt+thirdAmt (Or RunningTotal)
and for then next row should use Balance= RunningTotal then calculate the next row runningtotal and so on. I tried using custom code, RunningValue but still got no luck.
Any help would be great, Thanks. And also my reporting server is 2008.
(In case of confusion feel free to comment.)
I tried following Custom code but it doesn't work
public dim finalRunningTotal as decimal = 0
public function CalculateRunningTotal (totalAmount as decimal, CheckAmount as decimal,pstAmount as decimal) as decimal
dim valueToReturn as decimal = finalRunningTotal + totalAmount + CheckAmount +pstAmount
finalRunningTotal = valueToReturn
return valueToReturn
end function
Here's one of doing it - use an expression like:
=RunningValue(Fields!FirstAmt.Value + Fields!SecondAmt.Value + Fields!ThirdAmt.Value
, Sum
, Nothing)
+ Parameters!Balance.Value
You may have to change Nothing to a different Scope depending on how your table is set up.
Works for me in a simple example:
Here the example is as above.
To simplify this you could add a Calculated Field to the Dataset like:
=Fields!FirstAmt.Value + Fields!SecondAmt.Value + Fields!ThirdAmt.Value
Which makes the RunningValue expression simpler:
=RunningValue(Fields!MyCalculatedField.Value
, Sum
, Nothing)
+ Parameters!Balance.Value
I would like to convert minutes into hours and minutes with classic asp
Example:
90
would
1 hour and 30 minutes
How would I do this in classic ASP
Thanks!
Like this?
function toHourMin(minutes)
hours = minutes \ 60
minutes = minutes mod 60
toHourMin = hours & iif(hours=1," hour"," hours") & " and " & minutes & iif(minutes=1," minute"," minutes")
end function
function iif(condition, truepart, falsepart)
if condition then
iif = truepart
else
iif = falsepart
end if
end function
Note that this will return output like:
0 hours and 0 minutes
If that isn't desired behaviour, you should state what should happen when you pass in differing (smaller) amounts of time.
Passing in 90 will return what you asked for:
1 hour and 30 minutes