137748cd8SNickeau<?php 237748cd8SNickeau 337748cd8SNickeau 437748cd8SNickeaunamespace ComboStrap; 537748cd8SNickeau 637748cd8SNickeau 737748cd8SNickeauuse DateTime; 837748cd8SNickeau 937748cd8SNickeau 1037748cd8SNickeau/** 1137748cd8SNickeau * Class Is8601Date 1237748cd8SNickeau * @package ComboStrap 1337748cd8SNickeau * Format used by Google, Sqlite and others 141fa8c418SNickeau * 151fa8c418SNickeau * This is the date class of Combostrap 161fa8c418SNickeau * that takes a valid input string 171fa8c418SNickeau * and output an iso string 1837748cd8SNickeau */ 1937748cd8SNickeauclass Iso8601Date 2037748cd8SNickeau{ 211fa8c418SNickeau public const CANONICAL = "date"; 2237748cd8SNickeau /** 2337748cd8SNickeau * @var DateTime|false 2437748cd8SNickeau */ 2537748cd8SNickeau private $dateTime; 2637748cd8SNickeau 271fa8c418SNickeau /** 281fa8c418SNickeau * ATOM = IS08601 291fa8c418SNickeau * See {@link Iso8601Date::getFormat()} for more information 301fa8c418SNickeau */ 311fa8c418SNickeau private const VALID_FORMATS = [ 321fa8c418SNickeau \DateTimeInterface::ATOM, 331fa8c418SNickeau 'Y-m-d H:i:sP', 341fa8c418SNickeau 'Y-m-d H:i:s', 351fa8c418SNickeau 'Y-m-d H:i', 361fa8c418SNickeau 'Y-m-d H', 371fa8c418SNickeau 'Y-m-d', 381fa8c418SNickeau ]; 391fa8c418SNickeau 4037748cd8SNickeau 4137748cd8SNickeau /** 4237748cd8SNickeau * Date constructor. 4337748cd8SNickeau */ 4437748cd8SNickeau public function __construct($dateTime = null) 4537748cd8SNickeau { 4637748cd8SNickeau 4737748cd8SNickeau if ($dateTime == null) { 4837748cd8SNickeau 4937748cd8SNickeau $this->dateTime = new DateTime(); 5037748cd8SNickeau 5137748cd8SNickeau } else { 5237748cd8SNickeau 5337748cd8SNickeau $this->dateTime = $dateTime; 5437748cd8SNickeau 5537748cd8SNickeau } 5637748cd8SNickeau 5737748cd8SNickeau } 5837748cd8SNickeau 59*c3437056SNickeau /** 60*c3437056SNickeau * @param null $dateString 61*c3437056SNickeau * @return Iso8601Date 62*c3437056SNickeau * @throws ExceptionCombo if the format is not supported 63*c3437056SNickeau */ 64*c3437056SNickeau public static function createFromString($dateString = null): Iso8601Date 6537748cd8SNickeau { 661fa8c418SNickeau 671fa8c418SNickeau $original = $dateString; 681fa8c418SNickeau 691fa8c418SNickeau if ($dateString === null) { 7037748cd8SNickeau return new Iso8601Date(); 7137748cd8SNickeau } 7237748cd8SNickeau 7337748cd8SNickeau /** 7437748cd8SNickeau * Time ? 7537748cd8SNickeau * (ie only YYYY-MM-DD) 7637748cd8SNickeau */ 771fa8c418SNickeau if (strlen($dateString) <= 10) { 7837748cd8SNickeau /** 7937748cd8SNickeau * We had the time to 00:00:00 8037748cd8SNickeau * because {@link DateTime::createFromFormat} with a format of 8137748cd8SNickeau * Y-m-d will be using the actual time otherwise 8237748cd8SNickeau * 8337748cd8SNickeau */ 841fa8c418SNickeau $dateString .= "T00:00:00"; 851fa8c418SNickeau } 861fa8c418SNickeau 871fa8c418SNickeau /** 881fa8c418SNickeau * Space as T 891fa8c418SNickeau */ 901fa8c418SNickeau $dateString = str_replace(" ", "T", $dateString); 911fa8c418SNickeau 921fa8c418SNickeau 931fa8c418SNickeau if (strlen($dateString) <= 13) { 941fa8c418SNickeau /** 951fa8c418SNickeau * We had the time to 00:00:00 961fa8c418SNickeau * because {@link DateTime::createFromFormat} with a format of 971fa8c418SNickeau * Y-m-d will be using the actual time otherwise 981fa8c418SNickeau * 991fa8c418SNickeau */ 1001fa8c418SNickeau $dateString .= ":00:00"; 1011fa8c418SNickeau } 1021fa8c418SNickeau 1031fa8c418SNickeau if (strlen($dateString) <= 16) { 1041fa8c418SNickeau /** 1051fa8c418SNickeau * We had the time to 00:00:00 1061fa8c418SNickeau * because {@link DateTime::createFromFormat} with a format of 1071fa8c418SNickeau * Y-m-d will be using the actual time otherwise 1081fa8c418SNickeau * 1091fa8c418SNickeau */ 1101fa8c418SNickeau $dateString .= ":00"; 11137748cd8SNickeau } 11237748cd8SNickeau 11337748cd8SNickeau /** 11437748cd8SNickeau * Timezone 11537748cd8SNickeau */ 1161fa8c418SNickeau if (strlen($dateString) <= 19) { 11737748cd8SNickeau /** 11837748cd8SNickeau * Because this text metadata may be used in other part of the application 11937748cd8SNickeau * We add the timezone to make it whole 12037748cd8SNickeau * And to have a consistent value 12137748cd8SNickeau */ 1221fa8c418SNickeau $dateString .= date('P'); 12337748cd8SNickeau } 12437748cd8SNickeau 1251fa8c418SNickeau 12626a7e0f8Sgerardnico $dateTime = DateTime::createFromFormat(self::getFormat(), $dateString); 1271fa8c418SNickeau if ($dateTime === false) { 128*c3437056SNickeau $message = "The date string ($original) is not in a valid date format. (" . join(", ", self::VALID_FORMATS) . ")"; 129*c3437056SNickeau throw new ExceptionCombo($message, self::CANONICAL); 1301fa8c418SNickeau } 13137748cd8SNickeau return new Iso8601Date($dateTime); 1321fa8c418SNickeau 13337748cd8SNickeau } 13437748cd8SNickeau 1351fa8c418SNickeau public static function createFromTimestamp($timestamp): Iso8601Date 13637748cd8SNickeau { 13737748cd8SNickeau $dateTime = new DateTime(); 13837748cd8SNickeau $dateTime->setTimestamp($timestamp); 13937748cd8SNickeau return new Iso8601Date($dateTime); 14037748cd8SNickeau } 14137748cd8SNickeau 14237748cd8SNickeau /** 14337748cd8SNickeau * And note {@link DATE_ISO8601} 14437748cd8SNickeau * because it's not the compliant IS0-8601 format 14537748cd8SNickeau * as explained here 14637748cd8SNickeau * https://www.php.net/manual/en/class.datetimeinterface.php#datetime.constants.iso8601 14737748cd8SNickeau * ATOM is 14837748cd8SNickeau * 14937748cd8SNickeau * This format is used by Sqlite, Google and is pretty the standard everywhere 15037748cd8SNickeau * https://www.w3.org/TR/NOTE-datetime 15137748cd8SNickeau */ 1521fa8c418SNickeau public static function getFormat(): string 15337748cd8SNickeau { 15437748cd8SNickeau return DATE_ATOM; 15537748cd8SNickeau } 15637748cd8SNickeau 157*c3437056SNickeau public static function isValid($value): bool 158*c3437056SNickeau { 159*c3437056SNickeau $dateObject = Iso8601Date::createFromString($value); 160*c3437056SNickeau return $dateObject->isValidDateEntry(); 161*c3437056SNickeau } 162*c3437056SNickeau 163*c3437056SNickeau public function isValidDateEntry(): bool 16437748cd8SNickeau { 16537748cd8SNickeau if ($this->dateTime !== false) { 16637748cd8SNickeau return true; 16737748cd8SNickeau } else { 16837748cd8SNickeau return false; 16937748cd8SNickeau } 17037748cd8SNickeau } 17137748cd8SNickeau 172*c3437056SNickeau public static function createFromDateTime(DateTime $dateTime): Iso8601Date 173*c3437056SNickeau { 174*c3437056SNickeau return new Iso8601Date($dateTime); 175*c3437056SNickeau } 176*c3437056SNickeau 177*c3437056SNickeau public static function createFromNow(): Iso8601Date 178*c3437056SNickeau { 179*c3437056SNickeau return new Iso8601Date(); 180*c3437056SNickeau } 181*c3437056SNickeau 18237748cd8SNickeau public function getDateTime() 18337748cd8SNickeau { 18437748cd8SNickeau return $this->dateTime; 18537748cd8SNickeau } 18637748cd8SNickeau 18737748cd8SNickeau public function __toString() 18837748cd8SNickeau { 18937748cd8SNickeau return $this->getDateTime()->format(self::getFormat()); 19037748cd8SNickeau } 19137748cd8SNickeau 19237748cd8SNickeau /** 19337748cd8SNickeau * Shortcut to {@link DateTime::format()} 19437748cd8SNickeau * @param $string 19537748cd8SNickeau * @return string 19637748cd8SNickeau * @link https://php.net/manual/en/datetime.format.php 19737748cd8SNickeau */ 1981fa8c418SNickeau public function format($string): string 19937748cd8SNickeau { 20037748cd8SNickeau return $this->getDateTime()->format($string); 20137748cd8SNickeau } 20237748cd8SNickeau 203*c3437056SNickeau public function toString() 204*c3437056SNickeau { 205*c3437056SNickeau return $this->__toString(); 206*c3437056SNickeau } 207*c3437056SNickeau 208*c3437056SNickeau 209*c3437056SNickeau 21037748cd8SNickeau 21137748cd8SNickeau} 212