3v4l.org

run code in 300+ PHP versions simultaneously
<?php /** * IntlDateTime is an extended version of php 5 DateTime class with integrated * IntlDateFormatter functionality which adds support for multible calendars * and locales provided by ICU project. (needs php >= 5.3.0 with intl extension) * However, this class is not compatible with DateTime class because it uses ICU * pattern syntax for formatting and parsing date strings. * (@link http://userguide.icu-project.org/formatparse/datetime) * * @copyright Copyright 2010, Ali Farhadi (http://farhadi.ir/) * @license GNU General Public License 3.0 (http://www.gnu.org/licenses/gpl.html) */ class IntlDateTime extends DateTime { /** * @var string The current locale in use */ protected $locale; /** * @var string The current calendar in use */ protected $calendar; /** * Creates a new instance of IntlDateTime * * @param mixed $time Unix timestamp or strtotime() compatible string or another DateTime object * @param mixed $timezone DateTimeZone object or timezone identifier as full name (e.g. Asia/Tehran) or abbreviation (e.g. IRDT). * @param string $calendar any calendar supported by ICU (e.g. gregorian, persian, islamic, ...) * @param string $locale any locale supported by ICU * @param string $pattern the date pattern in which $time is formatted. * @return IntlDateTime */ public function __construct($time = null, $timezone = null, $calendar = 'gregorian', $locale = 'en_US', $pattern = null) { if (!isset($timezone)) $timezone = new DateTimeZone(date_default_timezone_get()); elseif (!is_a($timezone, 'DateTimeZone')) $timezone = new DateTimeZone($timezone); parent::__construct(null, $timezone); $this->setLocale($locale); $this->setCalendar($calendar); if (isset($time)) $this->set($time, null, $pattern); } /** * Returns an instance of IntlDateFormatter with specified options. * * @param array $options * @return IntlDateFormatter */ protected function getFormatter($options = array()) { $locale = empty($options['locale']) ? $this->locale : $options['locale']; $calendar = empty($options['calendar']) ? $this->calendar : $options['calendar']; $timezone = empty($options['timezone']) ? $this->getTimezone() : $options['timezone']; if (is_a($timezone, 'DateTimeZone')) $timezone = $timezone->getName(); $pattern = empty($options['pattern']) ? null : $options['pattern']; return new IntlDateFormatter($locale . '@calendar=' . $calendar, IntlDateFormatter::FULL, IntlDateFormatter::FULL, $timezone, $calendar == 'gregorian' ? IntlDateFormatter::GREGORIAN : IntlDateFormatter::TRADITIONAL, $pattern); } /** * Replaces localized digits in $str with latin digits. * * @param string $str * @return string Latinized string */ protected function latinizeDigits($str) { $result = ''; $num = new NumberFormatter($this->locale, NumberFormatter::DECIMAL); preg_match_all('/.[\x80-\xBF]*/', $str, $matches); foreach ($matches[0] as $char) { $pos = 0; $parsedChar = $num->parse($char, NumberFormatter::TYPE_INT32, $pos); $result .= $pos ? $parsedChar : $char; } return $result; } /** * Tries to guess the date pattern in which $time is formatted. * * @param string $time The date string * @return string Detected ICU pattern on success, FALSE otherwise. */ protected function guessPattern($time) { $time = $this->latinizeDigits(trim($time)); $shortDateRegex = '(\d{2,4})(-|\\\\|/)\d{1,2}\2\d{1,2}'; $longDateRegex = '([^\d]*\s)?\d{1,2}(-| )[^-\s\d]+\4(\d{2,4})'; $timeRegex = '\d{1,2}:\d{1,2}(:\d{1,2})?(\s.*)?'; if (preg_match("@^(?:(?:$shortDateRegex)|(?:$longDateRegex))(\s+$timeRegex)?$@", $time, $match)) { if (!empty($match[1])) { $separator = $match[2]; $pattern = strlen($match[1]) == 2 ? 'yy' : 'yyyy'; $pattern .= $separator . 'MM' . $separator . 'dd'; } else { $separator = $match[4]; $pattern = 'dd' . $separator . 'LLL' . $separator; $pattern .= strlen($match[5]) == 2 ? 'yy' : 'yyyy'; if (!empty($match[3])) $pattern = (preg_match('/,\s+$/', $match[3]) ? 'E, ' : 'E ') . $pattern; } if (!empty($match[6])) { $pattern .= !empty($match[8]) ? ' hh:mm' : ' HH:mm'; if (!empty($match[7])) $pattern .= ':ss'; if (!empty($match[8])) $pattern .= ' a'; } return $pattern; } return false; } /** * Sets the locale used by the object. * * @param string $locale * @return IntlDateTime The modified DateTime. */ public function setLocale($locale) { $this->locale = $locale; return $this; } /** * Gets the current locale used by the object. * * @return string */ public function getLocale() { return $this->locale; } /** * Sets the calendar used by the object. * * @param string $calendar * @return IntlDateTime The modified DateTime. */ public function setCalendar($calendar) { $this->calendar = strtolower($calendar); return $this; } /** * Gets the current calendar used by the object. * * @return string */ public function getCalendar() { return $this->calendar; } /** * Overrides the getTimestamp method to support timestamps out of the integer range. * * @return float Unix timestamp representing the date. */ public function getTimestamp() { return floatval(parent::format('U')); } /** * Overrides the setTimestamp method to support timestamps out of the integer range. * * @param float $unixtimestamp Unix timestamp representing the date. * @return IntlDateTime the modified DateTime. */ public function setTimestamp($unixtimestamp) { $diff = $unixtimestamp - $this->getTimestamp(); $days = floor($diff / 86400); $seconds = $diff - $days * 86400; $timezone = $this->getTimezone(); $this->setTimezone('UTC'); parent::modify("$days days $seconds seconds"); $this->setTimezone($timezone); return $this; } /** * Alters object's internal timestamp with a string acceptable by strtotime() or a Unix timestamp or a DateTime object. * * @param mixed $time Unix timestamp or strtotime() compatible string or another DateTime object * @param mixed $timezone DateTimeZone object or timezone identifier as full name (e.g. Asia/Tehran) or abbreviation (e.g. IRDT). * @param string $pattern the date pattern in which $time is formatted. * @return IntlDateTime The modified DateTime. */ public function set($time, $timezone = null, $pattern = null) { if (is_a($time, 'DateTime')) { $time = $time->format('U'); } elseif (!is_numeric($time) || $pattern) { if (!$pattern) { $pattern = $this->guessPattern($time); } if (!$pattern && preg_match('/((?:[+-]?\d+)|next|last|previous)\s*(year|month)s?/i', $time)) { if (isset($timezone)) { $tempTimezone = $this->getTimezone(); $this->setTimezone($timezone); } $this->setTimestamp(time()); $this->modify($time); if (isset($timezone)) { $this->setTimezone($tempTimezone); } return $this; } $timezone = empty($timezone) ? $this->getTimezone() : $timezone; if (is_a($timezone, 'DateTimeZone')) $timezone = $timezone->getName(); $defaultTimezone = @date_default_timezone_get(); date_default_timezone_set($timezone); if ($pattern) { $time = $this->getFormatter(array('timezone' => 'GMT', 'pattern' => $pattern))->parse($time); $time -= date('Z', $time); } else { $time = strtotime($time); } date_default_timezone_set($defaultTimezone); } $this->setTimestamp($time); return $this; } /** * Resets the current date of the object. * * @param integer $year * @param integer $month * @param integer $day * @return IntlDateTime The modified DateTime. */ public function setDate($year, $month, $day) { $this->set("$year/$month/$day ".$this->format('HH:mm:ss'), null, 'yyyy/MM/dd HH:mm:ss'); return $this; } /** * Sets the timezone for the object. * * @param mixed $timezone DateTimeZone object or timezone identifier as full name (e.g. Asia/Tehran) or abbreviation (e.g. IRDT). * @return IntlDateTime The modified DateTime. */ public function setTimezone($timezone) { if (!is_a($timezone, 'DateTimeZone')) $timezone = new DateTimeZone($timezone); parent::setTimezone($timezone); return $this; } /** * Internally used by modify method to calculate calendar-aware modifications * * @param array $matches * @return string An empty string */ protected function modifyCallback($matches) { if (!empty($matches[1])) { parent::modify($matches[1]); } list($y, $m, $d) = explode('-', $this->format('y-M-d')); $change = strtolower($matches[2]); $unit = strtolower($matches[3]); switch ($change) { case "next": $change = 1; break; case "last": case "previous": $change = -1; break; } switch ($unit) { case "month": $m += $change; if ($m > 12) { $y += floor($m/12); $m = $m % 12; } elseif ($m < 1) { $y += ceil($m/12) - 1; $m = $m % 12 + 12; } break; case "year": $y += $change; break; } $this->setDate($y, $m, $d); return ''; } /** * Alter the timestamp by incrementing or decrementing in a format accepted by strtotime(). * * @param string $modify a string in a relative format accepted by strtotime(). * @return IntlDateTime The modified DateTime. */ public function modify($modify) { $modify = $this->latinizeDigits(trim($modify)); $modify = preg_replace_callback('/(.*?)((?:[+-]?\d+)|next|last|previous)\s*(year|month)s?/i', array($this, 'modifyCallback'), $modify); if ($modify) parent::modify($modify); return $this; } /** * Returns date formatted according to given pattern. * * @param string $pattern Date pattern in ICU syntax (@link http://userguide.icu-project.org/formatparse/datetime) * @param mixed $timezone DateTimeZone object or timezone identifier as full name (e.g. Asia/Tehran) or abbreviation (e.g. IRDT). * @return string Formatted date on success or FALSE on failure. */ public function format($pattern, $timezone = null) { if (isset($timezone)) { $tempTimezone = $this->getTimezone(); $this->setTimezone($timezone); } // Timezones DST data in ICU are not as accurate as PHP. // So we get timezone offset from php and pass it to ICU. $result = $this->getFormatter(array( 'timezone' => 'GMT' . (parent::format('Z') ? parent::format('P') : ''), 'pattern' => $pattern ))->format($this->getTimestamp()); if (isset($timezone)) { $this->setTimezone($tempTimezone); } return $result; } /** * Preserve original DateTime::format functionality * * @param string $format Format accepted by date(). * @param mixed $timezone DateTimeZone object or timezone identifier as full name (e.g. Asia/Tehran) or abbreviation (e.g. IRDT). * @return string Formatted date on success or FALSE on failure. */ public function classicFormat($format, $timezone = null) { if (isset($timezone)) { $tempTimezone = $this->getTimezone(); $this->setTimezone($timezone); } $result = parent::format($format); if (isset($timezone)) { $this->setTimezone($tempTimezone); } return $result; } }

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.3.60.0060.00916.63
8.3.50.0070.01022.05
8.3.40.0060.00918.87
8.3.30.0000.01419.09
8.3.20.0040.00420.47
8.3.10.0000.00923.44
8.3.00.0030.00619.07
8.2.180.0130.01018.14
8.2.170.0070.01122.96
8.2.160.0100.00320.60
8.2.150.0040.00424.18
8.2.140.0000.00824.66
8.2.130.0080.00026.16
8.2.120.0030.00619.24
8.2.110.0070.00320.97
8.2.100.0160.00317.64
8.2.90.0080.00018.96
8.2.80.0000.00817.97
8.2.70.0040.00417.62
8.2.60.0030.00717.93
8.2.50.0000.00818.10
8.2.40.0060.00322.15
8.2.30.0070.00018.21
8.2.20.0080.00017.72
8.2.10.0040.00418.06
8.2.00.0040.00417.71
8.1.280.0030.01225.92
8.1.270.0040.00423.84
8.1.260.0000.00926.35
8.1.250.0000.00928.09
8.1.240.0030.00622.66
8.1.230.0030.00917.71
8.1.220.0040.00417.74
8.1.210.0030.00518.77
8.1.200.0060.00317.35
8.1.190.0040.00417.10
8.1.180.0030.00618.10
8.1.170.0050.00318.57
8.1.160.0050.00322.09
8.1.150.0040.00418.75
8.1.140.0040.00417.55
8.1.130.0000.00817.92
8.1.120.0000.00717.40
8.1.110.0020.00517.48
8.1.100.0040.00417.57
8.1.90.0040.00417.58
8.1.80.0040.00417.47
8.1.70.0040.00417.51
8.1.60.0070.00417.52
8.1.50.0030.00517.57
8.1.40.0050.00317.58
8.1.30.0060.00317.71
8.1.20.0000.00917.73
8.1.10.0030.00617.53
8.1.00.0000.00817.36
8.0.300.0040.00418.77
8.0.290.0050.00216.63
8.0.280.0040.00418.52
8.0.270.0040.00417.35
8.0.260.0070.00017.29
8.0.250.0040.00317.03
8.0.240.0030.00617.02
8.0.230.0040.00417.00
8.0.220.0040.00316.84
8.0.210.0000.00816.88
8.0.200.0040.00416.95
8.0.190.0000.00816.98
8.0.180.0030.00516.86
8.0.170.0000.00816.91
8.0.160.0040.00416.87
8.0.150.0000.00816.86
8.0.140.0020.00516.76
8.0.130.0060.00013.31
8.0.120.0000.00816.93
8.0.110.0040.00416.83
8.0.100.0000.00816.98
8.0.90.0040.00416.97
8.0.80.0090.00616.94
8.0.70.0000.00816.87
8.0.60.0000.00816.96
8.0.50.0030.00616.92
8.0.30.0090.00917.08
8.0.20.0150.00817.40
8.0.10.0000.00716.84
8.0.00.0100.00816.80
7.4.330.0030.00315.00
7.4.320.0000.00616.59
7.4.300.0030.00316.68
7.4.290.0040.00416.56
7.4.280.0000.00816.57
7.4.270.0030.00316.62
7.4.260.0050.00516.44
7.4.250.0070.00016.60
7.4.240.0040.00416.50
7.4.230.0040.00416.57
7.4.220.0120.00616.53
7.4.210.0080.00816.57
7.4.200.0040.00416.56
7.4.160.0060.00916.55
7.4.150.0110.00717.40
7.4.140.0070.01517.86
7.4.130.0110.00916.41
7.4.120.0070.01016.61
7.4.110.0110.00716.54
7.4.100.0040.01316.34
7.4.90.0130.00616.40
7.4.80.0190.00319.39
7.4.70.0100.00716.48
7.4.60.0210.00516.61
7.4.50.0000.00916.52
7.4.40.0130.00316.60
7.4.30.0030.01316.54
7.4.00.0030.01415.12
7.3.330.0030.00313.32
7.3.320.0000.00613.19
7.3.310.0030.00516.33
7.3.300.0030.00316.24
7.3.290.0000.01216.32
7.3.280.0090.00816.39
7.3.270.0120.00917.40
7.3.260.0060.01516.49
7.3.250.0110.00916.58
7.3.240.0090.01016.47
7.3.230.0040.01516.41
7.3.210.0050.01816.61
7.3.200.0090.00919.39
7.3.190.0090.01216.45
7.3.180.0130.00316.52
7.3.170.0130.01016.32
7.3.160.0100.00716.47
7.3.120.0070.01114.65
7.3.110.0080.00914.82
7.3.100.0040.01114.72
7.3.90.0000.01014.75
7.3.80.0070.01014.71
7.3.70.0040.00714.75
7.3.60.0070.01014.85
7.3.50.0100.00015.03
7.3.40.0060.00914.52
7.3.30.0060.01014.60
7.3.20.0070.00716.20
7.3.10.0030.01416.30
7.3.00.0060.00616.51
7.2.330.0130.00316.42
7.2.320.0090.00916.71
7.2.310.0070.01016.50
7.2.300.0100.00916.42
7.2.290.0070.01016.44
7.2.250.0130.00315.17
7.2.240.0100.01014.82
7.2.230.0070.01014.93
7.2.220.0090.00314.88
7.2.210.0070.00414.91
7.2.200.0070.01114.73
7.2.190.0080.00614.82
7.2.180.0070.00414.88
7.2.170.0080.00814.83
7.2.60.0040.00716.73
7.1.330.0050.00515.58
7.1.320.0040.00715.41
7.1.310.0030.00615.77
7.1.300.0040.00815.50
7.1.290.0060.00615.32
7.1.280.0070.00715.24
7.1.270.0120.00415.52
7.1.260.0130.00015.55
7.1.200.0070.00715.50
7.1.70.0050.00316.91
7.1.60.0150.00319.70
7.1.50.0090.01316.84
7.1.00.0030.07722.51
7.0.200.0080.00016.73
7.0.140.0100.06322.04
7.0.100.0070.05020.03
7.0.90.0100.04020.01
7.0.80.0000.04720.03
7.0.70.0030.04720.00
7.0.60.0030.04020.04
7.0.50.0070.08020.51
7.0.40.0070.04320.11
7.0.30.0100.06020.17
7.0.20.0070.04320.18
7.0.10.0070.08320.06
7.0.00.0070.08320.08
5.6.280.0070.06721.06
5.6.250.0030.04320.66
5.6.240.0070.04020.71
5.6.230.0130.03720.82
5.6.220.0170.04320.69
5.6.210.0070.04020.66
5.6.200.0130.04721.11
5.6.190.0000.04021.18
5.6.180.0100.08721.21
5.6.170.0170.07721.10
5.6.160.0100.08021.16
5.6.150.0130.07021.01
5.6.140.0030.09321.24
5.6.130.0100.08321.01
5.6.120.0100.05721.09
5.6.110.0070.06321.20
5.6.100.0100.08021.09
5.6.90.0100.08021.22
5.6.80.0100.07320.59
5.6.70.0070.07720.55
5.6.60.0030.08020.46
5.6.50.0070.04320.59
5.6.40.0100.07320.48
5.6.30.0070.07320.45
5.6.20.0030.08020.37
5.6.10.0130.07320.49
5.6.00.0200.06020.54
5.5.380.0100.03020.49
5.5.370.0100.03320.59
5.5.360.0070.04020.48
5.5.350.0030.03720.40
5.5.340.0070.07720.96
5.5.330.0070.03320.98
5.5.320.0100.08320.99
5.5.310.0200.06720.87
5.5.300.0170.05320.98
5.5.290.0200.06720.90
5.5.280.0100.08020.97
5.5.270.0100.05720.90
5.5.260.0070.08320.84
5.5.250.0100.04720.67
5.5.240.0170.06320.29
5.5.230.0200.03320.38
5.5.220.0070.05020.33
5.5.210.0030.04720.34
5.5.200.0100.07720.35
5.5.190.0130.07720.34
5.5.180.0070.05320.19
5.5.160.0030.08020.15
5.5.150.0230.06020.05
5.5.140.0070.08020.34
5.5.130.0100.04320.23
5.5.120.0100.08020.36
5.5.110.0130.07320.22
5.5.100.0070.03720.14
5.5.90.0070.08020.20
5.5.80.0170.04020.14
5.5.70.0130.06720.13
5.5.60.0170.07320.16
5.5.50.0130.06720.15
5.5.40.0100.06020.13
5.5.30.0100.08020.16
5.5.20.0070.07720.12
5.5.10.0030.07020.12
5.5.00.0100.04320.07
5.4.450.0100.06019.36
5.4.440.0030.04319.48
5.4.430.0070.07719.21
5.4.420.0030.08719.37
5.4.410.0070.07719.22
5.4.400.0170.03318.92
5.4.390.0070.04319.16
5.4.380.0170.06718.89
5.4.370.0070.07719.14
5.4.360.0030.07719.04
5.4.350.0170.07019.13
5.4.340.0170.07319.04
5.4.320.0070.07719.13
5.4.310.0100.07019.21
5.4.300.0100.04018.90
5.4.290.0100.07718.88
5.4.280.0070.07318.89
5.4.270.0030.05019.04
5.4.260.0100.06319.04
5.4.250.0100.07718.90
5.4.240.0070.06719.02
5.4.230.0100.05719.04
5.4.220.0000.08719.17
5.4.210.0100.07319.05
5.4.200.0070.07319.20
5.4.190.0070.07318.85
5.4.180.0170.06018.89
5.4.170.0030.08019.03
5.4.160.0130.07319.02
5.4.150.0030.07719.02
5.4.140.0130.06716.41
5.4.130.0070.06716.32
5.4.120.0100.07316.32
5.4.110.0100.07316.52
5.4.100.0070.07716.50
5.4.90.0130.06316.44
5.4.80.0170.06316.38
5.4.70.0070.07716.56
5.4.60.0100.04316.32
5.4.50.0130.06316.46
5.4.40.0130.06316.49
5.4.30.0070.07316.46
5.4.20.0100.07016.53
5.4.10.0070.04016.40
5.4.00.0100.06715.86
5.3.290.0130.07315.70
5.3.280.0070.06315.70
5.3.270.0070.07315.70
5.3.260.0030.08315.70
5.3.250.0100.07715.70
5.3.240.0100.06015.70
5.3.230.0030.04315.70
5.3.220.0170.03315.70
5.3.210.0030.07315.70
5.3.200.0070.06715.70
5.3.190.0130.03715.70
5.3.180.0170.07015.70
5.3.170.0100.06315.70
5.3.160.0070.07015.70
5.3.150.0230.03715.70
5.3.140.0130.07315.70
5.3.130.0070.06715.70
5.3.120.0170.05015.70
5.3.110.0070.05315.70
5.3.100.0100.07315.70
5.3.90.0030.07715.70
5.3.80.0030.04315.70
5.3.70.0070.06715.70
5.3.60.0030.08315.70
5.3.50.0030.07015.70
5.3.40.0030.07715.70
5.3.30.0100.05715.70
5.3.20.0030.07715.70
5.3.10.0000.06315.70
5.3.00.0070.07015.70

preferences:
41.62 ms | 401 KiB | 5 Q