Scott
Scott

Reputation: 3967

PHP - Get start and end date of current date interval

I have as unix timestamps

$now         = strtotime("2013-12-10");
$start_date  = strtotime("2013-01-01");
$end_date    = strtotime("2013-12-31");

The $start date and $end date span a period of time and the $now timestamp sits in the middle of the two.

I also have a variable date interval like so:

$interval = new DateInterval('P1W');
// or
$interval = new DateInterval('P3D');

Given the above how do I get the start and end timestamps of the interval that now sits in? The $now, $start_date, $end_date and the interval will be dynamic.

Example

Lets say I have these parameters:

$start_date = '2013-01-01 00:00:00';
$end_date   = '2013-12-31 23:59:59';
$now        = '2013-12-10 15:45:34';
$interval   = new DateInterval( 'P1W' );

I want to know the start and end date of the interval $now sits in. The output I would expect from the above params is:

$int_start_date = '2013-12-10 00:00:00';
$int_end_date   = '2013-12-16 23:59:59';

Upvotes: 1

Views: 3324

Answers (3)

vascowhite
vascowhite

Reputation: 18440

I think this is a less hacky and cleaner approach than yours.

$start_date    = new DateTime( '2013-01-01 00:00:00' );
$end_date      = new DateTime( '2013-12-31 23:59:59' );
$end_date_ts   = $end_date->getTimestamp();
$now           = new DateTime( '2013-12-10 15:45:34' );
$now_ts        = $now->getTimestamp();
$interval      = new DateInterval( 'P1W' );
$periods        = new DatePeriod( $start_date, $interval, $end_date );

/** @var \DateTime $period */
foreach($periods as $period){
    $periodEnd = clone $period;
    $periodEnd->add($interval);
    if($period < $now && $now < $periodEnd){
        $result = iterator_to_array(new \DatePeriod($period, $interval, $periodEnd->add($interval)));
        $int_start_date = $result[0];
        $int_end_date = $result[1];
        break;
    }
}

/** @var DateTime $int_start_date */
/** @var DateTime $int_end_date */
var_dump( $int_start_date->format( 'Y-m-d H:i:s' ) );
var_dump( $int_end_date->modify( '-1 Second' )->format( 'Y-m-d H:i:s' ) );

Upvotes: 1

Jon
Jon

Reputation: 12992

You could try:

$now = time();
$interval = new DateInterval('P1W');

$interval_seconds = $interval->s + ($interval->i * 60) + ($interval->h * 60 * 60) + ($interval->d * 60 * 60 * 24);
$half_interval = round($interval_seconds / 2);

// Unix timestamps
$interval_start = $now - $half_interval;
$interval_end = $now + $half_interval;

EDIT: 2nd answer following on from comments

This only works for intervals of length 1 - eg 1 week, 1 year etc.

If your interval is > 1 then you'll need to somehow determine how far through the interval you are... e.g for a 2 week interval, are you in the first week or the second week?

$now = time();

$interval = "week";

switch ($interval) {
    case "year":
        $start_int = strtotime(date("Y", $now)."-01-01 00:00:00");
        $end_int = strtotime(date("Y", $now)."-12-31 23:59:59");
    break;
    case "month":
        $start_int = strtotime(date("Y-m", $now)."-01 00:00:00");
        $end_int = strtotime(date("Y-m-t", $now)." 23:59:59");
    break;
    case "week":
        $start_week = date("Y-m-d", strtotime("previous Monday", $now));
        $end_week = date("Y-m-d", strtotime("next Sunday", $now));

        $start_int = strtotime($start_week." 00:00:00");
        $end_int = strtotime($end_week." 23:59:59");
    break;
    case "day":
        $start_int = strtotime(date("Y-m-d", $now)." 00:00:00");
        $end_int = strtotime(date("Y-m-d", $now)." 23:59:59");
    break;
    case "hour":
        $start_int = strtotime(date("Y-m-d H", $now).":00:00");
        $end_int = strtotime(date("Y-m-d H", $now).":59:59");
    break;
    case "minute":
        $start_int = strtotime(date("Y-m-d H:i", $now).":00");
        $end_int = strtotime(date("Y-m-d H:i", $now).":59");
    break;
}
echo date("Y-m-d H:i:s", $start_int), "<br>";
echo date("Y-m-d H:i:s", $end_int), "<br>";

Update 3

I've put the logic from your answer into a single loop:

$start_date    = new DateTime( '2013-01-01 00:00:00' );
$end_date      = new DateTime( '2013-12-31 23:59:59' );
$end_date_ts   = $end_date->getTimestamp();
$now           = new DateTime( '2013-12-10 15:45:34' );
$now_ts        = $now->getTimestamp();
$interval      = new DateInterval( 'P1W' );
$period        = new DatePeriod( $start_date, $interval, $end_date );

$int_start_date = $start_date;
$int_end_date   = $end_date;

foreach ( $period as $dt ) {
    $timestamp = $dt->getTimestamp();

    if ($now_ts >= $timestamp) {
        $int_start_date->setTimestamp($timestamp);
    }
    if ($now_ts < $timestamp and $timestamp < $int_end_date->getTimestamp()) {
        $int_end_date->setTimestamp($timestamp - 1);
    }
}
var_dump( $int_start_date->format( 'Y-m-d H:i:s' ) );
var_dump( $int_end_date->format( 'Y-m-d H:i:s' ) );

Upvotes: 0

Scott
Scott

Reputation: 3967

I have figured the problem myself however is hacky

$start_date    = new DateTime( '2013-01-01 00:00:00' );
$end_date      = new DateTime( '2013-12-31 23:59:59' );
$end_date_ts   = $end_date->getTimestamp();
$now           = new DateTime( '2013-12-10 15:45:34' );
$now_ts        = $now->getTimestamp();
$interval      = new DateInterval( 'P1W' );
$period        = new DatePeriod( $start_date, $interval, $end_date );

$intervals = array();

foreach ( $period as $dt ) {
    $intervals[] = $dt->getTimestamp();
}

$intervals[]    = $end_date_ts;
$int_start_date = new DateTime();
$int_end_date   = new DateTime();

for ( $i = 0; $i < count( $intervals ); $i++ ) {
    if ( $now_ts >= $intervals[$i] && $now_ts <= $intervals[$i+1]) {
        $int_start_date->setTimestamp($intervals[$i]);
        $int_end_date->setTimestamp($intervals[$i+1]-1);
            break;
    }
}

var_dump( $int_start_date->format( 'Y-m-d H:i:s' ) );
var_dump( $int_end_date->format( 'Y-m-d H:i:s' ) );

I gladly accept better approaches if anyone has them.

Upvotes: 0

Related Questions