I have a database that collects user input on their time in/out. I am collecting this information like so:
user_id clock_in clock_out
612 1383710400 1383728400
612 1384315200 1384333200
508 1383710400 1383738400
While looping, I calculate the hours of each object like so:
$total=(($e->clock_out-$e->clock_in)/60/60);
Where I am stuck
I'm a bit stuck on how to group them into pay periods. I know that there are 26 pay periods in a year. I also know our starting pay period for this year was 01.13.14 - 01.26.14.
What I have tried:
I thought to try just gathering the week of the year date('W',$e->clock_in) while looping through the database results but I am not sure how to group them.
Question:
Is grouping/sorting possible while looping during a foreach? Do you suggest a different approach on grouping/sorting the data into pay periods?
Please let me know if more code is needed, etc. Thank you!
Assuming those are standard Unix timestamps, you can trivially extract/mangle dates any way you want. If your workweek corresponds to a standard calendar week, it's even easier:
SELECT user_id, clock_in-clock_out
FROM yourtable
GROUP BY WEEK(FROM_UNIXTIME(clock_in))
This will just group by single weeks, but this is just to give you a general idea.
MySQL has a very wide variety of date/time functions that can be used for this: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_week
Related
Hello to all the experts here.
I have a conceptual question that I can use some help with.
In our site, we allow users to join a group for a specific amount of time. So there is a group that has activities outlined as follows week0day1, week0day4, week1day2, week1day5, week2day3.
In these groups we allow users to join and leave as they would like so week0day1 is not necessarily the same for each user.
I have worked out which week a user is currently in by looking at the date that they joined the group and then doing some math from there, that's not my problem. My issue comes from how I translate which day of the week an activity on a day like week0day4 would fall out on.
I thought about using the day of the week the user joined the group as an offset but I am not sure if that is the correct way to deal with this as there might be issues when the offset creates a situation where the calculated day of the week is not actually a valid weekday.
Can anyone recommend a better solution?
Thanks!
Don't reinvent the wheel, this already exists in PHP
http://php.net/manual/en/book.datetime.php
Given a date you can work out the Day, Tuesday, Wednesday etc. Its always better to work in the standard date time classes.
I am building a Time Clock application with PHP and Laravel 4.
My boss requires that he is able to pull and build different reports based on the data I store in the database for a Time Card record.
Right now I store a DateTime for clock in and clock out as well as a Timestamp for both those times as well into the Database.
I need to be able to Query the database and build reports for different Pay Periods for a user.
So for example I will store in another Database Table, records that will be for a User ID and will have different Pay Periods. So a Start day may be the 1st of the month and end date the 15th and that is 1 pay period (roughly 2 weeks) I am not sure the best way to store these records really.
Another will be the 16th of the month to the end of the month. So the end date would be different depending on how many days are in a month
I am not sure about the best way to define these Pay periods for a user. I can't simply say 1-15 and then 16-30 since the 30 would be a different number for each month.
Would appreciate any insight into how this could be done?
So I can build reports for any Pay Periods since not every user gets paid every 2 weeks it needs to be flexible so that I can define it on a per user basis
This question is more about the Logic instead of actual code.
Welcome to the wonderful world of Time and Attendance. You are touching the tip of the iceberg. You may find that purchasing a pre-packaged product may be easier than writing your own.
That said, I can offer you the following general advice:
Be very careful of your data types and how they are used, both in PHP and in MySQL.
You need to make sure you understand local time vs UTC, time zones, and daylight saving time. In general, you don't want to store local time unless you also store its offset from UTC. Otherwise you will have ambiguity around daylight saving time changes. This is important even if you only have one time zone to deal with.
When it comes to Pay Periods, the common types are:
Weekly
Bi-Weekly
Semi-Monthly
Monthly
Every X days starting from Y
In some systems, each individual pay period can be adjusted +/- a number of days from it's normal date. When doing so, the bordering period must also be adjusted to compensate.
You should start with business logic that can calculate the start and end date for a pay period given any particular date and time. You can then expand that to easily get the prior or next pay period.
You can store each pay period into it's own table, but it's not necessarily required. That will depend on a lot of specifics about your system internals.
Because a pay period is defined by dates, you have the "Whose Day is it?" problem. It might be the day as defined by the company, or if employees are in different time zones, then it might be the "logical day". If you only have one time zone to deal with then, you are lucky in this regard.
When comparing against the pay period, use half-open intervals, [start, end). In other words:
periodStart <= punchTime < periodEnd
or likewise
periodStart <= punchTime && periodEnd > punchTime
The end of one period should be exactly the same as the start of the next. Don't try to define the end of the period at some silly value like 23:59:59.999...
As you can see, this is just the beginning. I hope this is useful to you. If you can narrow the focus of your question further, I'll be happy to help more. Otherwise, it's like asking for how to build an ERP system when you're not sure what structure to store inventory.
I think you are over thinking this. Let thte user define the start and end dates.
You will need the UserId, a timestamp (time in and time out) of the user and that should be about it.
I picture something like this:
UserId | DateIn | DateOut
On the page you could put put dropdowns (or if you want a nifty interface a datepicker that uses javascript) and allow the manager to pick a start and end date that he wants to choose.
So if he wants to see an employees time between Jan. 1 and Feb. 31 he can choose those as his start and end dates.
This will allow things to be very flexible, for example the manager can choose Feb 16 as start date and Feb 29 as end date. It makes sense to allow him to choose the data requirements so he can view whatever he wants.
EDIT:
An example from my comment below this post you could do something like:
$startDate = new DateTime();
$startDate->modify('first day of this month'); //or 16th for second part of bi-monthly
$startDate->format(#some date formatting as you need#);
$endDate = new DateTime();
$endDate->modify('last day of this month'); //or 15th for first part of bi-monthly
$endDate->format(#some date formatting as you need#);
If things are even less defined however you could always try doing special math. date('t') will give you the number of days in a month. I would refrain from using this unless your pay days are fixed such as paid every 6 days.
In general I would harness the power of the PHP DateTime class over using date() function. http://php.net/manual/en/class.datetime.php
I have a problem that I just cannot seem to get my head around, and hope someone can help give me some advice.
Ever since getting solar PV cells fitted on my house roof, I have been generating electricity and in accordance to some (rather generous) incentives to do this kind of thing, have been making money for every kWh of electricity I generate. Seeing this as being a bit of a database project, I set about writing some PHP/MySQL to track daily generation, and now have nearly a year's worth of daily kWh readings, which are nicely presented to me in graphical form, both in a month-by-month view, and as a yearly (grouped into months) graph.
I'm now wanting to expand the system to show revenue in monetary terms, rather than kWh of electricity. Currently, the figure is £0.454 per kWh, though this figure changes every year on the April 1st (it was £0.433 previously).
This is my current MySQL structure:
Table feedin:
year (year4) rate (float)
2010 0.433
2011 0.433
2012 0.454
Table generation:
day (DATE) reading (float)
2011-12-01 7.682
2011-12-02 5.747
2011-12-03 4.982
... ...
2012-08-13 8.022
2012-08-14 19.449
2012-08-15 5.484
My first attempt at this was all rather cumbersome with a very mixed mess of PHP and MySQL queries, with the bulk of the logic being done in PHP (my MySQL skills are "limited", at best). However, as time is going on, I see that it would be ideal if the whole thing were done in MySQL.
I've no real idea how to tackle this. My initial thoughts are that we need to select yearly chunks of data (well, date-ranges from April 1st in one year, to March 31st the next), and multiply it by the appropriate year rate. And that "appropriate year rate is the rate applicable at the start of that date range, ie, as of April 1st).
Ideally, I'd like the query to be able to cope with multiple yearly boundaries, so, for example, several years down the road, I'd like to be able to query the absolute total revenue produced to date. Ultimately, I would just like to pass the query the start and end dates, and it returns the correct figure.
Link the year of the generation date to the year of the feedin tariff
SELECT *, generation.reading*feedin.rate AS profit
FROM generation, feedin
WHERE YEAR(generation.day)=feedin.year
BUT as this must relate to year start of APRIL 1st
SELECT *, generation.reading*feedin.rate AS profit
FROM generation, feedin
WHERE YEAR(DATE_SUB(generation.day, INTERVAL 3 MONTH))=feedin.year
This will move the recorded dates back 3 months too, making them Jan-Dec instead of Apr-Mar wich will then match the feedin year
something along these lines:
select year, sum(reading) as total_generation, (total_generation*feedin.rate)
FROM feedin
LEFT JOIN generation on feedin.year = YEAR(generation.day)
GROUP BY year
Hope this does what you want (tested and working)
SELECT (a.rate*b.reading),a.year as amount from generation as b, feedin as a where Year(b.day)=a.year
I'm building a home rental system. The system stores profiles of homes and users can book homes for rent for periods as between one day to a year. I've got the booking part all set up except I am faced with a requirement from teh client to be able to set certain dates and date ranges as un bookable for homes.
A home can be available for a whole year for rent, or can be available for 6 months, or be unavailable on discreet days eg: Holidays and weekends for summer homes etc.
I'm perplexed as how would I be able to set up a database table to store this information considering that the information must be retrievable by a sql query. I mean consider the following situation, a home can be rented through out the year except on wednesdays, the 4th of July, 10 November to 25th December and 31st December.
How do I store this in a database and be able to run a query to check for a homes availability between set dates. I'm wokring in php MySql
There are two different concepts that you're describing: the "on Wednesdays" is not as much of a date range as it is a recurrence pattern. The same goes for "weekends".
You're probably looking at two different tables in addition to your property table that define these unavailable dates: one that represents specific date ranges and one that represents recurrence patterns.
Property
|
-------------- ---------------
| |
PropertyUnavailableRecurrence PropertyUnavailableRange
(Bear in mind that you might want to figure out shorter names)
PropertyUnavailableRecurrence would need to store the information necessary for turning "Wednesdays" and "weekends" into viable decision logic. I can't model this for you, since all of you've presented in this pattern are specific days of the week, but I'd imagine that you'd need to be able to account for "First of the month" or "Second Wednesday of the month", but I don't know. In any case, this is where you'd need to store that information.
PropertyUnavailableRange would just contain simple From and To dates that define the range. This part is pretty simple.
Of course, an alternative would be to take the recurrence patterns specified in the application and turn them into discreet PropertyUnavailableRange records, but you'd still need to set up a table to store these recurrences and associate the discreet records with a recurrence so that you could manage them.
One approach is to have a table, PropertyUnavailable, with the following structure:
create table PropertyUnavailable
(
property_id number not null,
when date not null
);
This table would have a row for each day that the property is not available because of a black out period (e.g., every Wednesday, Holiday, etc). I am ignoring how you will store the meta information of the pattern -- all this table wants are rows for each day where the property is not available because of a blackout period.
I assume you will also have a table for reservation days, PropertyReserved, with the same structure as above plus a foreign key to reservation_id (or something similar).
Now to see what day's are unavailable/reserved for a given date range, the sql would be something like this:
SELECT a.when, 'blackout'
FROM PropertyUnavailable a
WHERE a.when between <from_date> to <to_date>
UNION ALL (
SELECT b.when, 'reserved'
FROM PropertyReserved b
WHERE b.when between <from_date> to <to_date>
);
If nothing is returned with the query, then the property is available between the date range specified (from_date, to_date).
Did you consider simply booking those "unbookable" dates in the name of the system?
It appears that you are not clear about what is required to be stored in teh database; and what is required in code segments. Set the "unbookable" dates aside for a moment, assume you only have actual booked dates. Catcall has a point. What does your current code look like, when you search for available dates ?
SQL is quite capable of handling dates and performing date arithmetic. My NonSQL is not, you will have to store more in the databse than in real SQL. But you do not need to store rows per date. The Reservation table needs FromDate and ToDate only.
I'm creating a calendar that displays a timetable of events for a month. Each day has several parameters that determine if more events can be scheduled for this day (how many staff are available, how many times are available etc).
My database is set up using three tables:
Regular Schedule - this is used to create an array for each day of the week that outlines how many staff are available, what hours they are available etc
Schedule Variations - If there are variations for a date, this overrides the information from the regular schedule array.
Events - Existing events, referenced by the date.
At this stage, the code loops through the days in the month and checks two to three things for each day.
Are there any variations in the schedule (public holiday, shorter hours etc)?
What hours/number of staff are available for this day?
(If staff are available) How many events have already been scheduled for this day?
Step 1 and step 3 require a database query - assuming 30 days a month, that's 60 queries per page view.
I'm worried about how this could scale, for a few users I don't imagine that it would be much of a problem, but if 20 people try and load the page at the same time, then it jumps to 1200 queries...
Any ideas or suggestions on how to do this more efficiently would be greatly appreciated!
Thanks!
I can't think of a good reason you'd need to limit each query to one day. Surely you can just select all the values between a pair of dates.
Similarly, you could use a join to get the number of events scheduled events for a given day.
Then do the loop (for each day) on the array returned by the database query.
Create a table:
t_month (day INT)
INSERT
INTO t_month
VALUES
(1),
(2),
...
(31)
Then query:
SELECT *
FROM t_month, t_schedule
WHERE schedule_date = '2009-03-01' + INTERVAL t_month.day DAY
AND schedule_date < '2009-03-01' + INTERVAL 1 MONTH
AND ...
Instead of 30 queries you get just one with a JOIN.
Other RDBMS's allow you to generate rowsets on the fly, but MySQL doesn't.
You, though, can replace t_month with ugly
SELECT 1 AS month_day
UNION ALL
SELECT 2
UNION ALL
...
SELECT 31
I faced the same sort of issue with http://rosterus.com and we just load most of the data into arrays at the top of the page, and then query the array for the relevant data. Pages loaded 10x faster after that.
So run one or two wide queries that gather all the data you need, choose appropriate keys and store each result into an array. Then access the array instead of the database. PHP is very flexible with array indexing, you can using all sorts of things as keys... or several indexes.