i'm pretty new to programming and can't seem to figure out my mistake here.
I have a calendar setup, every time a user changes a day I make a new row. This way all changes are logged (again new, id imagine there is a better way.) each row has some displayed information but its primary differentiated by a month a day and a year. IE 1 31 2013 .
I need to get the most recent unique row for each day of the month. So if I run a query for 1/31/2013, I need to return only the most recently created row WHERE month= '1' AND etc.
I'm using..
SELECT t.* FROM(SELECT * FROM calendar a
WHERE NOT EXISTS(SELECT * FROM calendar b
WHERE b.day = a.day AND b.lastaltered > a.lastaltered)) t
WHERE t.month = '12' AND t.year = '2013'
From PHP, if that matters.
Now it works fine if a user makes changes slowly. But I found if someone is quick with it like entering multiple days which end up having a very close time stamp ("lastaltered") it doesn't return that row with my current query. I tested this by modifying the time stamp to a later date and it then returned normally. I hope that explains my problem well enough. I'm still not clear as to why altering the time stamp caused the row to return.
Thank you for your time!
- Jer
Ah ... managing time in a database that doesn't understand what time is (and none of them do).
Go here, read the first book - it explains the intricacies of time and the difficulties of using one data type (DateTime) to represent different concepts:
A fixed instant: 10:15am 4 December 2013 UTC
A recurring instant: 10:15am every day, every Tuesday or the last Monday of a month
An instant defined from an anchor: 2 hours from now
A floating interval: 2 hours
An anchored interval: 2 hours from 10:15am to 12:15pm 4 December 2013 UTC
An instant that does not exist: 2:30 am Sunday 5 October 2014 Australian Eastern Daylight Time
An instant that happens twice 1 hour apart: 2:30am Sunday 6 April 2014 Australian Eastern Daylight Time
... and you get the idea.
The cleanest way to handle your problem is to have a ValidFrom and ValidTo DateTime field, when the user creates the row the ValidFrom is set to now and the ValidTo is set to NULL and a trigger executes that sets all the old entries with a NULL ValidTo to now. This will give a complete audit trail and you can get the current entry by querying for the one with the NULL ValidTo.
Related
Let's say I have a datetime, June 16 2011 at 7:00. I want to be able to check at, say, August 5 2011 at 7:00 and be able to tell that it is exactly a multiple of 1 day since the first date, whereas 7:01 would not count, since it is not an exact multiple.
Another test set: Let's say we have June 16 2011 at 7:00, and I want to check if a particular minute is within an interval of exactly 2 hours since then. So 9:00, 11:00, 13:00, etc. would count, but 9:30 and 10:00 would not. And this could continue for days and months - September 1 at 7:00 would still count as within every 2 hours. (And no, at the moment I don't know how I'm going to handle DST :D)
I thought about it for a moment and couldn't think of anything already existing in PHP or MySQL to do this easily but hell, it could, so I wanted to throw this up and ask before I start reinventing the wheel.
This is on PHP 5.1, sadly.
select *
from test
where datetimefield > '2011-06-16 07:00:00'
and
mod(timestampdiff(second,'2011-06-16 07:00:00',datetimefield),7200) = 0
This example will give you all the records greater than '2011-06-16 07:00:00' where the field is exactly a multiple of 2 hours.
Easiest would be to convert the date/time values into a unix timestamp and then simply do some subtraction/division:
2011-06-16 07:00:00 -> 1308229200
2011-08-05 07:00:00 -> 1312549200
2011-08-05 07:00:01 -> 1312549201
1312549200 - 1308229200 = 4320000 / 86400 = 50 (days)
1312549201 - 1308229200 = 4320001 / 86400 = 50.0000115...
So in other words:
if (($end_timestamp - $start_timestamp) % 864000)) == 0) {
... even multiple ...
}
Same would hold for the day/week comparisons. For months, this'll be out the window, since months aren't nice even figures to deal with.
MySQL Date functions:
http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html
You can use TIME() to get just the time part of a date. If the time parts are the same it is an exact multiple.
For the two hour thing, one way to do it would be to get the minute/seconds part of the date, make sure those are equal, then make sure that the hour parts of the dates are both even or both odd. For more complicated integer (e.g. 5) hour multiples, you can "fake" doing a mod by dividing the hour parts and checking if the result is an int.
You can compare two DateTime objects via diff() method. Result is a DateInterval object - you can check the exact number of days/hours/minutes between two dates.
It's useless to write your own algorithms if you can use built-in functionality.
TLDR: Need to understand the best way for a user to be able to add a date(s) & time(s) for an event, and how to structure database
Explanation:
When a user adds an event, they need to be able to choose the date of the event, whether or not it will repeat daily/weekly/monthly, start and end time of the event or "all-day", if it's weekdays only or weekend...etc. Basically everything you can do w/ Google calendar when you create an event and they need to be able to edit it too (if that matters). But ALSO, they need to be able to add another date/time - for instance:
Add an event where on Monday and Wednesday of this week and three weeks from now, it goes from 8-10pm. On Tuesday and Thursday this week only, it goes from 6-9pm.
My thoughts so far:
Create a "dates" table with a HABTM relationship w/ my "events" table. When a user adds a date (with all the options of repeat..etc etc., it runs a function to process those repeats/limits...etc and adds all the dates into the dates table w/ their start/end times.
But - then how do I manage it if they want to edit that - since it just created multiple fields.
Question / Help?:
Am I even on the right track with this? I'm new to CakePHP, and it's hard for me to wrap my head around the best ways to do things... I'm not yet looking for technical help (would not turn it down though) - for now, I just need to get the idea for the best way to structure everything to be able to manage this. Maybe I need a "dates" table AND a "times" table? Maybe a "dates" table with an id that references many individual rows in a "dates_data" table?
Thank you very much ahead of time for any help / direction!
You're doing great. Let me just share my thoughts.
If I would design this, I'd have 3 models:
Event
id
user_id
description
created (datetime)
updated (datetime)
Schedule
id
event_id
description
start (datetime)
end (datetime)
duration (time, if empty(NULL) it means this is a whole day event)
repeat_time (e.g. 3:00pm means 3pm daily)
repeat_day (for weekly/monthly, e.g. Monday, Monday & Tuesday, Monday to Friday)
repeat_date (for monthly, e.g. 1 means every 1st day of month, 31 means every 31st or end of the month)
repeat_anniversary (for specific date every year, e.g. every December 25th)
Date
id
schedule_id
start (datetime)
end (datetime)
Now let's have an example of an event. Let's say we want an event that will repeat every Saturday and Sunday of May & June 2011 at 1:00pm until 3:00pm (two hours):
The events table contains the basic detail of an event. One record will be saved here.
The schedules table is separated so that you could add multiple schedules. One record will also be saved in schedule with the following fields:
duration: 02:00
start: 2011-05-01
end: 2011-06-30
repeat_time: 13:00:00
repeat_day: 01,07 (Sunday & Saturday)
Now on dates table, there will be 17 records, one for each occurrence of the schedule. The reason why I separated this is that it will be easier for me know when will the event fall. This will be useful, for example, when creating the calendar. One of the records for the dates table will look like this:
start: 2011-05-01 13:00:00
end: 2011-05-01 15:00:00
Now what if the user edits the schedule? The schedule record would be edited. All dates record would also be edited. You don't wanna delete and recreate the dates, since you might use each record for another model (e.g. user might want to tag other users as attendees for each date of the event).
I hope this helps. Goodluck on your project!
I have started creating a website for a new online radio station, launching later in the year, and so far the basics are going well - it's running on Apache 2.2, with PHP 5.28.
However, I have one problem I'm struggling to find a solution for - how to store day and time in the database my site runs on, not date and time.
This is the type of thing I mean:
http://www.metroradio.co.uk/staff.asp
http://www.radioaire.co.uk/showdj.asp?DJID=41140
Notice in the second example how the date and time is shown:
This is my example:
Monday: 2:00 PM - 6:00 PM
Tuesday, Thursday - Saturday: 10:00 AM - 2:00 PM
Sunday: 7:00 PM - 11:00 PM
Although the links above use ASP.NET and IIS, my site uses PHP, and I'm not sure of the best way to get this to work in PHP.
This is my database structure for the presenter pages:
presenterid - autoincrement, INT 11
presentername - varchar, 255
airtime - DATETIME
showdesc - varchar 255
Anyone got a good solution?
thanx
You could create a second table, with the following fields :
show_id INT (foreign key)
day_id INT (use date('w'), date('S') or your own system)
begin TIME (time at which the show begins)
end TIME (time at which the show ends)
You must also add an unique constraint for the couple (show_id,day_id).
When you want to fetch the show, a simple JOIN will give you the times you want.
You could have a program table (presenter, description, etc.), having a one-to-many relationship to a schedule table (day, start time, end time).
Then, you just have to query for all the schedules of a given program, ordered by day, and detect similar start/end times for consecutive days to present them on one line.
I have a MySQL table titled 'my_cal' with a column titled 'start_time' for particular events in the calendar.
The way items are added to the database, there are no overlapping events.
There also may not be an event for a particular day/time either, in this case we leave it blank or put a blank value.
My problem lies in the fact that running 00:01AM to 23:59PM for each day sequentially would be easy, but I want to get the data as:
Mon 00:00, Tues 00:00, Wed 00:00, etc, etc
Mon 01:00, Tues 01:00, Wed 01:00, etc, etc
Mon 02:00, Tues 02:00, Wed 02:00, etc, etc
This is to build a table with 25 Rows (24 hours of the day + 1 for title), and 8 columns (7 days of the week + 1 hourly title)
Here is an example of how the calendar should look as far as HTML Table structure goes:
http://www.wmnf.org/programs/grid
I have made an attempt at getting this to work,
Running through the MySQL results, and saving them as
$data[$hour_of_the_day][$day_of_the_week]
I would then have recursive while() loops for each hour, and then each day,
$hour=0;
while($hour > 24)
{
$day=0;
while($day > 8)
{
if(isset($data[$hour][$day]))
{ echo "event"; }
$day++;
}
hour++;
}
I believe this may get me by, but it does not seem very elegant.
I also wanted the time the calendar started to be 6:00AM, and not 12:00AM.
I wanted the first day listed to be today - 3 (to center the calendar on today)
I.e:
$calendar_begin_day = date("j", mktime()) - 3;
I am looking for any way to make this easier, as I want it to run as efficient as possible due to large hit count.
Thanks
When you retrieve your results, I think you can use the ORDER BY clause and date functions on your to order them by hour and then by day and not the other way round. This way you can iterate on results and avoid storing your data in a php array.
I am trying to create a custom MySQL for use with the Expression Engine CMS. The purpose of the query is to display events that are happening today or in the future.
The problem is that the EE field type that allows you to put in the date and converts it into a unix timestamp. If I pick the 26th July it puts in the date value "25th July 23:00".
As you see from my query below it almost works but I need to add 24 hours onto the values that are used in the conditional part of the statement. I want events that occur on the day "for example today 25th July" to be displayed up until 23:00 hours that day then be removed.
I almost have it I am just stuck on how to add 24 hours to the conditional.
SELECT t.entry_id,
t.title,
t.url_title,
d.field_id_13 AS event_lineup,
d.field_id_14 AS event_details,
d.field_id_15 AS event_day,
d.field_id_16 AS event_flyer_front,
d.field_id_17 AS event_flyer_back,
d.field_id_18 AS event_facebook,
d.field_id_12 AS event_date
FROM `exp_weblog_titles` AS t
NATURAL JOIN `exp_weblog_data` AS d
WHERE d.weblog_id = 5
AND CAST(d.field_id_12 AS UNSIGNED) >= (unix_timestamp(Now()))
ORDER BY d.field_id_12 ASC
What I think might be happening is your timestamps get adjusted for the time zone, and that adjustment is configured differently in the CMS and on the server.