/** * Creates a new calendar instance with the current time set. * * @param mixed This can be either an AgaviLocale, an AgaviTimeZone or * a string specifying the calendar type. * * @return AgaviCalendar The current timezone instance. * * @author Dominik del Bondio <*****@*****.**> * @since 0.11.0 */ public function createCalendar($type = null) { $locale = $this->getCurrentLocale(); $calendarType = null; $zone = null; $time = null; if ($type instanceof AgaviLocale) { $locale = $type; } elseif ($type instanceof AgaviTimeZone) { $zone = $type; } elseif ($type instanceof DateTime) { $time = $type; } elseif (is_int($type)) { $time = $type * AgaviDateDefinitions::MILLIS_PER_SECOND; } elseif ($type !== null) { $calendarType = $type; } if ($time === null) { $time = AgaviCalendar::getNow(); } if (!$zone) { if ($locale->getLocaleTimeZone()) { $zone = $this->createTimeZone($locale->getLocaleTimeZone()); } } if (!$calendarType) { $calendarType = $locale->getLocaleCalendar(); if (!$calendarType) { $calendarType = AgaviCalendar::GREGORIAN; } } switch ($calendarType) { case AgaviCalendar::GREGORIAN: $c = new AgaviGregorianCalendar($this); break; default: throw new AgaviException('Calendar type ' . $calendarType . ' not supported'); } // Now, reset calendar to default state: if ($zone) { $c->setTimeZone($zone); } if ($time instanceof DateTime) { // FIXME: we can't use $time->getTimezone()->getName() here since that triggers // https://github.com/facebook/hhvm/issues/1777 but luckily using format('e') // works for both php and hhvm $tzName = $time->format('e'); if (preg_match('/^[+-0-9]/', $tzName)) { $tzName = 'GMT' . $tzName; } $c->setTimeZone($this->createTimeZone($tzName)); $dateStr = $time->format('Y z G i s'); list($year, $doy, $hour, $minute, $second) = explode(' ', $dateStr); $c->set(AgaviDateDefinitions::YEAR, $year); $c->set(AgaviDateDefinitions::DAY_OF_YEAR, $doy + 1); $c->set(AgaviDateDefinitions::HOUR_OF_DAY, $hour); $c->set(AgaviDateDefinitions::MINUTE, $minute); $c->set(AgaviDateDefinitions::SECOND, $second); // complete the calendar $c->getAll(); } else { $c->setTime($time); // let the new calendar have the current time. } return $c; }
/** * Sets the GregorianCalendar change date. This is the point when the switch * from Julian dates to Gregorian dates occurred. Default is 00:00:00 local * time, October 15, 1582. Previous to this time and date will be Julian * dates. * * @param float The given Gregorian cutover date. * * @author Dominik del Bondio <*****@*****.**> * @author The ICU Project * @since 0.11.0 */ public function setGregorianChange($date) { $this->fGregorianCutover = $date; // Precompute two internal variables which we use to do the actual // cutover computations. These are the normalized cutover, which is the // midnight at or before the cutover, and the cutover year. The // normalized cutover is in pure date milliseconds; it contains no time // of day or timezone component, and it used to compare against other // pure date values. $cutoverDay = (int) floor($this->fGregorianCutover / AgaviDateDefinitions::MILLIS_PER_DAY); $this->fNormalizedGregorianCutover = $cutoverDay * AgaviDateDefinitions::MILLIS_PER_DAY; // Handle the rare case of numeric overflow. If the user specifies a // change of UDate(Long.MIN_VALUE), in order to get a pure Gregorian // calendar, then the epoch day is -106751991168, which when multiplied // by ONE_DAY gives 9223372036794351616 -- the negative value is too // large for 64 bits, and overflows into a positive value. We correct // this by using the next day, which for all intents is semantically // equivalent. if ($cutoverDay < 0 && $this->fNormalizedGregorianCutover > 0) { $this->fNormalizedGregorianCutover = ($cutoverDay + 1) * AgaviDateDefinitions::MILLIS_PER_DAY; } // Normalize the year so BC values are represented as 0 and negative // values. $cal = new AgaviGregorianCalendar($this->getTimeZone()); $cal->setTime($date); $this->fGregorianCutoverYear = $cal->get(AgaviDateDefinitions::YEAR); if ($cal->get(AgaviDateDefinitions::ERA) == self::BC) { $this->fGregorianCutoverYear = 1 - $this->fGregorianCutoverYear; } $this->fCutoverJulianDay = $cutoverDay; }
/** * Queries if the given date is in daylight savings time in * this time zone. * This method is wasteful since it creates a new AgaviGregorianCalendar and * deletes it each time it is called. * * @param float The given time * * @return bool True if the given date is in daylight savings time, * false, otherwise. * * @author Dominik del Bondio <*****@*****.**> * @author The ICU Project * @since 0.11.0 */ public function inDaylightTime($date) { $cal = new AgaviGregorianCalendar($this); $cal->setTime($date); return $cal->inDaylightTime(); }
/** * Creates a new calendar instance with the current time set. * * @param mixed This can be either an AgaviLocale, an AgaviTimeZone or * a string specifying the calendar type. * * @return AgaviCalendar The current timezone instance. * * @author Dominik del Bondio <*****@*****.**> * @since 0.11.0 */ public function createCalendar($type = null) { $locale = $this->getCurrentLocale(); $calendarType = null; $zone = null; $time = null; if ($type instanceof AgaviLocale) { $locale = $type; } elseif ($type instanceof AgaviTimeZone) { $zone = $type; } elseif ($type instanceof DateTime) { $time = $type; } elseif (is_int($type)) { $time = $type * AgaviDateDefinitions::MILLIS_PER_SECOND; } elseif ($type !== null) { $calendarType = $type; } if ($time === null) { $time = AgaviCalendar::getNow(); } if (!$zone) { if ($locale->getLocaleTimeZone()) { $zone = $this->createTimeZone($locale->getLocaleTimeZone()); } } if (!$calendarType) { $calendarType = $locale->getLocaleCalendar(); if (!$calendarType) { $calendarType = AgaviCalendar::GREGORIAN; } } switch ($calendarType) { case AgaviCalendar::GREGORIAN: $c = new AgaviGregorianCalendar($this); break; default: throw new AgaviException('Calendar type ' . $calendarType . ' not supported'); } // Now, reset calendar to default state: if ($zone) { $c->setTimeZone($zone); } if ($time instanceof DateTime) { $tzName = $time->getTimezone()->getName(); if (version_compare(PHP_VERSION, '5.3', '<')) { // when a datetime object is created with an timezone offset like in '2005-02-21 00:00:00+01:00' // php falsely returns the name of the current default timezone as the name of the datetimes timezone // but luckily timezone abbreviation (T) is GMT name (GMT-0200) of the timezone // to not accidentally report dates which are really in the default timezone the name is explicitly checked if ($tzName == date_default_timezone_get()) { $abbr = $time->format('T'); if (preg_match('/^GMT[+-]\\d{4}$/', $abbr)) { $tzName = $abbr; } } } if (preg_match('/^[+-0-9]/', $tzName)) { $tzName = 'GMT' . $tzName; } $c->setTimeZone($this->createTimeZone($tzName)); $dateStr = $time->format('Y z G i s'); list($year, $doy, $hour, $minute, $second) = explode(' ', $dateStr); $c->set(AgaviDateDefinitions::YEAR, $year); $c->set(AgaviDateDefinitions::DAY_OF_YEAR, $doy + 1); $c->set(AgaviDateDefinitions::HOUR_OF_DAY, $hour); $c->set(AgaviDateDefinitions::MINUTE, $minute); $c->set(AgaviDateDefinitions::SECOND, $second); // complete the calendar $c->getAll(); } else { $c->setTime($time); // let the new calendar have the current time. } return $c; }