Last active
November 26, 2018 18:34
-
-
Save schuhwerk/42af93c9f10121455a30ba52e633c40d to your computer and use it in GitHub Desktop.
first draft of endlessly recurring datespans optimised for querying...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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