Using Advanced Custom Fields with the add-on of Date Time Piker, I populate a calendar with the information of Year, Date, Time (am and pm).
On the calendar listing page, I have a query and, for some reason, it skips February and repeats March twice.
Here is the code:
<?php
$today = date('Ymd h:i:s a', time() - 60 * 60 * 24);
#start from current month. Change 2 to however months ahead you want
for ($x=0; $x<=6; $x++) {
$date = new DateTime("$x months");
$date->modify("-" . ($date->format('j')-1) . " days");
#echo $date->format('j, m Y');
$month = $date->format('m');
$year = $date->format('Y');
#echo 'Month= '.$month .' Year= '.$year.' <br>'; #debug
$rows = $wpdb->get_results($wpdb->prepare(
"
SELECT *
FROM wp_postmeta
WHERE meta_key LIKE %s
AND meta_value LIKE %s
ORDER BY meta_value ASC
",
'show_date_time_%_show_date', // meta_name: $ParentName_$RowNumber_$ChildName
#''.$year.''.$month.'%' // meta_value: 20131031 for example
''.$year.''.$month.'%' // meta_value: 20131031 for example
));
// loop through the results
if( $rows ) {
echo '<div class="month">';
echo '<h2>'.$date->format('F').' '.$date->format('Y').'</h2>';
echo '<ul>';
foreach( $rows as $row ) {
// for each result, find the 'repeater row number' and use it to load the sub field!
preg_match('_([0-9]+)_', $row->meta_key, $matches);
$meta_key = 'show_date_time_' . $matches[0] . '_show_date'; // $matches[0] contains the row number!
// today or later
$showDate = $row->meta_value;
$do_current = ($showDate > $today);
if ( $do_current || $continue ) :
$show_title = get_the_title( $row->post_id );
$machine_name = preg_replace('#[^a-z0-9-]+#','-', strtolower($show_title));
$post_type = get_post_type($row->post_id);
if( $post_type === 'pre-post-show' ){
// echo 'pre-post-show matching';
$postID = $row->post_id;
$posts = get_field('pre_post_related_show', $postID);
if( $posts ){
foreach( $posts as $post): // variable must be called $post (IMPORTANT)
setup_postdata($post);
$related_show = get_the_title($post->ID);
$related_show_machine = preg_replace('#[^a-z0-9-]+#','-', strtolower($related_show));
endforeach;
wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly
}
}// post type define
?>
Any thoughts about why this could be happening?
Well, it's a bit trickier than it seems. In this stackoverflow post you'll find a complete explanation of this "odd" behaviour. To sum up:
+1 month increases the month number (originally 1) by one. This makes the date 2015-02-31.
The second month (February) only has 28 days in 2015, so PHP auto-corrects this by just continuing to count days from February 1st. You then end up at March 3rd.
That's why you're seeing month 3 twice. How to get around this? Well, in the post I showed you there are some ways of getting around this "problem". If you have php 5.3 or higher, I'd suggest this:
$date = new DateTime();// Now.
for ($x=0; $x<=6; $x++) {
($x) ? $date->modify( 'first day of next month' ) : NULL;// It should give you next month from $x=0 onwards. Output: 01,02,03,04,05,06,07
....// Your code comes here
Hope it helps.
UPDATE
There are a lot of documentation relative to dates and PHP. The DateTime class is really handy to deal with dates. Check its modify method to change the date. Lastly, have a look at the different date and time supported formats. Especially to the relative formats if you're interested in modifying dates using strings like '+7 day'.
Lastly, have a look at the wpdb documentation. The class wpdb allows you to interact with the database in wp. You'll have to learn a bit of SQL in order to make queries. There are hundreds of pages on the internet (not to mention books) that will help you to learn.
For instance, if you want to retrieve all posts that are within the next 7 days you could do something like:
$now_date = (new DateTime())->format("Y-m-d");
$next_seven_days = (new DateTime("+7 day"))->format("Y-m-d");
$query = "SELECT * FROM wp_posts WHERE post_date >= '$now_date' AND post_date < '$next_seven_days'";
$rows = $wpdb->get_results( $query, OBJECT );
Note: since there is no input from the users/visitors nor they can't effect the query, I'm not going to use prepare for simplicity's sake. Anyway, I must say it's good practice to use it systematically.
Related
I'm trying to create a filter, whereby if days (Monday, Tuesday etc) are NOT found in a list, I want that specific DateTime to be removed from my DatePeriod. This is so that I can say, I work Monday and Tuesday. If you find that the day is Thursday, continue out of this loop and don't include it.
However, I cannot seem to do this as when I iterate through a DatePeriod, I cannot unset anything, as it does not count it as an array. Is there a way to do this? The code can be found below:
//Get all the start and end dates of the holidays (This will be run iteratively)
$get_st_date = $row['h_s_date'];
$get_end_date = $row['h_e_date'];
//Convert them to approprariate format to be used with DatePeriod
$get_begin = new DateTime( "$get_st_date" );
$get_end = new DateTime( "$get_end_date");
//Add an extra day or else it will be omitted from the following process.
$get_end = $get_end->add(new DateInterval('P1D'));
//Count per day
$get_interval = DateInterval::createFromDateString('1 day');
$get_period = new DatePeriod($get_begin, $get_interval, $get_end);
//Iteration Count
$iter = 0;
foreach($get_period as $get_dt){
//Find if date is Saturday or Sunday. If it is, break that current loop.
$iter++;
$str_result = $get_dt->format('l');
if($str_result == "Saturday") {continue;}
elseif($str_result == "Sunday") {continue;}
elseif(!preg_match("($str_result)", $e_d_w_p_w)){
echo "<br>Don't count this day" . $str_result;
unset($get_period[$iter]);
continue;
}
Then close the end tags (I haven't included it here as I do some other stuff.
From the above code, I get the following error:
"Fatal error: Uncaught Error: Cannot use object of type DatePeriod as array"
Is there a workaround to this?
For Clarification: $e_d_w_p_w is "Employee Days Worked Per Week"
$e_d_w_p_w is formatted like so "Monday;Tuesday;" etc
The problem is that DatePeriod is not an array, just like the error says. It just has the properties required so as to make the list of days required, but it doesn't store them, so you can't unset() a specific day from the list.
What you can do to accomplish this is create a new array, and instead of removing the days that do not match the criteria from the DatePeriod, only add the days that do to this new array:
<?php
$get_st_date = "2017-09-01";
$get_end_date = "2017-09-20";
//Convert them to approprariate format to be used with DatePeriod
$get_begin = new DateTime( "$get_st_date" );
$get_end = new DateTime( "$get_end_date");
//Add an extra day or else it will be omitted from the following process.
$get_end = $get_end->add(new DateInterval('P1D'));
//Count per day
$get_interval = DateInterval::createFromDateString('1 day');
$get_period = new DatePeriod($get_begin, $get_interval, $get_end);
$e_d_w_p_w = "Monday;Tuesday;";
$workDays = [];
//Iteration Count
$iter = 0;
foreach($get_period as $get_dt) {
//Find if date is Saturday or Sunday. If it is, break that current loop.
$iter++;
$str_result = $get_dt->format('l');
if($str_result == "Saturday") {continue;}
elseif($str_result == "Sunday") {continue;}
elseif(preg_match("($str_result)", $e_d_w_p_w)){
$workDays[] = $get_dt;
}
}
var_dump($workDays);
Demo
Also, I think it might be a bit cleaner (and faster; avoid regular expressions whenever possible) to transform $e_d_w_p_w to an array and check if the current day is in that array:
$e_d_w_p_w = "Monday;Tuesday;";
$days = explode(";", $e_d_w_p_w); // transform to an array, separating by ;
array_pop($days); // remove the last element (assuming you always have a trailing ;
and then
elseif(in_array($str_result, $days)){
$workDays[] = $get_dt;
}
I was researching ways to iterate over certain days within a DatePeriod and Google led me here. I ended up writing a class for it - hopefully this helps the OP.
DatePeriod_Filter gist
To address the OP needs, you may use it like so:
$e_d_w_p_w = "Monday;Tuesday;";
//Add an extra day or else it will be omitted from the following process.
$filter = new DatePeriod_Filter(
new DateTime( '2017-09-01' ),
new DateInterval( 'P1D' ),
new DateTime( '2017-09-20 + 1 day' )
);
foreach( explode( ';', strtolower( trim( $e_d_w_p_w, ';' ) ) ) as $day )
$filter->$day();
foreach( $filter as $date )
{
// do something here
}
Ok so I have this code and im not sure exactly how to go about checking if the post modified date was more than a week ago.
So if the post was modified more than a week ago it should echo modified.
The code:
$sticky = get_option( 'sticky_posts' );
if (count($sticky) > 0) {
$stringSticky = implode(",", $sticky);
$postsModifiedCheck = $wpdb->get_results(
"SELECT ID, post_modified
FROM `{$wpdb->prefix}posts`
WHERE post_status = 'publish' AND post_type = 'post'
AND ID IN ($stringSticky)"
);
$now = new DateTime();
$currentDateTime = $now->getTimestamp();
foreach ($postsModifiedCheck as $post) {
if ($currentDateTime > $post->post_modified) {
echo "modified";
}
}
}
So at the moment it will echo "modified", just not sure how to modify the dates to echo "modified" if $post->post_modified more than a week ago.
Cheers
check your formats -
var_dump($currentDateTime .' <- current date - modified date -> '.$post->post_modified );
see if they are the same format,
if they are not the same format, force them to be the same like this
then when you get to that point - just create a variable where you check the difference f.eks
if($currentDateTime - $post->post_modified >= 7){echo 'shiit, It has been modified over a week ago'; }
This should help you on your way
Ok so this is how I solved the problem.
While in the loop use this code:
$weekAgo = strtotime('-1 week');
foreach ($postsModifiedCheck as $post) :
if (intval(strtotime($post->post_modified)) < intval($weekAgo)) unstick_post( $post->ID );
endforeach;
The code will check if the post modified date was more than one week ago and unstick the post.
Hope this helps someone :)
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.
I am currently attempting to get a list of dates from a current date using the following format so that I can process it and stick it in my database
Saturday/02-05-2015
So far, i've managed to get the system to output the date correctly, but can not get it to increment in single day values.
My current code to attempt to increment this is the following
$tempStartDateN = ("$splode[0]/$splode[1]/$splode[2]/$splode[3]");
echo $tempStartDateN;
$tempStartDateN = date('l/d/m/Y', strtotime($tempStartDateN . ' + 1 day'));
echo $tempStartDateN;
I am currently using explode to process the data after the increment, which works fine, but can not get the date itself to increment as long as the day name is included.
Currently, the time is got using this code, which is processed afterwords using explode
$OldDateArray = date("Y/m/d/l");
So to keep a long question short, what is the best way to increment a date that requires the day name, day, month then year?
EDIT:
Heres my current code, managed to get this far thanks to SamV
$date = date("l/d/m/Y");
echo $date;
echo ('</br>');
list($weekdayName, $dateString) = explode("/", $date, 2);
$dateObj = new \DateTime($dateString);
for($i=0; $i<=5; $i++){
$dateObj->add(new \DateInterval("P1D")); // P1D stands for "Period 1 Day"
echo $dateObj->format("l/d/m/Y"); // Sunday/03/05/2015
echo ('</br>');
}
What this does however is:
Friday/01/05/2015
Tuesday/06/01/2015
Wednesday/07/01/2015
Thursday/08/01/2015
Friday/09/01/2015
Saturday/10/01/2015
Sunday/11/01/2015
this means that date and month are swapping around, what is causing this?
You don't need to parse the week day name to add days onto a date.
$date = "Saturday/02-05-2015";
list($weekdayName, $dateString) = explode("/", $date, 2); // Parse "02-05-2015"
$dateObj = new \DateTime($dateString);
$dateObj->add(new \DateInterval("P1D")); // P1D stands for "Period 1 Day"
echo $dateObj->format("l/d/m/Y"); // Sunday/03/05/2015
I used the DateTime class, here is the documentation.
I wrote out what you are trying to do yourself, not sure what is causing your issue. This code works though.
$date = "Friday/01-05-2015";
list($weekdayName, $dateString) = explode("/", $date, 2); // Parse "01-05-2015"
$dateObj = new \DateTime($dateString);
for($i = 0; $i < 5; $i++) {
$dateObj->add(new \DateInterval("P1D")); // P1D stands for "Period 1 Day"
echo $dateObj->format("l/d/m/Y") . '<br>';
}
Outputs:
Saturday/02/05/2015
Sunday/03/05/2015
Monday/04/05/2015
Tuesday/05/05/2015
Wednesday/06/05/2015
If strtotime is able to parse a date it returns the timestamp. Why not add to it the number of seconds in a day? Smth. like $timestamp += 24 * 3600;
P.S. As far as I can understand, strtotime may accept timestamp as second argument (http://us2.php.net/manual/en/function.strtotime.php) smth. like $timestamp = strtotime('+1 day', $timestamp);
I wish to print the totals of a column in my database for each month in the last year. The code I have so far to do this is:
$month = date("n");
$year = date("Y");
$loop = 12;
while($loop>1) {
$first = mktime(0,0,0,$month,1,$year);
$last = mktime(23,59,00,$month+1,0,$year);
$spendingData = mysql_query("SELECT * FROM spending WHERE date BETWEEN $first AND $last") or die(mysql_error());
$totalMonth = 0;
while($spending = mysql_fetch_array($spendingData))
{
$totalMonth = $totalMonth + $spending['amount'];
}
print "£".$totalMonth;
$loop = $loop-1;
print "<br>";
}
My quesiton is how, in the loop, do I adjust the times for each month? I thought about just taking a months worth of seconds away from the timestamps, but as I don't know how many days are in each month I don't think this will work. I also don't think I can just keep taking 1 away from the month figure as this will not account for years. I also don't want to hard code the figures in, as they will change with each new month.
How can I achieve this?
Thank you
You could do this rather trivially in MySQL:
SELECT MONTH(date) AS month, SUM(amount) AS amount
FROM yourtable
WHERE YEAR(date) = $year
GROUP BY MONTH(date)
without ever having to involve PHP for the date manipulation stuff.