1<?php 2 3 4namespace ComboStrap; 5 6 7use DateTime; 8 9 10/** 11 * Class Is8601Date 12 * @package ComboStrap 13 * Format used by Google, Sqlite and others 14 * 15 * This is the date class of Combostrap 16 * that takes a valid input string 17 * and output an iso string 18 */ 19class Iso8601Date 20{ 21 public const CANONICAL = "date"; 22 /** 23 * @var DateTime|false 24 */ 25 private $dateTime; 26 27 /** 28 * ATOM = IS08601 29 * See {@link Iso8601Date::getFormat()} for more information 30 */ 31 private const VALID_FORMATS = [ 32 \DateTimeInterface::ATOM, 33 'Y-m-d H:i:sP', 34 'Y-m-d H:i:s', 35 'Y-m-d H:i', 36 'Y-m-d H', 37 'Y-m-d', 38 ]; 39 40 41 /** 42 * Date constructor. 43 */ 44 public function __construct($dateTime = null) 45 { 46 47 if ($dateTime == null) { 48 49 $this->dateTime = new DateTime(); 50 51 } else { 52 53 $this->dateTime = $dateTime; 54 55 } 56 57 } 58 59 public static function create($dateString = null): Iso8601Date 60 { 61 62 $original = $dateString; 63 64 if ($dateString === null) { 65 return new Iso8601Date(); 66 } 67 68 /** 69 * Time ? 70 * (ie only YYYY-MM-DD) 71 */ 72 if (strlen($dateString) <= 10) { 73 /** 74 * We had the time to 00:00:00 75 * because {@link DateTime::createFromFormat} with a format of 76 * Y-m-d will be using the actual time otherwise 77 * 78 */ 79 $dateString .= "T00:00:00"; 80 } 81 82 /** 83 * Space as T 84 */ 85 $dateString = str_replace(" ", "T", $dateString); 86 87 88 if (strlen($dateString) <= 13) { 89 /** 90 * We had the time to 00:00:00 91 * because {@link DateTime::createFromFormat} with a format of 92 * Y-m-d will be using the actual time otherwise 93 * 94 */ 95 $dateString .= ":00:00"; 96 } 97 98 if (strlen($dateString) <= 16) { 99 /** 100 * We had the time to 00:00:00 101 * because {@link DateTime::createFromFormat} with a format of 102 * Y-m-d will be using the actual time otherwise 103 * 104 */ 105 $dateString .= ":00"; 106 } 107 108 /** 109 * Timezone 110 */ 111 if (strlen($dateString) <= 19) { 112 /** 113 * Because this text metadata may be used in other part of the application 114 * We add the timezone to make it whole 115 * And to have a consistent value 116 */ 117 $dateString .= date('P'); 118 } 119 120 121 $dateTime = DateTime::createFromFormat(DateTime::ATOM, $dateString); 122 if ($dateTime === false) { 123 throw new \RuntimeException("The date string ($original) is not one of the valid date format. " . join(", ", self::VALID_FORMATS)); 124 } 125 return new Iso8601Date($dateTime); 126 127 } 128 129 public static function createFromTimestamp($timestamp): Iso8601Date 130 { 131 $dateTime = new DateTime(); 132 $dateTime->setTimestamp($timestamp); 133 return new Iso8601Date($dateTime); 134 } 135 136 /** 137 * And note {@link DATE_ISO8601} 138 * because it's not the compliant IS0-8601 format 139 * as explained here 140 * https://www.php.net/manual/en/class.datetimeinterface.php#datetime.constants.iso8601 141 * ATOM is 142 * 143 * This format is used by Sqlite, Google and is pretty the standard everywhere 144 * https://www.w3.org/TR/NOTE-datetime 145 */ 146 public static function getFormat(): string 147 { 148 return DATE_ATOM; 149 } 150 151 public function isValidDateEntry() 152 { 153 if ($this->dateTime !== false) { 154 return true; 155 } else { 156 return false; 157 } 158 } 159 160 public function getDateTime() 161 { 162 return $this->dateTime; 163 } 164 165 public function __toString() 166 { 167 return $this->getDateTime()->format(self::getFormat()); 168 } 169 170 /** 171 * Shortcut to {@link DateTime::format()} 172 * @param $string 173 * @return string 174 * @link https://php.net/manual/en/datetime.format.php 175 */ 176 public function format($string): string 177 { 178 return $this->getDateTime()->format($string); 179 } 180 181 182} 183