I am trying to compare two date strings of type d/m/y, but it seems that something with the comparison of that type of dates doesn't work. I thought to use DateTime PHP's function, but at first I want to learn why the script above doesn't work.
Here is the code:
public function listActiveNews(){
$today = strtotime(date('d/m/Y'));
$db = mysql_init();
$sql = "SELECT * FROM ph_news WHERE newActive = 1";
$prq = $db->prepare($sql);
$prq->execute();
foreach($prq->fetchAll(PDO::FETCH_ASSOC) as $fetch){
$dateFrom = strtotime($fetch['newsDateFrom']);
$dateUntil = strtotime($fetch['newsDateUntil']);
if ( ($today >= $dateFrom) && ($today <= $dateUntil) ){
print date('d/m/Y') . " >= " . $fetch['newsDateFrom'] .
" && " . date('d/m/Y') . " <= " .
$fetch['newsDateUntil'] ."<br>" ;
print $fetch['Title'];
}
}
}
I am getting this result and I cannot understand why the comparison of these dates returns TRUE in the if clause.
Output:
28/02/2014 >= 20/03/2014 && 28/02/2014 <= 27/02/2014
Title
Here are the dates values:
date('d/m/Y') = 28/02/2014
$newsDateFrom = 20/03/2014
$dateUntil = 27/02/2014
Really... stop abusing the date system. $today = strtotime(date('d/m/Y')); is utterly pointless. $today = time() is the less convoluted and far more efficient version.
Plus, why are you doing the time filtering in PHP when you could simply do it in MySQL?
SELECT *
FROM ph_news
WHERE (newActive = 1) AND (curdate() BETWEEN newsDateFrom AND newsDateUntil)
will fetch only the records you actually want. Right now you're fetching pretty much the entire table, and then throwing away most everything except the few records you really did want.
Related
I want to create a function that checks, if a specific time is between two timestamps that are stored in a MySQL database.
The function should be able to ignore the time ($fullday = true) or check the time as well.
My presence table has a row with start = 2021-11-01 10:00:00 and end = 2021-11-05 18:00:00.
is_available('2021-11-02', true); should give me a result, but is doesn't.
What I expect as well:
is_available('2021-11-01 09:30:00'); should not have a result, as 9:30 is before 10:00 but is_available('2021-11-01 10:01:00'); should give me a result. And so on.
The query, my function creates is:
SELECT *
FROM `presence`
WHERE DATE_FORMAT(start, "%Y-%m-%d") <= "2021-11-02"
AND DATE_FORMAT(end, "%Y-%m-%d") >= "2021-11-02"
And this my function so far:
function is_available($date, $fullday = false)
{
$presenceModel = new PresenceModel();
if ($fullday) {
$date = date('Y-m-d', strtotime($date));
$presences = $presenceModel
->where('DATE_FORMAT(start, "%Y-%m-%d") <= "' . $date . '"')
->where('DATE_FORMAT(end, "%Y-%m-%d") >= "' . $date . '"')
->findAll();
} else {
$date = date('Y-m-d H:i:s', strtotime($date));
$presences = $presenceModel
->where('DATE_FORMAT(start, "%Y-%m-%d %H:%i:%s") <= "' . $date . '"')
->where('DATE_FORMAT(end, "%Y-%m-%d %H:%i:%s") >= "' . $date . '"')
->findAll();
}
return count($presences) > 0 ? true : false;
}
You should be able to simplify this dramatically by getting MySQl to do more of the work. You don't need to format DATETIME columns to do comparisons on them, and BETWEEN will further reduce your PHP effort.
Based on your code above I think this will do the job:
function is_available($date, $fullDay = false) {
$presenceModel = new PresenceModel();
$date = date('Y-m-d H:i:s', strtotime($date));
if ($fullDay) {
$presences = $presenceModel
->where("'$date' between DATE(`start`) and DATE(`end`)" )
->findAll();
} else {
$presences = $presenceModel
->where("'$date' between `start` and `end`" )
->findAll();
}
return count($presences) > 0 ? true : false;
}
However, using SELECT * will return the entirety of all the matching rows, when all you really need is whether one exists. You should aim to get your query something close to this, which will return just a single value (1) if there's a matching row.:
SELECT 1 FROM `presence`
WHERE "2021-11-02" between start AND end
LIMIT 1
My approach would be to use strtotime() function to convert the date into an int and then convert the other date from the db and then compare those ints in php.
if($datenow > $dbstartdate && $datenow < $dbenddate){
return true;
}else{
return false;
}
I am using MVC framework called FuelPhp I am aware this is an old framework but this is what the application runs on.
Trying to send an email comparing two datetimes, so if the website is down which is recorded in $down_timeand five minutes have passed which is recorded in the $last_checked_time then an email should send. The problem I am having is the code seems to stop at this line $difference = $last_checked_time->diff($down_time); and is never hitting the if statement. Basically all I want to do is to check if the $last_checked_time is greater than the $down_time by 5 minutes. There are no errors been logged so I'm unsure what the problem is, I would really appreciate the help thank you.
$down_time = DateTime::createFromFormat('Y-m-d H:i:s', $website->down_at);
$last_checked_time = DateTime::createFromFormat('Y-m-d H:i:s', $website->last_checked);
$difference = $last_checked_time->diff($down_time);
if ($difference->format("a") > 0 || $difference->format("h") > 0 || $difference->format("m") >= 5) {
Cli::write("Emailing: " . $website->url . " is offline");
$notify_emails = array();
foreach ($services as $service)
{
$service_id = $service->service_id;
if (in_array($service_id, $dept_emails))
{
$notify_emails[] = $dept_emails[$service_id];
}
}
$message = "Hi," . $website->url . " has been down since " . $website->down_at . ".";
$email = Model_Mail::send_email($dept_emails, "" . $website->url . " is down", $message);
$result = DB::update('clients_websites')
->set(array(
'down_email_sent' => date('Y-m-d H:i:s')
))
->where('id', '=', $website->id)
->execute();
}
When calling format you need to use a % symbol in front of the format string:
if ($difference->format("%a") > 0 || $difference->format("%h") > 0 || $difference->format("%m") >= 5) {
Also, %m is months. If you want minutes you should use %i.
edit
Also again, the DateInterval class can be annoying because you have to check many properties, it might be easier to just deal with seconds:
$diff_in_seconds = $last_checked_time->getTimestamp() - $down_time->getTimestamp();
if($diff_in_seconds >= 300){
//Do something
}
I have some problems with dates. I need make if like --->
if your activity is less than 1 day do somethink
else if your activity is more than 1 day and less than 3 do moething else
else if your activity is more than 3 do moething else
I need this in PHP. My actual code is:
if (strtotime(strtotime($last_log)) < strtotime('-1 day') ) {
$prom .= "" . json_encode('last_activity') . ": " . json_encode("inactive less than 1 day") . ",";
} else if (strtotime($last_log) > strtotime('-1 day') && strtotime($last_log) < strtotime('-3 day')) {
$prom .= "" . json_encode('last_activity') . ": " . json_encode("inactive more than 1 day and less than 3 days") . ",";
} else if (strtotime($last_log) > strtotime('-3 day')) {
$prom .= "" . json_encode('last_activity') . ": " . json_encode("inactive more than 3") . ",";
}
I think I really don't understand date calculations.
Date_diff is much easier in this case:
$datetime1 = date_create(); // now
$datetime2 = date_create($last_log);
$interval = date_diff($datetime1, $datetime2);
$days = $interval->format('%d'); // the time between your last login and now in days
see: http://php.net/manual/en/function.date-diff.php
Or in your way:
if(strtotime($last_log) < strtotime('-1 day')){
// it's been longer than one day
}
If you want to do it with strtotime, do it like this:
date_default_timezone_set('SOMETHING FOR YOU');
$last_log = '-0.5 day';
$last_log_time = strtotime($last_log);
$minus1day_time = strtotime('-1 day');
$minus3day_time = strtotime('-3 day');
echo $last_log_time . "<br>";
echo $minus1day_time . "<br>";
echo $minus3day_time . "<br>";
if ($last_log_time < $minus3day_time)
{
echo "inactive more than 3";
}
elseif ( ($last_log_time <= $minus1day_time) && ($last_log_time >= $minus3day_time) )
{
echo "inactive more than 1 day and less than 3 days";
}
elseif ($last_log_time > $minus1day_time)
{
echo "inactive less than 1";
}
Couple things I changed from your code:
remove the strtotime(strtotime()). Do not do it twice!
For your second if, I added parentheses to ensure correct evaluation of conditions.
I reversed the order of your if. First check if it is very old (so < -3). Then check if it is between -3 and -1. Then check between -1 and now.
Added <= and >=. The = cases were missing from your code. So if the last_log was == -1, it was not processed ever.
I replace "else if" by "elseif".
I used variables because recalculating strtotime all over is wasteful. And it makes the code less readable IMHO.
Then apply the json_encode comment.
To explain why the logic was reversed:
the last login of a user will always be before now.
lets say that the user's last_login is 5 days ago. strtotime($last_login) will be smaller than strtotime('-1 days'), so the if will be true. But that is not what the OP wants! He wants here the case where the last login is older than 3 days.
Remember that we are comparing numbers in the past, so the smaller, the older.
$dateLog = new DateTime($last_log); // format if needed
$tomorrow = new DateTime("tomorrow");
$yesterday = new DateTime("yesterday");
$threeDaysAgo = new DateTime("-3 days");
if ($dateLog < $yesterday) {
// Do what you want
} else if ($dateLog > $yesterday && $dateLog < $threeDaysAgo) {
// Do another thing
} else if ($dateLog > $threeDaysAgo) {
// ...
}
The doc is here : http://php.net/manual/en/datetime.diff.php
Im using the following mysql script to display a list of active / upcoming fixtures.
Select * FROM schedule
WHERE schedule.gameDate > CURDATE() OR
( schedule.gameDate = CURDATE() and schedule.gameTime > CURTIME() )
GROUP BY schedule.tournament
ORDER By schedule.gameDate
The above script works perfectly.
However, as an additional check to prevent a user from accessing a fixture which has expired im doing the following.
$curTime = date('H:i:s');
$curDate = date('Y-m-d');
$sql = "SELECT * FROM schedule
WHERE tournament = :tour AND weekNum = :round";
$stmnt = $db->prepare($sql);
$stmnt->bindValue(':tour',$tournament);
$stmnt->bindValue(':round', $round);
$stmnt->execute();
$results = $stmnt->fetchAll();
foreach($results as $result){
echo $eventDate = $result['gameDate'];
echo $startTime = $result['gameTime'];
if($curDate > $eventDate){
echo '<h1> CURRENT ROUND ALLREADY STARTED</h1>';
die();
}//if
else if($eventDate==$curDate && $curTime>$startTime){
echo '<h1> CURRENT ROUND ALLREADY STARTED</h1>';
die();
}//else if
}//foreach
My Problem.
The loop never passes the first IF statment which always results to true...
DB Table
When I echo the variables I get the following:
$curTime = 09:30:00
$curDate = 2017-19-03
$eventDate = 2017-03-21
$startTime = 13:00:00
I realize it is not the prettiest code but according to my little experience and logic it should pass both if statments...
Any advise appreciated
Use strtotime() in compare two date in php
Replace if($curDate > $eventDate) with if(strtotime($curDate) > strtotime($eventDate)) and other comparison also
You can convert them to DateTime objects or timestamps to compare. String comparison will only check whether they are equal or not.
So:
$now = new DateTime();
$event = new DateTime($eventDate . ' ' . $startTime);
Then you can check whether dates are equal or later the same way you're already doing. See Example #2 on the Date Diff page of the php website. E.g. $now > $event, etc.
It should be elseif.not else if. There should not be a space between else and if.
This is setup to show a button between 2 dates set. And to show a "Sign up starts at xxx" before the set start up date, and "Sign up closed the xxxx" after the set end date...
Somehow nothing shows for the "active periode" / the dates in betweeen...
$DateToday = date('Ymd');
$DateStart = get_field('pamelding_fra');
$DateEnd = get_field('pamelding_slutt');
$DateStartOut = new DateTime($DateStart);
$DateEndOut = new DateTime($DateEnd);
if ($DateStart >= $DateToday){
$ClassStatus = "<div class=\"OpenClassButton\"><span class=\"ClassFullWarning\">Påmeldingen åpner " . $DateStartOut->format('j M Y') . "</span></div>";
$ClassButton = $ClassStatus;
}elseif ($DateEnd <= $DateToday){
$ClassStatus = "<div class=\"OpenClassButton\"><span class=\"ClassFullWarning\">Påmeldingen stengte " . $DateEndOut->format('j M Y') . "</span></div>";
$ClassButton = $ClassStatus;
}elseif ($DateStart <= $DateToday && $DateEnd >= $DateToday){
//Do some stuff - show button, this is the active time.
}
Might not be best-practice and I might make stuff difficult for me, suggestions appriciated.
Don't compare dates using date strings. If they are in different formats (like Ymd, mdY etc) you will get unwanted results. Use unix timestamps instead.
$today = time(); // Get today's timestamp
if ($today < strtotime($DateStart)) {
// Do stuff before
} elseif ($today > strtotime($DateEnd)) {
// Do stuff after
} else {
// Active. No need for any conditions here,
// since we only have three states.
}