I am working on a page which contains the following line of mysql. The overal objective is simply to match the current week num to the current date
$sql = "select distinct weekNum from " . DB_PREFIX . "schedule where DATE_ADD(NOW(), INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR)"
As per my research DATE_ADD() allows you to add a certain number of days to a date.
Thus I am assuming DATE_ADD(NOW() adds the current date to...well date?
What exactly does INTERVAL do in this statment.
Any help interms of an explanation clarifying above statment will be much appreciated.
DATE_ADD(NOW(), INTERVAL 2 HOURS)
-- This will add 2 hours to the current time
-- The format is DATE_ADD(date, INTERVAL value unit)
value can be anything --> a number
unit will be -- > anything from following list
MICROSECOND
SECOND
MINUTE
HOUR
DAY
WEEK
MONTH
QUARTER
YEAR
SECOND_MICROSECOND
MINUTE_MICROSECOND
MINUTE_SECOND
HOUR_MICROSECOND
HOUR_SECOND
HOUR_MINUTE
DAY_MICROSECOND
DAY_SECOND
DAY_MINUTE
DAY_HOUR
YEAR_MONTH
So you can add minutes , Hours , months into your date using this function
Like that you can use the function DATE_SUB(date, INTERVAL value unit) Which will substract the date hope you are clear. for more information just visit the link [https://www.w3schools.com/sql/func_mysql_date_add.asp]
As far as I can see this statement is trying to manage timezone difference
INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR
should return difference(in hours) for different timezone(server and offset) which is then added to current date to calculate actual time for scheduling.
from https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add
DATE_ADD(date,INTERVAL expr unit), DATE_SUB(date,INTERVAL expr unit)
These functions perform date arithmetic. The date argument specifies the starting date or datetime value. expr is an expression specifying the interval value to be added or subtracted from the starting date. expr is a string; it may start with a - for negative intervals. unit is a keyword indicating the units in which the expression should be interpreted.
It takes a date - is this case "now" and ads some hours to it.
In this case it reads the server timezone offset and adds that.
The result would be a date where you get a selection based on the GMT-0 based time.
The function DATE_ADD() has two parameters:
1. the date to which you want to add any interval
2. the amount of units with key words INTERVAL the numbe UNITS, where 'UNITS' can be any supported time value between MILLISECONDS ~ YEAR
The DATE_ADD() is the synonym of ADDDATE().
Related
How to write a sql query to find out that there are 2 days left before the current date.
In php, this can be done via:
$res['end_date'] - time () < 86400 * 3;
How can I do the same after 1 sql query, well or better, only 2 days, if less so that it does not work out, well, if it works out, it's okay.
UPD:
It is necessary to compose a sql query that will select only those records that have 2 days left before the end_date expires
The type is int for the field end_date and is stored via the time () function in php.
Can't compose a WHERE clause.
You can use the FROM_UNIXTIME function to convert it to a DateTime you can then use the NOW() plus 2 days to check if the date is under 2 days. You then have to check that the date is before the current time otherwise you'll get dates that have already gone.
SELECT
end_date
FROM
table
WHERE
FROM_UNIXTIME(end_date) <= NOW() + INTERVAL 2 DAY
AND
FROM_UNIXTIME(end_date) > NOW()
Assuming that you are storing an epoch timestamp (the number of seconds since January 1st, 1970), I would recommend:
select *
from mytable
where end_date >= unix_timestamp() and end_date < unix_timestamp() + 2 * 24 * 60 * 60
unix_timestamp() gives you the current epoch. You can use simple math to add two days to that.
The upside of this approach is that this does direct filtering against the store value, so this can take advantagae of an index on end_date - as opposed to converting the timestamp to a date, which requires converting the whole column before the filtering can happen. So this is much more efficient.
You can ajust the inequalities as you prefer. I used a half-open interval (inclusive on the lower bound and exclusive on the upper bound), which is a widely used approach.
I ended up doing this:
$time = time();
$params = $db->query("SELECT * FROM `params` WHERE (`end_date` - {$time}) < 86400 * 3");
And it worked.
I always do
select *
from mytable
where FROM_UNIXTIME(end_date) < NOW() + INTERVAL 2 DAY
This will get results where two days in the future is ahead of the end date ie, anything that will end within 2 days (or has already ended as I didn't add a check for that)
Edit: I see you can't use where
If you cannot use where clause
select FROM_UNIXTIME(end_date) - INTERVAL 2 DAY as end_date
from mytable
And then check in php if the result is before or after. This will show all results however
I probably made a poor decision years ago where I have been storing intervals in a char(3) column with values such as "1M" or "3M" or "1Y". This helps me store info about recurring invoices. "1M" means the invoice renews every 1 month.
Here is a sample for the database : https://i.imgur.com/D8oKaV3.png
The reason of this poor design is because I calculate the next invoice date through a php function :
function increment_date($date, $increment)
{
$new_date = new DateTime($date);
$new_date->add(new DateInterval('P' . $increment));
return $new_date->format('Y-m-d');
}
so that I can pass it arguments such as "P1M" which was actually very convenient for DateInterval
I now wish I stored them such as "1 month" instead of "1M", because I am stuck when try to run the following dynamic SQL request :
SELECT SUM(invoice_total) prevision_for_current_month
FROM lf_invoice_amounts a
JOIN lf_invoices_recurring r
ON r.invoice_id a.invoice_id
WHERE (month(recur_next_date) = 5 and year(recur_next_date)= 2020)
OR (month(recur_next_date - INTERVAL recur_frequency) = 5 and year(recur_next_date - INTERVAL recur_frequency) = 2020)
The part with month(recur_next_date - INTERVAL recur_frequency) fails and throws an error because it runs such as month(recur_next_date - INTERVAL 1M) which mySQL does not understand, while the following would have been correct : month(recur_next_date - INTERVAL 1 month)
The purpose of this sql request is to estimate all the money that should come in during current month, from invoices that are recurring every month/3 months/year/2 weeks/etc
I cannot refactor the whole code base at this moment. What would be a possible workaround?
TL;DR : How do I transform a column that contains value "1M" into "1 month" so that I can run SQL requests with intervals. (same for "3M" or "1Y" or "1M" or "2W" or "30D" or "31D", etc).
Ugly solutions also welcome. I'm currently think about a big nest of replace() maybe like month(recur_next_date - INTERVAL replace(recur_frequency, 'M', ' month')) ?
Unfortunately converting your recur_frequency into a string like 1 month isn't going to help, as the syntax for intervals requires that unit be one of YEAR, MONTH, DAY etc. i.e. one of a fixed set of specifiers, not a string, so trying to use something like INTERVAL recur_frequency or even INTERVAL recur_frequency recur_period won't work. Without using dynamic SQL to insert the value of recur_frequency into the query I think your best option is probably to store the recurrence frequency into one of 4 columns (e.g. recur_year, recur_month, recur_week, recur_day), then you can use a query such as
curdate() - interval recur_year year
- interval recur_month month
- interval recur_week week
- interval recur_day day
Demo on dbfiddle
Need help here, having an mysql table called APPROVAL, there having an id,dateandtime and level, i need a query that selects the id alone with the following condition.
Taking date alone from database and comparing it with current system date, if the days exceeds above 30 and below 60 and also level = 5.
How can I write a query for this.
Thanks in advance.
MySQL has good date arithmetic. For example, the expression
CURDATE() + INTERVAL 30 DAY
gives a datetime value denoting midnight 30 days hence. Similarly
CURDATE() + INTERVAL 61 DAY
yields midnight on the 61st day.
So a query of the form
SELECT ID
FROM APPROVAL
WHERE Level = 5
AND `DateTime` >= CURDATE() + INTERVAL 30 DAY
AND `DateTime` < CURDATE() + INTERVAL 61 DAY
will yield what you want. Notice the use of >= for the beginning of the range of days, and the use of < and an extra day for the end of the range. We do that because we want all items from the 60th day, and none from the 61st day.
A compound index on (Level, DateTime) will make this query very efficient to satisfy.
Notice that an expression like
DATE(`DateTime`) <= CURDATE() + INTERVAL 60 DAY /* slow! */
will also yield correct results, but the presence of the the DATE() function call on the column to be searched makes it unsargeable. That is, it makes MySQL unable to use an index to satisfy the search.
Ok so use this query to retrieve all the IDs that match level 5 and date diff between 30 and 60 compared to the current date.
SELECT id
FROM APPROVAL
WHERE level = 5 && DATEDIFF(NOW(), dateandtime) BETWEEN 30 AND 60
I'd suggest you to order them dy date DESC too.
Hope that helps
I hope, I understood your problem correctly.
select `ID`
from APPROVAL
where `Level` = 5
and ( DATE(`DateTime`) > curdate() + interval 30 day
and DATE(`DateTime`) < curdate() + interval 60 day )
order by `ID` asc;
Where DATE() gets the date from a datetime and CURDATE() is the current system date. With interval you can manipulate a date expression whitout having to worry about its limits.
This question already has answers here:
Add 2 hours to current time in MySQL?
(5 answers)
Closed 8 years ago.
I have a subscription system in my website. When the users subscribe, their start date and time is added using the now() function. I also need to calculate the date and time six months from now and store it in database. How can I do it?
DATE(DATE_ADD(NOW(), INTERVAL 6 MONTH))
can be used directly in your query and will do the job:
INSERT INTO table (datenow,dateplus6m) VALUES (NOW(), DATE(DATE_ADD(NOW(), INTERVAL 6 MONTH)));
Explanation from the docs:
DATE_ADD(date,INTERVAL expr unit)
These functions perform date arithmetic. The date argument specifies the starting date or datetime value. expr is an expression specifying the interval value to be added or subtracted from the starting date. expr is a string; it may start with a “-” for negative intervals. unit is a keyword indicating the units in which the expression should be interpreted.
The date_add function is what you're looking for:
INSERT INTO users
(username, registration_date, six_months_date)
VALUES ('someone', NOW(), DATE_ADD (NOW(), INTERVAL 6 MONTH));
Try this
$newDate = date('Y-m-d', strtotime("+6 months", time()));
echo $newDate;
OUTPUT
2015-06-01
You can use date function for adding months in php .
Suppose $date contains current date,$date1 contains current date + 6 months
Here is the code
$date=date("Y-m-d");
echo $date;
$date1=date('Y-m-d',strtotime("6 months"));
echo $date1;
Here is the manual for other options
Hope this helps!
Please I am making a reminder to start sending mails for events starting in 7 days or less.
That is send mails to attendees to events starting in 0 - 7 days only.
Where I need help is on this line:
...WHERE event_start_date > '$current_time' //currently sends to all attendees for all events starting in future
$current_time = time();
How can I change that to reflect what I need?
Kindly note date is stored in unix_timestamp.
Thank you
You could also do this in MySQL only, without determining the time in PHP first. I don't think it's faster, but it's a lot more readable.:
...WHERE FROM_UNIXTIME(event_start_date) <= DATE_ADD(CURDATE(), INTERVAL 1 WEEK)
However, this also returns events starting before today. If you don't want that, you could use:
...WHERE FROM_UNIXTIME(event_start_date) BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 1 WEEK)
(adapted from the MySQL docs)
Get the current unix timestamp.
$current_time = time();
As it is stored in seconds, you can add to it by adding 60 seconds * 60 minutes * 24 hours * 7 days to get the unix timestamp in a week.
$weekFromNow=$current_time+(60*60*24*7);
Now just find events where the event_start_date is less than or equal to it.
...WHERE event_start_date <= '$weekFromNow'
and event_start_date > '$current_time'
//sends to all attendees for all events starting in future
Edit: as $weekFromNow is one week into the future, the query needs to find all times less than or equal to that value, which is what the query does. If your event_start_date holds some value OTHER than the unix timestamp of the event starting time, let me know.