function to calculate days of work - function

hello everyone i want to calculate the days of work between two dates without calculing sunday and saturday but i don't know how to do that !
this is the code that i used but it doesn't work
file.py
import datetime
import math
from datetime import date
from openerp.osv import osv, fields, orm
class obj_ghb(osv.osv):
_name = 'obj.ghb'
_description = 'objet ghb'
def get_total_days( self, cr, uid, ids,days_tota,arg, context = {}):
diff_day={}
for record in self.browse(cr, uid, ids, context=context):
s_date = datetime.datetime.strptime(record.datedebut, "%Y-%m-%d").date()
e_date =datetime.datetime.strptime(record.datefin, "%Y-%m-%d").date()
diff_day[record.id] =(e_date-s_date).days
return diff_day
_columns = {
'nomprojet': fields.char('Nom du projet'),
'responsable': fields.char('Responsable GHB'),
'client': fields.char('Client'),
'contactclient': fields.char('Contact du client'),
'datedebut': fields.date('Date de debut'),
'datefin': fields.date('Date de fin'),
'nombredejour': fields.function(get_total_days, type = "integer", method=True, store = True),
'obj_ghb_parent': fields.one2many('loyer', 'loyer_obj_ghb'),
'obj_ghb_id': fields.one2many('assurance', 'assurance_obj_ghb'),
'obj_ghb_parenttt': fields.one2many('salaire', 'salaire_obj_ghb'),
'obj_ghb_parentttt': fields.one2many('autres', 'autres_obj_ghb'),

I suppose your code is in python. I don't work with python, so I don't know if you have some code errors in your code, but at first sight what you do is wrong.
s_date = datetime.datetime.strptime(record.datedebut, "%Y-%m-%d").date()
e_date =datetime.datetime.strptime(record.datefin, "%Y-%m-%d").date()
diff_day[record.id] =(e_date-s_date).days
You wrote you don't want to count the weekend days also your diff of days is probably wrong.
Lets say you want to count days from monday to friday in January 2017.
Monday was 2.1. and Friday was 6.1. If you do your diff_day calculation
e_date - s_date = 6. - 2. = 4 which is obviously wrong, because its 5 days.
So your number of days count will be like e_date - s_date + 1.
Next you need to subtract number of saturdays and sundays in your time range + you will probably also want to exclude some public holidays etc or other non working days.
Look at answer for this question: Calculate the number of business days between two dates?
It should lead you to right way.

Related

Counting days in a product life excluding the summers

I am trying to write an ms access SQL query in order to calculate the number of days that have passed since a date in two year periods: "summer" (from 1/6 to 30/09) and non-summer (from 1/1 to 30/05 and from 1/10 to 31/12).
This date is the last "measure" of the product and it could be as old as two years.
Then I would like to know, as today, how many days of summer and vice-versa how many days of nonsummer has passed since the product has been measured.
ie. the date is 31/10/2017, I'd like two columns to show summer days passed (=30days*4months in 2018+ 28days in 2019 = 148days) and non-summer days passed ( 7months between Nov17 and may17+ 8 months from Ott18 to May 19 = 450days)
I have been trying using IIF cycles like that one:
(ANNI is a variable that means in which year we are 0=this year, 1 past year, etc)
days of non-summer
IIF(ANNI=0; "150"; IIF(ANNI=1;
IIF(G2.DATA_PRODUZ<#01/06/2018#;DateDiff("d",[G2]!
[DATA_PRODUZ],#01/06/2018#)+90+150;
IIF(G2.DATA_PRODUZ>#30/08/18#;DateDiff("d",[G2]!
[DATA_PRODUZ],#31/12/2018#)+150));"etc");)
But it won't work and it does it would only work this summer. I'd accept any ideas.
Perhaps not the most efficient method, but certainly the most readable might be to define a VBA function (in a public module) such as:
Function SummerDays(ByVal dateFrom As Date, ByVal dateTo As Date) As Long
While dateFrom < dateTo
If dateFrom >= DateSerial(Year(dateFrom), 6, 1) And dateFrom <= DateSerial(Year(dateFrom), 9, 30) Then
SummerDays = SummerDays + 1
End If
dateFrom = dateFrom + 1
Wend
End Function
And then call this from your query:
SummerDays(G2.DATA_PRODUZ, Date())
Then, for the non-summer days, you could either define another function with an inverse if statement, or subtract the number of summer days from the total number of days between the two dates, e.g.:
DateDiff("d",G2.DATA_PRODUZ, Date()) - SummerDays(G2.DATA_PRODUZ, Date())
To create a public module in which to define the above function:
Open the VBA IDE using Alt+F11
Insert a new public module by going to Insert > Module or Alt, I, M
Copy the above function definition into the Module, below the Option statements.
Save the Module with an appropriate name.

MySql string search as Date using LIKE

I am managing a system designed 10 years ago for booking lessons.
The data structure saves the startTime as a string in the format YYYYmmDDHHMM and same format as lesson endTime.
How can I run a query which can get me all the lessons booked at HHMM (0930 or 1630) in future only?
The lesson may be an hour long and booked from 09:00 to 10:00, so If I put the search time as 09:30 this lesson should be returned as well.
Thank you
You could use a combination of STR_TO_DATE and RIGHT:
SELECT ...
WHERE STR_TO_DATE(startTime, '%Y%m%d%H%i') > CURDATE() AND
(RIGHT(startTime, 4) = '0930' OR RIGHT(startTime, 4) = '1630')
Update
To look for lessons which may overlap the desired time (e.g. a lesson that goes from 9am to 10am) is a little more complicated. Basically we also need to get the time part of the value and check for it surrounding 9:30 or 16:30 e.g.
SELECT ...
WHERE STR_TO_DATE(startTime, '%Y%m%d%H%i') > CURDATE() AND
('09:30' BETWEEN TIME(STR_TO_DATE(startTime, '%Y%m%d%H%i')) AND TIME(STR_TO_DATE(endTime, '%Y%m%d%H%i')) OR
'16:30' BETWEEN TIME(STR_TO_DATE(startTime, '%Y%m%d%H%i')) AND TIME(STR_TO_DATE(endTime, '%Y%m%d%H%i')))

Time difference between dates, including business hour and excluding holidays

How can I calculate the time difference between two date, considering:
Only Monday to Friday
Time between 9am to 5:30pm;
Exclude Holidays.
Example:
d1 = 2012-10-05 17:00:00
d2 = 2012-14-09 12:00:00
Calculation Steps:
2012-10-05 = 00:30:00
2012-10-06 = 00:00:00
2012-10-07 = 00:00:00
2012-10-08 = 07:30:00
2012-10-09 = 04:00:00
ddiff(d2,d1) = 12:00:00
I know how to do it using only mon-fri, as described here. And I am talking about MySQL.
I've come up with a solution that's relatively straightforward for calculating the time difference for the full interim dates. However it's a bit messy to use mysql for calculating the time difference for the start & end dates. I have included them in my solution, but with a number of assumptions.
In any case, here's the sql
SET #startdate:='2012-12-24 17:00:00';
SET #enddate:='2013-01-02 12:00:00';
SELECT
TIME_TO_SEC(TIMEDIFF(CONCAT(DATE(#startdate),' 17:30:00'), #startdate))/3600 as startday_time,
TIME_TO_SEC(TIMEDIFF(#enddate, CONCAT(DATE(#enddate),' 9:00:00')))/3600 as endday_time,
SUM(daily_hours) as otherdays_time from
(
SELECT 7.5 as daily_hours, id, DATE_ADD(DATE(#startdate),INTERVAL id-1 DAY) as idate from numbers
) dates
LEFT JOIN holidays on DATE(dates.idate) = DATE(holidays.date)
WHERE
idate BETWEEN #startdate AND #enddate
AND holidays.date IS NULL
AND DAYOFWEEK(idate) <> 7 AND DAYOFWEEK(idate) <> 1;
sqlfiddle here:
http://sqlfiddle.com/#!2/ff3f3/1/2
To get the valid interim dates, we'll need two tables - a holidays table listing all the holiday dates and a numbers table that contains a series of integers which is very useful for joining against to get a sequential series of dates (with no gaps).
Note: In the sqlfiddle, I've populated the numbers table only up to 12 to cover the dates used in my example - it will probably need to be populated to a higher number depending on the range of dates you'll be working with.
For the start day time & end day time, I've made the following assumptions:
that start date & end date are both valid dates that should be counted towards the total time
that the time on the start date is between lunch and 17.30
that the time on the end date is between lunch and 17.30
if these assumptions are wrong, you're getting into serious conditional territory (with lots of ifs) and might be best doing this in the php (or whatever).
note: I've left the times (which are in hours) un-added for illustration purposes.

Get the last twelve months worth of data from a database

I'm trying to work with a database of unemployment figures from the department of labor statistics' data (available at ftp://ftp.bls.gov/pub/time.series/la/)
I need to get the last 12 months of data for any given state, which is trickier then just selecting all data from the last year as they don't always have the last few months of data in yet (right now, the last month's worth of data is November 2010).
I know which record is the newest, and the date fields I have in the database to work with are:
period_name (month name)
year
period (M01, M02, etc for January, February)
My current SQL, which pulls data from a bunch of JOINed tables, is:
USE unemploymentdata;
SELECT DISTINCT series.series_id, period_name, year, value, series.area_code,
footnote_codes, period_name, measure_text, area_text, area_type_text
FROM state_overview
LEFT JOIN series ON state_overview.series_id=series.series_id
LEFT JOIN footnote ON state_overview.footnote_codes = footnote.footnote_code
LEFT JOIN period ON state_overview.period = period.period
LEFT JOIN measure ON series.measure_code = measure.measure_code
LEFT JOIN area ON series.area_code=area.area_code
LEFT JOIN area_type ON area.area_type_code=area_type.area_type_code
WHERE area_text = 'State Name' AND year > 2009
ORDER BY state_overview.period, measure_text;
Any idea?
Since you have textual values to work with for month and year, you'll need to convert them to MySQL-formatted DATE values and can then let MySQL calculate the last year interval like so:
SELECT ... WHERE STR_TO_DATE(CONCAT(period_name,' 1 ',year),'%M %d %Y') >= DATE_SUB(STR_TO_DATE(CONCAT(most_recent_period_name,' 1 ',most_recent_year),'%M %d %Y'), INTERVAL 1 YEAR) ...;
The CONCAT() function is just building a string like "Month 1 YYYY", and the STR_TO_DATE() function is taking that string and a formatting string to tell it how to parse it, and converting it into a DATE.
Note: This query probably sucks index-wise but it should work. : )
I think a few changes to WHERE clause should do it, but for effeciency/simplcity you should also add MAX(year) to the SELECT section.
SELECT ...... MAX(year) as max_year .....
WHERE area_text = 'State Name'
AND year >= max_year - 1
AND period >= (SELECT MAX(period) WHERE year = max_year)
ORDER BY state_overview.period, measure_text;
You can store the year and month as a date, even though you don't have the day information. Just use the first of each month.
{2009, 'M1'} => 2009-01-01
{2009, 'M2'} => 2009-02-01
{2009, 'M3'} => 2009-03-01
This makes date arithmetic much easier than dealing with substrings of (potentially dirty) data. Plus (and this is big), you can index the data much more effective. As a bonus, you can now extract a lot of extra goodies using DATE_FORMAT such as month names, nr of days in month etc.
Does all states have data for all months, and is the data updated at the same time? The answer to that question dictates what query strategy you should use.
The best way is to take the strtotime ($a) of correct 1 year ago and then, when fetching the value from database then find the strtotime ($b) of the date in each result. Now
if($b < $a){
continue;
}
else {
//do something.
}

Need some groupby Linq2Sql help, please

I need to display a history all our Products we've sold by day, week, month and year. This data will be sent to google charts API to display a line graph of the results.
So if i have a table called Products and it looks like:-
Products
ProductID INT
DateCreated DATETIMEOFFSET
and the user asks to see the history for ProductID 1. How could i retrieve this?
eg output.
Graph 1 (Dates vs Sale Count)
Monday 1st Dec: 0
Tuesday 2nd Dec: 3
Wed 3rd Dec: 1
Graph 2 (Weeks vs Sale Count)
Week 49 2008: 21
Week 50 2008: 11
Week 51 2008: 45
Week 52 2008: 0
Graph3 (Months vs Sale Count)
Dec 08: 102
Jan 09: 23
I'm not sure if the 'by day' can be done ... or any of it.
cheers :)
Update 1 : got part of it working...
After spending a bit of time, i got the first one working... but still need help on the other two AND making it all part of one query...
from p in Products
where p.ProductId == 69
group p.DateCreated by p.DateCreated.Date into grouping
orderby grouping.Key
select new { Date = grouping.Key, Count = grouping.Count() }
var data = from p in ctx.Products
where p.ProductID == *productId*
group p by p.DateCreated.DayOfWeek into groupedProducts
select new { DayOfWeek = groupedProducts.Key, Count = groupedProcuts.Count() };
Without testing I think that may do it for you
To do it per-year something like this:
var data = from p in ctx.Products
where p.ProductID == *productId*
group p by n.CreateDate.Year into gn
select new {
Count = from a in gn
group a by a.CreateDate.DayOfYear into aa
select new { Count = aa.Count(), Key = new DateTime(gn.Key , 1, 1).AddDays(aa.Key) }
};
(Sorry about the variable names :P)
I don't know how to do it with a LINQ expression, but you could write a stored procedure using the PIVOT operator. See Using PIVOT and UNPIVOT.
Use DateTime.Date, DateTime.Month and DateTime.Year. However there is a bug in LINQ-to-SQL that sometimes translates those to invalid SQL. As a workaround you can group by SqlMethods.DateDiffDay, SqlMethods.DateDiffMonth and SqlMethods.DateDiffYear from say '1980-01-01'.
The week part is not so easy. Start of the week depends on Sql Server settings so it's not reliable. Alternatively you can use SqlMethods.DateDiffDay from some date that starts the week in your case and divide day difference by 7. If you need the week number in a given year you should calculate day difference from the most recent week start day that is less or equal to start of the year.