Path: blob/master/src/applications/calendar/parser/data/PhutilCalendarAbsoluteDateTime.php
12262 views
<?php12final class PhutilCalendarAbsoluteDateTime3extends PhutilCalendarDateTime {45private $year;6private $month;7private $day;8private $hour = 0;9private $minute = 0;10private $second = 0;11private $timezone;1213public static function newFromISO8601($value, $timezone = 'UTC') {14$pattern =15'/^'.16'(?P<y>\d{4})(?P<m>\d{2})(?P<d>\d{2})'.17'(?:'.18'T(?P<h>\d{2})(?P<i>\d{2})(?P<s>\d{2})(?<z>Z)?'.19')?'.20'\z/';2122$matches = null;23$ok = preg_match($pattern, $value, $matches);24if (!$ok) {25throw new Exception(26pht(27'Expected ISO8601 datetime in the format "19990105T112233Z", '.28'found "%s".',29$value));30}3132if (isset($matches['z'])) {33if ($timezone != 'UTC') {34throw new Exception(35pht(36'ISO8601 date ends in "Z" indicating UTC, but a timezone other '.37'than UTC ("%s") was specified.',38$timezone));39}40}4142$datetime = id(new self())43->setYear((int)$matches['y'])44->setMonth((int)$matches['m'])45->setDay((int)$matches['d'])46->setTimezone($timezone);4748if (isset($matches['h'])) {49$datetime50->setHour((int)$matches['h'])51->setMinute((int)$matches['i'])52->setSecond((int)$matches['s']);53} else {54$datetime55->setIsAllDay(true);56}5758return $datetime;59}6061public static function newFromEpoch($epoch, $timezone = 'UTC') {62$date = new DateTime('@'.$epoch);6364$zone = new DateTimeZone($timezone);65$date->setTimezone($zone);6667return id(new self())68->setYear((int)$date->format('Y'))69->setMonth((int)$date->format('m'))70->setDay((int)$date->format('d'))71->setHour((int)$date->format('H'))72->setMinute((int)$date->format('i'))73->setSecond((int)$date->format('s'))74->setTimezone($timezone);75}7677public static function newFromDictionary(array $dict) {78static $keys;79if ($keys === null) {80$keys = array_fuse(81array(82'kind',83'year',84'month',85'day',86'hour',87'minute',88'second',89'timezone',90'isAllDay',91));92}9394foreach ($dict as $key => $value) {95if (!isset($keys[$key])) {96throw new Exception(97pht(98'Unexpected key "%s" in datetime dictionary, expected keys: %s.',99$key,100implode(', ', array_keys($keys))));101}102}103104if (idx($dict, 'kind') !== 'absolute') {105throw new Exception(106pht(107'Expected key "%s" with value "%s" in datetime dictionary.',108'kind',109'absolute'));110}111112if (!isset($dict['year'])) {113throw new Exception(114pht(115'Expected key "%s" in datetime dictionary.',116'year'));117}118119$datetime = id(new self())120->setYear(idx($dict, 'year'))121->setMonth(idx($dict, 'month', 1))122->setDay(idx($dict, 'day', 1))123->setHour(idx($dict, 'hour', 0))124->setMinute(idx($dict, 'minute', 0))125->setSecond(idx($dict, 'second', 0))126->setTimezone(idx($dict, 'timezone'))127->setIsAllDay((bool)idx($dict, 'isAllDay', false));128129return $datetime;130}131132public function newRelativeDateTime($duration) {133if (is_string($duration)) {134$duration = PhutilCalendarDuration::newFromISO8601($duration);135}136137if (!($duration instanceof PhutilCalendarDuration)) {138throw new Exception(139pht(140'Expected "PhutilCalendarDuration" object or ISO8601 duration '.141'string.'));142}143144return id(new PhutilCalendarRelativeDateTime())145->setOrigin($this)146->setDuration($duration);147}148149public function toDictionary() {150return array(151'kind' => 'absolute',152'year' => (int)$this->getYear(),153'month' => (int)$this->getMonth(),154'day' => (int)$this->getDay(),155'hour' => (int)$this->getHour(),156'minute' => (int)$this->getMinute(),157'second' => (int)$this->getSecond(),158'timezone' => $this->getTimezone(),159'isAllDay' => (bool)$this->getIsAllDay(),160);161}162163public function setYear($year) {164$this->year = $year;165return $this;166}167168public function getYear() {169return $this->year;170}171172public function setMonth($month) {173$this->month = $month;174return $this;175}176177public function getMonth() {178return $this->month;179}180181public function setDay($day) {182$this->day = $day;183return $this;184}185186public function getDay() {187return $this->day;188}189190public function setHour($hour) {191$this->hour = $hour;192return $this;193}194195public function getHour() {196return $this->hour;197}198199public function setMinute($minute) {200$this->minute = $minute;201return $this;202}203204public function getMinute() {205return $this->minute;206}207208public function setSecond($second) {209$this->second = $second;210return $this;211}212213public function getSecond() {214return $this->second;215}216217public function setTimezone($timezone) {218$this->timezone = $timezone;219return $this;220}221222public function getTimezone() {223return $this->timezone;224}225226private function getEffectiveTimezone() {227$date_timezone = $this->getTimezone();228$viewer_timezone = $this->getViewerTimezone();229230// Because all-day events are always "floating", the effective timezone231// is the viewer timezone if it is available. Otherwise, we'll return a232// DateTime object with the correct values, but it will be incorrectly233// adjusted forward or backward to the viewer's zone later.234235$zones = array();236if ($this->getIsAllDay()) {237$zones[] = $viewer_timezone;238$zones[] = $date_timezone;239} else {240$zones[] = $date_timezone;241$zones[] = $viewer_timezone;242}243$zones = array_filter($zones);244245if (!$zones) {246throw new Exception(247pht(248'Datetime has no timezone or viewer timezone.'));249}250251return head($zones);252}253254public function newPHPDateTimeZone() {255$zone = $this->getEffectiveTimezone();256return new DateTimeZone($zone);257}258259public function newPHPDateTime() {260$zone = $this->newPHPDateTimeZone();261262$y = $this->getYear();263$m = $this->getMonth();264$d = $this->getDay();265266if ($this->getIsAllDay()) {267$h = 0;268$i = 0;269$s = 0;270} else {271$h = $this->getHour();272$i = $this->getMinute();273$s = $this->getSecond();274}275276$format = sprintf('%04d-%02d-%02d %02d:%02d:%02d', $y, $m, $d, $h, $i, $s);277278return new DateTime($format, $zone);279}280281282public function newAbsoluteDateTime() {283return clone $this;284}285286}287288289