How to calculate time between dates on a report viewer expression - vb.net

I have a program that uses report viewers to show various types of data to the user, and I need one of them to (basically) calculate the days between two dates WITHOUT weekends (i.e: from Friday to Monday, should show 2 and not 4).
So far, I can calculate it but with the weekends.
If anyone knows how, I'll appreciate it.
Code sample:(the formula i use on one of my tables as a expression)
CInt(Avg(DateDiff(dateinterval.DayOfYear,
Fields!DataEntregue.Value,
Fields!DataPrevista.Value,
FirstDayofWeek.Monday)))

From this question, I have converted Alec Pojidaev's (not accepted) answer to VB. I also returned an integer instead of double:
Public Shared Function GetBusinessDays(startD As DateTime, endD As DateTime) As Integer
Dim calcBusinessDays As Double = 1 + ((endD - startD).TotalDays * 5 - (startD.DayOfWeek - endD.DayOfWeek) * 2) / 7
If CInt(endD.DayOfWeek) = 6 Then
calcBusinessDays -= 1
End If
If CInt(startD.DayOfWeek) = 0 Then
calcBusinessDays -= 1
End If
Return CInt(calcBusinessDays)
End Function
Usage:
GetBusinessDays(date1, date2)
BTW, in the future, what you were looking for was how to calculate number of business days between two dates in [enter language here]. A quick web search for this would have brought you to a number of answers.

Related

Ingres multiplication gives wrong result

I have an Ingres table with following columns
from_date ingresdate
to_date ingresdate
model_amt money
The dates can reflect a period of any number of days, and the model_amt is always a weekly figure. I need to work out the the total model_amt for the period
To do this I need to know how many days are covered by the period, and then divide model_amt by 7, and multiply it by the number of days
however, I am getting incorrect results using the code below
select model_amt, date_part('day',b.to_date - b.from_date),
model_amt / 7 * int4( (date_part('day',b.to_date - b.from_date)) )
from table
For example, where model_amt = 88.82 and the period is for 2 weeks, I get the following output
+-------------------------------------------------------+
¦model_amt ¦col2 ¦col3 ¦
+--------------------+-------------+--------------------¦
¦ #88.82¦ 14¦ #177.66¦
+-------------------------------------------------------+
But 88.82 / 7 * 14 = 177.64, not 177.66?
Any ideas what is going on? The same issue happens regardless of whether I include the int4 function around the date_part.
* Update 15:28 *
The solution was to add a float8 function around the model_amt
float8(model_amt)/ 7 * interval('days', to_date - from_date)
Thanks for the responses.
In computers, floating point numbers are notoriously inaccurate. You can multiply do all kinds of basic mathematics calculations on floating point numbers and they'll be off by a few decimals.
Some information can be found here; but its very googleable :). http://effbot.org/pyfaq/why-are-floating-point-calculations-so-inaccurate.htm
Generally to avoid inaccuracies, you need to use a language specific feature (e.g. BigDecimal in Java) to "perfectly" store the decimals. Alternatively, you can represent decimals as separate integers (e.g. main number is one integer and the decimal is another integer) and combine them later.
So, I suspect this is just ingres showing the normal floating point inaccuracies and that there are known workarounds for it in that database.
Update
Here's a support article from Actian specifically about ingres floating point issues which seems useful: https://communities.actian.com/s/article/Floating-Point-Numbers-Causes-of-Imprecision.

"Between" Statement in Left Join Returns null

OK, there's GOT to be an answer to this... likely a straightforward solution for one of the many experts here at Stack Overflow! :-)
Background:
I am trying to create a restaurant sales report by shift. I have 2 tables... one with RECEIPT details (restaurant, date, time, receipt#, amount, server, etc.) and another with SHIFT details (restaurant, shift start time, shift end time & shift name). There are Shift Numbers in both tables, but unfortunately the Shift Numbers in the Receipts table are not always accurate, so I am having to come up with a workaround based on which bucket of ShiftStart & ShiftEnd times the ReceiptTime falls into. This code for the join almost works:
LEFT OUTER JOIN: Receipts.Time BETWEEN ShiftDetails.ShiftStartTime AND ShiftsDetails.ShiftEndTime
BUT... my challenge is that the Dinner ShiftEndTime is currently 02:00, which (of course) is less than the Dinner ShiftStartTime of 17:31, so any ReceiptTimes "between" these hours returns a null value. I would also like to keep the query dynamic by avoiding "hard coding" the Start/End times, instead using those in the Shift table, as they are likely to be revised in the future.
FWIW, my data source is SQL Server with Power BI as a front-end, so alternatively I could scrap the SQL code and perform magic with PowerQuery or DAX...
Many thanks in advance!
Danny
Here is one way of handling this logic:
Receipts r LEFT OUTER JOIN
ShiftDetails sd
ON (sd.ShiftStartTime <= sd.ShiftEndTime AND r.Time BETWEEN sd.ShiftStartTime AND sd.ShiftEndTime) OR
(sd.ShiftStartTime > sd.ShiftEndTime AND r.Time BETWEEN sd.ShiftEndTime AND sd.ShiftStartTime)
You might decide that you really don't want BETWEEN. Receipts that are exactly on the boundary between shifts will return both of them -- because BETWEEN includes the end points of the range.
You are missing a function that says if the shift end time is less than 4:00 AM than return the DateTime for the next day's date.
So it would be used in a join like:
WHERE ShiftEndDateTime <= dbo.EndShiftDateTime(#ShiftDate, #ShiftEndTime)
This bumps it to the next day if the hour is less than 5:
CREATE FUNCTION dbo.EndShiftDateTime(#ShiftDate Date, #ShiftTime Time)
RETURNS DateTime
AS
BEGIN
IF(DATEPART(HOUR, #ShiftTime) < 5)
SET #ShiftDate = dateadd(day, 1, #ShiftDate)
RETURN cast(#ShiftDate as datetime) + cast(#ShiftTime as datetime)
END
I don't like hard coding an hour like this, but it is unlikely to ever change. You could make the logic to be more flexible (if endtime < starttime) but I've seen that that just leads to hard to find bugs.

VB.net how to subtract date with another date and get a whole number of days

i use MS Access for my database.
I have 2 columns holding 2 different dates
example
column 1 = 8/7/2016
column 2 = 8/11/2016
i want to subtract 8/11/2016 to 8/7/2016 and get a whole number.
in this example i should be getting 4. What i intend to do is to use the result to compute for something.
Date(Time)s can directly be substracted resulting in a TimeSpan object which has Days or TotalDays properties
Dim result = (#11/08/2016# - #07/08/2016#).Days
Have a look at DateDiff
Days = DateDiff("d", #07/08/2016#, #11/08/2016#)
or in an access sql query:
DateDiff('d', [DateCol1], [DateCol2])

Find the number of days passed since January 1 of a particular year in vba

I want to find the number of days passed since January 1 from a date I provide.
Example :
Input - 12/01/2015
Output - 12
Input - 02/02/2015
Output - 33
I need the shortest possible way to do this. Please tell me if there is any function available in vb for this.
This should do it: (input in cell C4 .. or replace C4 with your input)
=C4-DATE(YEAR(C4)-1,12,31)
(I looked at DAYS360() first, but that one isn't the same math OP needs, so not a good choice there)
and yeah, no vba needed .. I'd just stick with a normal formula if you can ;)
VBA can be a bit slower sometimes, and harder to maintain ...
DatePart("y", dt) is one way, and possibly the shortest, where dt is your date.
Alternatively, you can use =A1 - DATE(YEAR(A1), 1, 0) directly on a worksheet, where A1 holds a date.
In VBA, just subtract the dates:
intDays = dt1 - #1/1/2015# ' Date literals use #
Dates are stored internally in VBA as Double, with "days" as the integer portion and "time" as the decimal portion. You can always just subtract one from another to determine the difference in number of days.

sqlalchemy select by date column only x newset days

suppose I have a table MyTable with a column some_date (date type of course) and I want to select the newest 3 months data (or x days).
What is the best way to achieve this?
Please notice that the date should not be measured from today but rather from the date range in the table (which might be older then today)
I need to find the maximum date and compare it to each row - if the difference is less than x days, return it.
All of this should be done with sqlalchemy and without loading the entire table.
What is the best way of doing it? must I have a subquery to find the maximum date? How do I select last X days?
Any help is appreciated.
EDIT:
The following query works in Oracle but seems inefficient (is max calculated for each row?) and I don't think that it'll work for all dialects:
select * from my_table where (select max(some_date) from my_table) - some_date < 10
You can do this in a single query and without resorting to creating datediff.
Here is an example I used for getting everything in the past day:
one_day = timedelta(hours=24)
one_day_ago = datetime.now() - one_day
Message.query.filter(Message.created > one_day_ago).all()
You can adapt the timedelta to whatever time range you are interested in.
UPDATE
Upon re-reading your question it looks like I failed to take into account the fact that you want to compare two dates which are in the database rather than today's day. I'm pretty sure that this sort of behavior is going to be database specific. In Postgres, you can use straightforward arithmetic.
Operations with DATEs
1. The difference between two DATES is always an INTEGER, representing the number of DAYS difference
DATE '1999-12-30' - DATE '1999-12-11' = INTEGER 19
You may add or subtract an INTEGER to a DATE to produce another DATE
DATE '1999-12-11' + INTEGER 19 = DATE '1999-12-30'
You're probably using timestamps if you are storing dates in postgres. Doing math with timestamps produces an interval object. Sqlalachemy works with timedeltas as a representation of intervals. So you could do something like:
one_day = timedelta(hours=24)
Model.query.join(ModelB, Model.created - ModelB.created < interval)
I haven't tested this exactly, but I've done things like this and they have worked.
I ended up doing two selects - one to get the max date and another to get the data
using the datediff recipe from this thread I added a datediff function and using the query q = session.query(MyTable).filter(datediff(max_date, some_date) < 10)
I still don't think this is the best way, but untill someone proves me wrong, it will have to do...