Can not figure out why results do not match the date range that was specified with DateTime()

I already tried to find the answer by myself with the help of related posts like:

but unfortunately I wasn’t able to find my mistake :-/ So I’m asking you for your support.

I’m currently trying to customize a wordpress theme for an event website and I’d like to enhance the existing search options with a filter by month.

I have a select box that contains all month from January – December:

<select id="listingFormTime" name="listingFormTime">                            
  <option value=""<?php selected( $time, "" ); ?>><?php _e( "Any Time", "themesdojo" ); ?></option>
  <option value="1"<?php selected( $time, 1 ); ?>><?php _e( "January", "themesdojo" ); ?></option>
  <option value="2"<?php selected( $time, 2 ); ?>><?php _e( "February", "themesdojo" ); ?></option>
  <option value="3"<?php selected( $time, 3 ); ?>><?php _e( "March", "themesdojo" ); ?></option>
 ...
  <option value="12"<?php selected( $time, 12 ); ?>><?php _e( "December", "themesdojo" ); ?></option>
</select>

when selecting a month the corresponding records should be picked from the database and should be displayed. When selecting “March” all events that have their start date in March should be listed, etc.

The necessary event dates are stored in an additional table as “meta_key” and “meta_value”

  • event_start_date –> e.g.: 02/20/2016
  • event_start_time –> e.g.: 3:00 PM
  • event_start_date_number –> e.g.: 1455980400
  • event_end_date –> e.g.: 02/20/2016
  • event_end_time –> e.g.: 7:00 PM
  • event_end_date_number –> e.g.: 1455994800

I found out that I can use DateTime(); and have the option to modify and also use relative formats. So firstly I added the following 12 queries for each month:

if($time == 1) { 

$dt_min = new DateTime('2015-12-31'); // January
$dt_max = clone($dt_min);
$dt_max->modify('+1 month'); 
$end_date = $dt_max->format('m/d/Y'); 

$date = $end_date." 23:59:59"; 
$event_start_date_number = strtotime($date); erzeugen

$time_args = array(
    'key'     => 'event_start_date_number',  
    'value'   => $event_start_date_number, 
    'compare' => '<=',
    'orderby' => 'value',
    'order'   => 'ASC',
);


} elseif($time == 2) {

$dt_min = new DateTime('2016-01-31');  // February
$dt_max = clone($dt_min);
$dt_max->modify('+1 month');
$end_date = $dt_max->format('m/d/Y');

$date = $end_date." 23:59:59";
$event_start_date_number = strtotime($date);

$time_args = array(
    'key'     => 'event_start_date_number', 
    'value'   => $event_start_date_number, 
    'compare' => '<=',
    'orderby' => 'value',
    'order'   => 'ASC',
);

...

} elseif($time == 12) { ...

Then I read that “modify(‘+1 month’);” could lead to problems and found out that my results works perfectly for February but from March on the results aren’t correct any longer.

So I tried to find another solution and tried to use another relative format: $dt_max->modify(‘last day of January 2016’); instead of $dt_max->modify(‘+1 month’);

    if($time == 1) {

$dt_min = new DateTime('2016-01-01'); 
$dt_max = clone($dt_min);
$dt_max->modify('last day of January 2016'); 
$end_date = $dt_max->format('m/d/Y'); 

$date = $end_date." 23:59:59"; 
$event_start_date_number = strtotime($date);

$time_args = array(
    'key'     => 'event_start_date_number',
    'value'   => $event_start_date_number, 
    'compare' => '<=',
    'orderby' => 'value',
    'order'   => 'ASC',
);


} elseif($time == 2) {

$dt_min = new DateTime('2016-02-01');
$dt_max = clone($dt_min);
$dt_max->modify('last day of February 2016');
$end_date = $dt_max->format('m/d/Y');

$date = $end_date." 23:59:59";
$event_start_date_number = strtotime($date);

$time_args = array(
    'key'     => 'event_start_date_number', 
    'value'   => $event_start_date_number, 
    'compare' => '<=',
    'orderby' => 'value',
    'order'   => 'ASC',
);

Unfortunately same result here – February is fine but in March also the February events are shown. In April the events from February AND March are shown. It seems as if the next month’s events are simply added and I do not know why ;-(

I thought when setting the new DateTime() each time to the beginning of the month the duration is limited?!

I am very sorry in case that this is a dumb question – I’m not a developer and have very poor programming skills but willing to learn. Your help and experiences are really appreciated.


After using:

var_dump($dt_min );
var_dump($dt_max );
var_dump($date );
var_dump($end_date );
var_dump($event_start_date_number );

I firstly get results as expected, so I can be sure that the variables are filled with information and datetime is working properly:

$dt_min --> object(DateTime)#5820 (3) { ["date"]=> string(26) "2016-01-01 00:00:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } 
$dt_max --> object(DateTime)#5819 (3) { ["date"]=> string(26) "2016-01-31 00:00:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } 
$date --> string(19) "01/31/2016 23:59:59" 
$end_date --> string(10) "01/31/2016" 
$event_start_date_number  = int(1454284799) // 01. Februar 2016, 00:59:59 UTC+1

But there are two issues that are confusing:

$event_start_date_number = int(1454284799) // 01. Februar 2016, 00:59:59 UTC+1

the generated $event_start_date_number in UNIX Time should be 01/31/2016 23:59:59 in my understanding. But when decoding it there seem to be +1 hour to my timezone (GMT +1 Berlin) in January and from March it differs to +2 hours to my timezone (GMT +2 Berlin) – I guess this is due to Daylight Time, but I will have to consider this to make the correct events show up.

Is there a way to influence the timezone or can I subtract -1 or -2 hours from the Unix timestamp?

The second issue I figured out is:

(...)
$time_args = array(
    'key'     => 'event_start_date_number', 
    'value'   => $event_start_date_number, 
    'compare' => '<=',
    'orderby' => 'value',
    'order'   => 'ASC',
);

Could it be that I am only selecting events which start dates are smaller than the end date I defined? This would explain, why all events from the previous month are always listed -,-

I thought that I will limit the duration for the event selection with

$dt_min = new DateTime('2016-02-01');
$dt_max = clone($dt_min);
$dt_max->modify('last day of February 2016');

But in the array there seem to be no limitation from which starting point the events should be listed.

Is there a way to enhance the array in a way that only events are listed whose event_start_date_number is between $dt_min and dt_max?

Related posts

1 comment

  1. Ok I figured it out by myself

    Is there a way to influence the timezone or can I subtract -1 or -2 hours from the Unix timestamp?

    I did it with a workaround and quick & dirty fix by editing the startdate and time in winter and summer to fix this +1 / +2 hour issue – even if I’m aware that there will be a few days the problem will still occur:

    //WINTER (January, February, March, November, December)
    $dt_min = new DateTime('2015-12-31'); // --> 01.01.2016
    (...) 
    $start = $start_date." 23:00:01"; // --> 00:00:01 (+1 hour)
    (...)
    $end = $end_date." 22:59:59"; // --> 23:59:59 (+1 hour)
    
    //SUMMER (April - October)
    $dt_min = new DateTime('2015-03-31'); // --> 01.04.2016
    (...) 
    $start = $start_date." 22:00:01"; // --> 00:00:01 (+2 hours)
    (...)
    $end = $end_date." 21:59:59"; // --> 23:59:59 (+2 hours)
    

    For the second question I found a better solution with no workaround

    Is there a way to enhance the array in a way that only events are listed whose event_start_date_number is between $dt_min and dt_max?

    } elseif($time == 4) {
    
    $dt_min = new DateTime('2016-03-31');
    $dt_max = clone($dt_min);
    $dt_max->modify('last day of April 2016');
    
    // additionally defined a start date for the range based on $dt_min
    $start_date = $dt_min->format('m/d/Y');
    $start = $start_date." 22:00:01";  
    $start_date_number = strtotime($start);
    
    $end_date = $dt_max->format('m/d/Y');
    $end = $end_date." 21:59:59"; 
    $event_start_date_number = strtotime($end);
    
    // found out that I can have an array in an array ^^ to define the date range
    $time_args = array(
    'key'     => 'event_start_date_number', 
    'value'   => array ($start_date_number, $event_start_date_number),  
    'compare' => 'BETWEEN',
    'orderby' => 'value',
    'order'   => 'ASC',
    );  
    

    For now my problem is “solved” because the correct events are listed when selecting a month.

Comments are closed.