DateAndOrTime.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <?php
  2. namespace Sabre\VObject\Property\VCard;
  3. use
  4. Sabre\VObject\DateTimeParser,
  5. Sabre\VObject\Property\Text,
  6. Sabre\VObject\Property,
  7. DateTime;
  8. /**
  9. * DateAndOrTime property
  10. *
  11. * This object encodes DATE-AND-OR-TIME values.
  12. *
  13. * @copyright Copyright (C) 2007-2014 fruux GmbH. All rights reserved.
  14. * @author Evert Pot (http://evertpot.com/)
  15. * @license http://sabre.io/license/ Modified BSD License
  16. */
  17. class DateAndOrTime extends Property {
  18. /**
  19. * Field separator
  20. *
  21. * @var null|string
  22. */
  23. public $delimiter = null;
  24. /**
  25. * Returns the type of value.
  26. *
  27. * This corresponds to the VALUE= parameter. Every property also has a
  28. * 'default' valueType.
  29. *
  30. * @return string
  31. */
  32. public function getValueType() {
  33. return "DATE-AND-OR-TIME";
  34. }
  35. /**
  36. * Sets a multi-valued property.
  37. *
  38. * You may also specify DateTime objects here.
  39. *
  40. * @param array $parts
  41. * @return void
  42. */
  43. public function setParts(array $parts) {
  44. if (count($parts)>1) {
  45. throw new \InvalidArgumentException('Only one value allowed');
  46. }
  47. if (isset($parts[0]) && $parts[0] instanceof \DateTime) {
  48. $this->setDateTime($parts[0]);
  49. } else {
  50. parent::setParts($parts);
  51. }
  52. }
  53. /**
  54. * Updates the current value.
  55. *
  56. * This may be either a single, or multiple strings in an array.
  57. *
  58. * Instead of strings, you may also use DateTime here.
  59. *
  60. * @param string|array|\DateTime $value
  61. * @return void
  62. */
  63. public function setValue($value) {
  64. if ($value instanceof \DateTime) {
  65. $this->setDateTime($value);
  66. } else {
  67. parent::setValue($value);
  68. }
  69. }
  70. /**
  71. * Sets the property as a DateTime object.
  72. *
  73. * @param \DateTime $dt
  74. * @return void
  75. */
  76. public function setDateTime(\DateTime $dt) {
  77. $values = array();
  78. $tz = null;
  79. $isUtc = false;
  80. $tz = $dt->getTimeZone();
  81. $isUtc = in_array($tz->getName() , array('UTC', 'GMT', 'Z'));
  82. if ($isUtc) {
  83. $value = $dt->format('Ymd\\THis\\Z');
  84. } else {
  85. // Calculating the offset.
  86. $value = $dt->format('Ymd\\THisO');
  87. }
  88. $this->value = $value;
  89. }
  90. /**
  91. * Returns a date-time value.
  92. *
  93. * Note that if this property contained more than 1 date-time, only the
  94. * first will be returned. To get an array with multiple values, call
  95. * getDateTimes.
  96. *
  97. * If no time was specified, we will always use midnight (in the default
  98. * timezone) as the time.
  99. *
  100. * If parts of the date were omitted, such as the year, we will grab the
  101. * current values for those. So at the time of writing, if the year was
  102. * omitted, we would have filled in 2014.
  103. *
  104. * @return \DateTime
  105. */
  106. public function getDateTime() {
  107. $dts = array();
  108. $now = new DateTime();
  109. $tzFormat = $now->getTimezone()->getOffset($now)===0?'\\Z':'O';
  110. $nowParts = DateTimeParser::parseVCardDateTime($now->format('Ymd\\This' . $tzFormat));
  111. $value = $this->getValue();
  112. $dateParts = DateTimeParser::parseVCardDateTime($this->getValue());
  113. // This sets all the missing parts to the current date/time.
  114. // So if the year was missing for a birthday, we're making it 'this
  115. // year'.
  116. foreach($dateParts as $k=>$v) {
  117. if (is_null($v)) {
  118. $dateParts[$k] = $nowParts[$k];
  119. }
  120. }
  121. return new DateTime("$dateParts[year]-$dateParts[month]-$dateParts[date] $dateParts[hour]:$dateParts[minute]:$dateParts[second] $dateParts[timezone]");
  122. }
  123. /**
  124. * Returns the value, in the format it should be encoded for json.
  125. *
  126. * This method must always return an array.
  127. *
  128. * @return array
  129. */
  130. public function getJsonValue() {
  131. $parts = DateTimeParser::parseVCardDateTime($this->getValue());
  132. $dateStr = '';
  133. // Year
  134. if (!is_null($parts['year'])) {
  135. $dateStr.=$parts['year'];
  136. if (!is_null($parts['month'])) {
  137. // If a year and a month is set, we need to insert a separator
  138. // dash.
  139. $dateStr.='-';
  140. }
  141. } else {
  142. if (!is_null($parts['month']) || !is_null($parts['date'])) {
  143. // Inserting two dashes
  144. $dateStr.='--';
  145. }
  146. }
  147. // Month
  148. if (!is_null($parts['month'])) {
  149. $dateStr.=$parts['month'];
  150. if (isset($parts['date'])) {
  151. // If month and date are set, we need the separator dash.
  152. $dateStr.='-';
  153. }
  154. } else {
  155. if (isset($parts['date'])) {
  156. // If the month is empty, and a date is set, we need a 'empty
  157. // dash'
  158. $dateStr.='-';
  159. }
  160. }
  161. // Date
  162. if (!is_null($parts['date'])) {
  163. $dateStr.=$parts['date'];
  164. }
  165. // Early exit if we don't have a time string.
  166. if (is_null($parts['hour']) && is_null($parts['minute']) && is_null($parts['second'])) {
  167. return array($dateStr);
  168. }
  169. $dateStr.='T';
  170. // Hour
  171. if (!is_null($parts['hour'])) {
  172. $dateStr.=$parts['hour'];
  173. if (!is_null($parts['minute'])) {
  174. $dateStr.=':';
  175. }
  176. } else {
  177. // We know either minute or second _must_ be set, so we insert a
  178. // dash for an empty value.
  179. $dateStr.='-';
  180. }
  181. // Minute
  182. if (!is_null($parts['minute'])) {
  183. $dateStr.=$parts['minute'];
  184. if (!is_null($parts['second'])) {
  185. $dateStr.=':';
  186. }
  187. } else {
  188. if (isset($parts['second'])) {
  189. // Dash for empty minute
  190. $dateStr.='-';
  191. }
  192. }
  193. // Second
  194. if (!is_null($parts['second'])) {
  195. $dateStr.=$parts['second'];
  196. }
  197. // Timezone
  198. if (!is_null($parts['timezone'])) {
  199. $dateStr.=$parts['timezone'];
  200. }
  201. return array($dateStr);
  202. }
  203. /**
  204. * Sets a raw value coming from a mimedir (iCalendar/vCard) file.
  205. *
  206. * This has been 'unfolded', so only 1 line will be passed. Unescaping is
  207. * not yet done, but parameters are not included.
  208. *
  209. * @param string $val
  210. * @return void
  211. */
  212. public function setRawMimeDirValue($val) {
  213. $this->setValue($val);
  214. }
  215. /**
  216. * Returns a raw mime-dir representation of the value.
  217. *
  218. * @return string
  219. */
  220. public function getRawMimeDirValue() {
  221. return implode($this->delimiter, $this->getParts());
  222. }
  223. /**
  224. * Validates the node for correctness.
  225. *
  226. * The following options are supported:
  227. * Node::REPAIR - May attempt to automatically repair the problem.
  228. *
  229. * This method returns an array with detected problems.
  230. * Every element has the following properties:
  231. *
  232. * * level - problem level.
  233. * * message - A human-readable string describing the issue.
  234. * * node - A reference to the problematic node.
  235. *
  236. * The level means:
  237. * 1 - The issue was repaired (only happens if REPAIR was turned on)
  238. * 2 - An inconsequential issue
  239. * 3 - A severe issue.
  240. *
  241. * @param int $options
  242. * @return array
  243. */
  244. public function validate($options = 0) {
  245. $messages = parent::validate($options);
  246. $value = $this->getValue();
  247. try {
  248. DateTimeParser::parseVCardDateTime($value);
  249. } catch (\InvalidArgumentException $e) {
  250. $messages[] = array(
  251. 'level' => 3,
  252. 'message' => 'The supplied value (' . $value . ') is not a correct DATE-AND-OR-TIME property',
  253. 'node' => $this,
  254. );
  255. }
  256. return $messages;
  257. }
  258. }