⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.89
Server IP:
41.128.143.86
Server:
Linux host.raqmix.cloud 6.8.0-1025-azure #30~22.04.1-Ubuntu SMP Wed Mar 12 15:28:20 UTC 2025 x86_64
Server Software:
Apache
PHP Version:
8.3.23
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
psa-pear
/
pear
/
php
/
Horde
/
Timezone
/
Edit File: Rule.php
<?php /** * Class representing a set of "Rule" timezone database entries of the * same name. * * Copyright 2011-2017 Horde LLC (http://www.horde.org/) * * See the enclosed file COPYING for license information (LGPL). If you * did not receive this file, see http://www.horde.org/licenses/lgpl21. * * @author Jan Schneider <jan@horde.org> * @package Timezone */ class Horde_Timezone_Rule { /** * A ruleset name. * * @var string */ protected $_name; /** * All Rule lines for this ruleset. * * @var array */ protected $_rules = array(); /** * List to map weekday descriptions used in the timezone database. * * @var array */ protected $_weekdays = array('Mon' => Horde_Date::DATE_MONDAY, 'Tue' => Horde_Date::DATE_TUESDAY, 'Wed' => Horde_Date::DATE_WEDNESDAY, 'Thu' => Horde_Date::DATE_THURSDAY, 'Fri' => Horde_Date::DATE_FRIDAY, 'Sat' => Horde_Date::DATE_SATURDAY, 'Sun' => Horde_Date::DATE_SUNDAY); /** * Constructor. * * @param string $name A ruleset name. */ public function __construct($name) { $this->_name = $name; } /** * Adds a Rule line to this ruleset. * * @param array $rule A parsed Rule line. */ public function add($rule) { $this->_rules[] = $rule; } /** * Adds rules from this ruleset to a VTIMEZONE component. * * @param Horde_Icalendar_Vtimezone $tz A VTIMEZONE component. * @param string $tzid The timezone ID of the component. * @param string $name A timezone name abbreviation. * May contain a placeholder that is * replaced the Rules' "Letter(s)" * entry. * @param array $startOffset An offset hash describing the * base offset of a timezone. * @param Horde_Date $start Start of the period to add rules * for. * @param Horde_Date $end End of the period to add rules * for. */ public function addRules(Horde_Icalendar_Vtimezone $tz, $tzid, $name, $startOffset, Horde_Date $start, Horde_Date $end = null) { foreach ($this->_rules as $ruleNo => $rule) { // The rule items are: // 0: "Rule" // 1: The rule name // 2: The start year or "minimum" // 3: The end year or "only" if only at the start year or "maximum" // 4: Type, whatever that means (unused) // 5: The start month // 6: The start day, either specific or as a rule // 7: The start time // 8: The offset to the base time // 9: The time name abbreviation $year = $rule[3]; if ($year[0] == 'o') { // TO is "only" $rule[3] = $rule[2]; } if ($rule[3][0] != 'm' && $rule[3] < $start->year) { // TO is not "maximum" and is before the searched period continue; } if ($end && $rule[2][0] != 'm' && $rule[2] > $end->year) { // FROM is not "minimum" and is after the searched period break; } if ($rule[2][0] != 'm' && $rule[2] < $start->year) { $rule[2] = $start->year; } // The month of rule start. $month = Horde_Timezone::getMonth($rule[5]); // The time of rule start. preg_match('/(\d+)(?::(\d+))?(?::(\d+))?([wsguz])?/', $rule[7], $match); $hour = $match[1]; $minute = isset($match[2]) ? $match[2] : 0; if (!isset($match[4])) { $modifier = 'w'; } elseif ($match[4] == 'g' || $match[4] == 'z') { $modifier = 'u'; } else { $modifier = $match[4]; } // Find the start date. $first = $this->_getFirstMatch($rule, $rule[2]); $first->hour = $hour; $first->min = $minute; $previousOffset = $this->_findPreviousOffset( $first, $ruleNo, $startOffset ); if ($rule[8] == 0) { $component = new Horde_Icalendar_Standard(); $component->setAttribute('TZOFFSETFROM', $previousOffset); $component->setAttribute('TZOFFSETTO', $startOffset); } else { $component = new Horde_Icalendar_Daylight(); $component->setAttribute('TZOFFSETFROM', $previousOffset); $component->setAttribute( 'TZOFFSETTO', $this->_getOffset($startOffset, $rule[8]) ); } switch ($modifier) { case 's': $first->hour += ($previousOffset['ahead'] ? 1 : -1) * $previousOffset['hour'] - ($startOffset['ahead'] ? 1 : -1) * $startOffset['hour']; $first->min += ($previousOffset['ahead'] ? 1 : -1) * $previousOffset['minute'] - ($startOffset['ahead'] ? 1 : -1) * $startOffset['minute']; break; case 'u': $first->hour += ($previousOffset['ahead'] ? 1 : -1) * $previousOffset['hour']; $first->min += ($previousOffset['ahead'] ? 1 : -1) * $previousOffset['minute']; break; } $component->setAttribute('DTSTART', $first); // Find the end date. if ($rule[3][0] == 'm') { $until = ''; } else { $last = $this->_getFirstMatch($rule, $rule[3]); $last->hour = $hour; $last->min = $minute; switch ($modifier) { case 's': $last->hour -= ($startOffset['ahead'] ? 1 : -1) * $startOffset['hour']; $last->min -= ($startOffset['ahead'] ? 1 : -1) * $startOffset['minute']; break; case 'w': $last->hour -= ($previousOffset['ahead'] ? 1 : -1) * $previousOffset['hour']; $last->min -= ($previousOffset['ahead'] ? 1 : -1) * $previousOffset['minute']; break; } $until = ';UNTIL=' . $last->format('Ymd\THis') . 'Z'; } if ($rule[2] != $rule[3]) { if (preg_match('/^\d+$/', $rule[6])) { // Rule starts on a specific date. $component->setAttribute( 'RRULE', 'FREQ=YEARLY;BYMONTH=' . $month . ';BYMONTHDAY=' . $rule[6] . $until); } elseif (substr($rule[6], 0, 4) == 'last') { // Rule starts on the last of a certain weekday of the month. $component->setAttribute( 'RRULE', 'FREQ=YEARLY;BYDAY=-1' . Horde_String::upper(substr($rule[6], 4, 2)) . ';BYMONTH=' . $month . $until); } elseif (strpos($rule[6], '>=')) { // Rule starts on a certain weekday after a certain day of // month. list($weekday, $day) = explode('>=', $rule[6]); for ($days = array(), $i = $day, $lastDay = min(Horde_Date_Utils::daysInMonth($month, $rule[2]), $i + 6); $day > 1 && $i <= $lastDay; $i++) { $days[] = $i; } $component->setAttribute( 'RRULE', 'FREQ=YEARLY;BYMONTH=' . $month . ($days ? (';BYMONTHDAY=' . implode(',', $days)) : '') . ';BYDAY=1' . Horde_String::upper(substr($weekday, 0, 2)) . $until); } elseif (strpos($rule[6], '<=')) { // Rule starts on a certain weekday before a certain day of // month. for ($days = array(), $i = 1; $i <= $day; $i++) { $days[] = $i; } $component->setAttribute( 'RRULE', 'FREQ=YEARLY;BYMONTH=' . $month . ';BYMONTHDAY=' . implode(',', $days) . ';BYDAY=-1' . Horde_String::upper(substr($weekday, 0, 2)) . $until); } else { continue; } } $component->setAttribute('TZNAME', sprintf($name, $rule[9])); $tz->addComponent($component); } } /** * Finds a date matching a rule definition. * * @param array $rule A rule definition hash from addRules(). * @param integer $year A year when the rule should be applied. * * @return Horde_Date The first matching date. */ protected function _getFirstMatch($rule, $year) { $month = Horde_Timezone::getMonth($rule[5]); if (preg_match('/^\d+$/', $rule[6])) { // Rule starts on a specific date. $date = new Horde_Date(array( 'year' => $year, 'month' => $month, 'mday' => $rule[6], )); } elseif (substr($rule[6], 0, 4) == 'last') { // Rule starts on the last of a certain weekday of the month. $weekday = $this->_weekdays[substr($rule[6], 4, 3)]; $date = new Horde_Date(array( 'year' => $year, 'month' => $month, 'mday' => Horde_Date_Utils::daysInMonth($month, $rule[2]), )); while ($date->dayOfWeek() != $weekday) { $date->mday--; } } elseif (strpos($rule[6], '>=')) { // Rule starts on a certain weekday after a certain day of month. list($weekday, $day) = explode('>=', $rule[6]); $weekdayInt = $this->_weekdays[substr($weekday, 0, 3)]; $date = new Horde_Date(array( 'year' => $year, 'month' => $month, 'mday' => $day, )); while ($date->dayOfWeek() != $weekdayInt) { $date->mday++; } } elseif (strpos($rule[6], '<=')) { // Rule starts on a certain weekday before a certain day of month. list($weekday, $day) = explode('>=', $rule[6]); $weekdayInt = $this->_weekdays[substr($weekday, 0, 3)]; $date = new Horde_Date(array( 'year' => $year, 'month' => $month, 'mday' => $day, )); while ($date->dayOfWeek() != $weekdayInt) { $date->mday--; } } else { throw new Horde_Timezone_Exception('Cannot parse rule ' . $rule[6]); } return $date; } /** * Finds the offset of a previous rule. * * There may be different potential rules that are "before" the current * one, and there may even be two sequential daylight rules with different * offsets. Thus we go through all earlier rules (as in "before the current * rule in the rule definition", because the rules are ordered by start * date), and find the one that starts the closest to the start date of the * current rule. * * @param Horde_Date $date The start date of the current rule. * @param integer $ruleNo The rule number of the current rule. * @param integer $startOffset The offset to use for the first rule, and * also the default. * * @return integer The offset of the last rule before the current. */ protected function _findPreviousOffset($date, $ruleNo, $startOffset) { // This is the default. $offset = $startOffset; if ($ruleNo == 0) { return $offset; } // Remember the closest found day and year. The year is faster to // calculate, only fall back to days if necessary. For years we compare // the end dates, to quickly rule out any rules that even ended earlier // than the currently closest match. For rules with end dates in the // future we have to go down to the level of days and calculate the // distance of the occurrence in the current year. $diff = $diffYear = null; for ($i = $ruleNo - 1; $i >= 0; $i--) { $end = $this->_rules[$i][3][0] == 'o' ? $this->_rules[$i][2] : $this->_rules[$i][3]; if ($end[0] != 'm') { if (!is_null($diffYear) && ($date->year - $end) > $diffYear) { // We already found a rule that ends closer (by year) continue; } if (is_null($diffYear) || ($date->year - $end) < $diffYear) { // This rule ends closer. $diffYear = $date->year - $end; $diff = $this->_getDiff($i, $date, min($date->year, $end)); $offset = $this->_rules[$i][8] ? $this->_getOffset($startOffset, $this->_rules[$i][8]) : $startOffset; continue; } } // On the same year or with an end in the future, now check days. $year = $date->year; if ($end[0] != 'm') { $year = min($year, $end); } $diffDays = $this->_getDiff($i, $date, $year); if (!is_null($diff) && $diffDays > $diff) { // We already found a rule that ends closer. continue; } if (is_null($diff) || $diffDays < $diff) { // This rule ends closer. $diffYear = $date->year - $year; $diff = $diffDays; $offset = $this->_rules[$i][8] ? $this->_getOffset($startOffset, $this->_rules[$i][8]) : $startOffset; } } return $offset; } protected function _setTime($date, $hour, $minute, $modifier, $utc = false) { } /** * Helper method to calculate the difference in days between a date and the * occurence of rule. * * @param integer $ruleNo A rule number. * @param Horde_Date $date A date. * @param integer $year A year. * * @return integer The days between the date and the rule occurrence in * the year. */ protected function _getDiff($ruleNo, $date, $year) { $ruleDate = $this->_getFirstMatch($this->_rules[$ruleNo], $year); if ($ruleDate->after($date)) { $ruleDate = $this->_getFirstMatch($this->_rules[$ruleNo], $year - 1); } return $date->diff($ruleDate); } /** * Calculates the new offset of a timezone. * * @param array $start A hash describing the original timezone offset. * @param string $new A string describing the offset to be added to (or * subtracted from) the original offset. * * @return array A hash describing the new timezone offset. */ protected function _getOffset($start, $new) { $start = ($start['ahead'] ? 1 : -1) * (60 * $start['hour'] + $start['minute']); preg_match('/(-)?(\d+):(\d+)/', $new, $match); $start += ($match[1] == '-' ? -1 : 1) * (60 * $match[2] + $match[3]); $result = array('ahead' => $start > 0); $start = abs($start); $result['hour'] = floor($start / 60); $result['minute'] = $start % 60; return $result; } }
Simpan