/** * AgaviTimeZone API. * * @see AgaviTimeZone::useDaylightTime() * * @author Dominik del Bondio <*****@*****.**> * @author The ICU Project * @since 0.11.0 */ public function useDaylightTime() { // If DST was observed in 1942 (for example) but has never been // observed from 1943 to the present, most clients will expect // this method to return FALSE. This method determines whether // DST is in use in the current year (at any point in the year) // and returns TRUE if so. $days = floor(AgaviCalendar::getNow() / AgaviDateDefinitions::MILLIS_PER_DAY); // epoch days $year = 0; $month = 0; $dom = 0; $dow = 0; AgaviCalendarGrego::dayToFields($days, $year, $month, $dom, $dow); if ($year > $this->finalYear) { // [sic] >, not >=; see above if ($this->finalZone) { return $this->finalZone->useDaylightTime(); } else { return true; } } // Find start of this year, and start of next year $start = (int) AgaviCalendarGrego::fieldsToDay($year, 0, 1) * AgaviDateDefinitions::SECONDS_PER_DAY; $limit = (int) AgaviCalendarGrego::fieldsToDay($year + 1, 0, 1) * AgaviDateDefinitions::SECONDS_PER_DAY; // Return TRUE if DST is observed at any time during the current year. for ($i = 0, $transitionCount = count($this->transitions); $i < $transitionCount; ++$i) { if ($this->transitions[$i]['time'] >= $limit) { break; } if ($this->transitions[$i]['time'] >= $start && $this->types[$this->transitions[$i]['type']]['dstOffset'] != 0 || $this->transitions[$i]['time'] > $start && $i > 0 && $this->types[$this->transitions[$i - 1]['type']]['dstOffset'] != 0) { return true; } } return false; }
/** * 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; }
public function testJD() { $kEpochStartAsJulianDay = 2440588; $cal = $this->tm->createCalendar(); $cal->setTimeZone(AgaviTimeZone::getGMT($this->tm)); $cal->clear(); $jd = $cal->get(AgaviDateDefinitions::JULIAN_DAY); $this->assertEquals($kEpochStartAsJulianDay, (int) $jd); $cal->setTime(AgaviCalendar::getNow()); $cal->clear(); $cal->set(AgaviDateDefinitions::JULIAN_DAY, $kEpochStartAsJulianDay); $epochTime = $cal->getTime(); $this->assertEquals(0, (int) $epochTime); }
/** * Initializes the 100-year window that dates with 2-digit years are * considered to fall within so that its start date is 80 years before the * current time. * * @author Dominik del Bondio <*****@*****.**> * @author The ICU Project * @since 0.11.0 */ private static function initializeSystemDefaultCentury() { // initialize systemDefaultCentury and systemDefaultCenturyYear based // on the current time. They'll be set to 80 years before // the current time. // No point in locking as it should be idempotent. if (self::$fgSystemDefaultCenturyStart == self::$fgSystemDefaultCentury) { $calendar = new GregorianCalendar(); $calendar->setTime(AgaviCalendar::getNow()); $calendar->add(AgaviDateDefinitions::YEAR, -80); $newStart = $calendar->getTime(); $newYear = $calendar->get(AgaviDateDefinitions::YEAR); self::$fgSystemDefaultCenturyStart = $newStart; self::$fgSystemDefaultCenturyStartYear = $newYear; } }
/** * 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; }