Skip to content

Instantly share code, notes, and snippets.

@schuhwerk
Last active November 26, 2018 18:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save schuhwerk/42af93c9f10121455a30ba52e633c40d to your computer and use it in GitHub Desktop.
Save schuhwerk/42af93c9f10121455a30ba52e633c40d to your computer and use it in GitHub Desktop.
first draft of endlessly recurring datespans optimised for querying...
<?php
namespace Spaces;
require dirname( __DIR__ ) . '/vendor/autoload.php';
/**
* @see https://github.com/smhg/date-timespan-php
*/
use Timespan\Timespan;
use ArrayObject;
use DateTime;
use DateTimeZone;
/**
* The plan:
* We have a set of repeating datespans ( never ending recurring, with a name and a type ) in our db.
* - this can create "current timespans" start a date (or a timespan?)
* - it can create the next/previous timestamp (of a type like "semester")
* - pass it a timespan and it checks if the timespan has a name!
* - decision: a blog/space can only have a single timespan.
*/
/**
* Endlessly yearly recurring Datespans.
* Defined by a start and an end date (not really, just month and day).
*/
class Yearly_Datespan_Collection extends ArrayObject {
/**
* Undocumented variable
*
* @var Yearly_Datespan[] $datespans
*/
public $datespans;
public function __construct( array $yearly_datespans ) {
$this->datespans = $yearly_datespans;
}
public function get_containing( DateTime $date, $type = 'any' ) {
$overlapping = array();
foreach ( $this->datespans as $datespan ) {
if ( $datespan->contains( $date ) && $datespan->has_type( $type ) ) {
$overlapping[] = $datespan;
}
}
return new Yearly_Datespan_Collection( $overlapping );
}
public function get_overlapping( Timespan $timespan ) {
}
/**
* Check if a
*
* @param Timespan $timespan
* @return void
*/
public function get_name_type( Timespan $timespan ) {
}
}
$ydate = Yearly_Date::createFromFormat( 'd.m', '25.02' );
$ds_collection = new Yearly_Datespan_Collection(
[
new Yearly_Datespan(
Yearly_Date::createFromFormat( 'd.m', '15.07' ), // start
Yearly_Date::createFromFormat( 'd.m', '04.02' ), // end
'Wintersemester',
'Semester'
),
],
[
new Yearly_Datespan(
Yearly_Date::createFromFormat( 'd.m', '5.2' ), // start
Yearly_Date::createFromFormat( 'd.m', '14.7' ), // end
'Summersemester',
'Semester'
),
]
);
$overlapping = $ds_collection->get_containing( new DateTime(), 'semester' );
print_r( $overlapping->datespans[0]->cast_to_year( new DateTime() ) );
/**
* Contains a recurring Datestpan with no Beginning an no End.
* We can't extend the Timespan object, because of the $over_years.
*
* @todo this can't do datespans longer than a year.
* @todo feed date-object, just keep month and day (loose the year).
*
* - the beauty if compareable date-objects.
*/
class Yearly_Datespan {
/**
* Undocumented variable
*
* @var Yearly_Date
*/
private $start;
/**
* Undocumented variable
*
* @var Yearly_Date
*/
private $end;
private $name;
private $type;
private $over_years = false;
public function __construct( Yearly_Date $start, Yearly_Date $end, $name, $type = '' ) {
$this->start = $start;
$this->end = $end;
$this->name = $name;
$this->type = $type;
$this->check_over_years();
}
private function check_over_years() {
if ( $this->end < $this->start ) {
$this->over_years = true;
}
}
/**
* Check if the current Datespan instance has a certain type.
* (case insensitive matching)
* Pass 'any' to match any type.
*
* @param string $type
* @return boolean
*/
public function has_type( string $type ) {
if ( 'any' == $type ) {
return true;
}
if ( strcasecmp( $this->type, $type ) == 0 ) {
return true;
}
return false;
}
public function overlaps() {
/** either a specific Timespan or a yearly datespan */
}
public function cast_to_year( DateTime $date ) {
/** there is a special case if over_year is true */
$year = (int) $date->format( 'Y' );
$contains = $this->contains( $date );
if ( $contains === 0 ) {
return false;
}
if ( $contains === 1 ) {
return new Timespan(
new DateTime( $this->start->to_year( $year ) ),
new DateTime( $this->end->to_year( $year ) )
);
} elseif ( $contains === 2 ) {
return new Timespan(
new DateTime( $this->start->to_year( $year - 1 ) ),
new DateTime( $this->end->to_year( $year ) )
);
} elseif ( $contains === 3 ) {
return new Timespan(
new DateTime( $this->start->to_year( $year ) ),
new DateTime( $this->end->to_year( $year + 1 ) )
);
}
}
/**
* Returns bigger 0 if the datespan contains $date otherwise 0.
*
* A special case: if the datespan overlaps year borders:
* returns 2 if it matches after the end-date.
* returns 3 if it matches before the beginning of the start-date.
*
* @param DateTime $date
* @return int
*/
public function contains( DateTime $date ) {
$compare = Yearly_Date::createFromDate( $date );
$after_start = ( $this->start <= $compare ) ? true : false;
$before_end = ( $compare <= $this->end ) ? true : false;
$inside = ( $after_start && $before_end ) ? true : false;
if ( $this->over_years ) {
if ( $inside ) {
return 0;
}
return ( $after_start ) ? 3 : 2;
} else {
/** The default case: not overlapping years. */
return ( $inside ) ? 1 : 0;
}
}
}
class Yearly_Date extends DateTime {
public function __construct( $time = 'now', $timezone = 'UTC' ) {
parent::__construct( $time, new DateTimeZone( $timezone ) );
$this->modify( self::get_clean_timestring( $this ) );
}
public static function get_clean_timestring( DateTime $date ) {
$month_day = $date->format( 'm-d' );
return "0000-$month_day 00:00:00";
}
public function set_month( $m ) {
$this->modify( $this->format( "Y-$m-d 00:00:00" ) );
}
public function set_day( $d ) {
$this->modify( $this->format( "Y-m-$d 00:00:00" ) );
}
public static function createFromFormat( $format, $time, $timezone = 'UTC' ) {
$instance = parent::createFromFormat( $format, $time, new DateTimeZone( $timezone ) );
return new Yearly_Date( self::get_clean_timestring( $instance ) );
}
public static function createFromDate( DateTime $date ) {
return new Yearly_Date( self::get_clean_timestring( $date ) );
}
/**
* Undocumented function
*
* @param int|string $year
* @return void
* @todo rename!
* @see http://php.net/manual/en/datetime.createfromformat.php
*/
public function to_year( $year ) {
return $this->format( "$year-m-d 00:00:00" );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment