+ */
+class MercurialProcessor implements ProcessorInterface
+{
+ private $level;
+ private static $cache;
+
+ public function __construct($level = Logger::DEBUG)
+ {
+ $this->level = Logger::toMonologLevel($level);
+ }
+
+ /**
+ * @param array $record
+ * @return array
+ */
+ public function __invoke(array $record)
+ {
+ // return if the level is not high enough
+ if ($record['level'] < $this->level) {
+ return $record;
+ }
+
+ $record['extra']['hg'] = self::getMercurialInfo();
+
+ return $record;
+ }
+
+ private static function getMercurialInfo()
+ {
+ if (self::$cache) {
+ return self::$cache;
+ }
+
+ $result = explode(' ', trim(`hg id -nb`));
+ if (count($result) >= 3) {
+ return self::$cache = array(
+ 'branch' => $result[1],
+ 'revision' => $result[2],
+ );
+ }
+
+ return self::$cache = array();
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php
new file mode 100644
index 000000000..66b80fbbd
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+/**
+ * Adds value of getmypid into records
+ *
+ * @author Andreas Hörnicke
+ */
+class ProcessIdProcessor implements ProcessorInterface
+{
+ /**
+ * @param array $record
+ * @return array
+ */
+ public function __invoke(array $record)
+ {
+ $record['extra']['process_id'] = getmypid();
+
+ return $record;
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php b/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php
new file mode 100644
index 000000000..7e64d4dfa
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+/**
+ * An optional interface to allow labelling Monolog processors.
+ *
+ * @author Nicolas Grekas
+ */
+interface ProcessorInterface
+{
+ /**
+ * @return array The processed records
+ */
+ public function __invoke(array $records);
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php
new file mode 100644
index 000000000..a318af7e4
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php
@@ -0,0 +1,81 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+use Monolog\Utils;
+
+/**
+ * Processes a record's message according to PSR-3 rules
+ *
+ * It replaces {foo} with the value from $context['foo']
+ *
+ * @author Jordi Boggiano
+ */
+class PsrLogMessageProcessor implements ProcessorInterface
+{
+ const SIMPLE_DATE = "Y-m-d\TH:i:s.uP";
+
+ /** @var string|null */
+ private $dateFormat;
+
+ /** @var bool */
+ private $removeUsedContextFields;
+
+ /**
+ * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format
+ * @param bool $removeUsedContextFields If set to true the fields interpolated into message gets unset
+ */
+ public function __construct($dateFormat = null, $removeUsedContextFields = false)
+ {
+ $this->dateFormat = $dateFormat;
+ $this->removeUsedContextFields = $removeUsedContextFields;
+ }
+
+ /**
+ * @param array $record
+ * @return array
+ */
+ public function __invoke(array $record)
+ {
+ if (false === strpos($record['message'], '{')) {
+ return $record;
+ }
+
+ $replacements = array();
+ foreach ($record['context'] as $key => $val) {
+ $placeholder = '{' . $key . '}';
+ if (strpos($record['message'], $placeholder) === false) {
+ continue;
+ }
+
+ if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) {
+ $replacements[$placeholder] = $val;
+ } elseif ($val instanceof \DateTime) {
+ $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE);
+ } elseif (is_object($val)) {
+ $replacements[$placeholder] = '[object '.Utils::getClass($val).']';
+ } elseif (is_array($val)) {
+ $replacements[$placeholder] = 'array'.Utils::jsonEncode($val, null, true);
+ } else {
+ $replacements[$placeholder] = '['.gettype($val).']';
+ }
+
+ if ($this->removeUsedContextFields) {
+ unset($record['context'][$key]);
+ }
+ }
+
+ $record['message'] = strtr($record['message'], $replacements);
+
+ return $record;
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php
new file mode 100644
index 000000000..615a4d991
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php
@@ -0,0 +1,44 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+/**
+ * Adds a tags array into record
+ *
+ * @author Martijn Riemers
+ */
+class TagProcessor implements ProcessorInterface
+{
+ private $tags;
+
+ public function __construct(array $tags = array())
+ {
+ $this->setTags($tags);
+ }
+
+ public function addTags(array $tags = array())
+ {
+ $this->tags = array_merge($this->tags, $tags);
+ }
+
+ public function setTags(array $tags = array())
+ {
+ $this->tags = $tags;
+ }
+
+ public function __invoke(array $record)
+ {
+ $record['extra']['tags'] = $this->tags;
+
+ return $record;
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php
new file mode 100644
index 000000000..d1f708cf2
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php
@@ -0,0 +1,59 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+use Monolog\ResettableInterface;
+
+/**
+ * Adds a unique identifier into records
+ *
+ * @author Simon Mönch
+ */
+class UidProcessor implements ProcessorInterface, ResettableInterface
+{
+ private $uid;
+
+ public function __construct($length = 7)
+ {
+ if (!is_int($length) || $length > 32 || $length < 1) {
+ throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
+ }
+
+
+ $this->uid = $this->generateUid($length);
+ }
+
+ public function __invoke(array $record)
+ {
+ $record['extra']['uid'] = $this->uid;
+
+ return $record;
+ }
+
+ /**
+ * @return string
+ */
+ public function getUid()
+ {
+ return $this->uid;
+ }
+
+ public function reset()
+ {
+ $this->uid = $this->generateUid(strlen($this->uid));
+ }
+
+ private function generateUid($length)
+ {
+ return substr(hash('md5', uniqid('', true)), 0, $length);
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php
new file mode 100644
index 000000000..2e8dfae1b
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php
@@ -0,0 +1,113 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+/**
+ * Injects url/method and remote IP of the current web request in all records
+ *
+ * @author Jordi Boggiano
+ */
+class WebProcessor implements ProcessorInterface
+{
+ /**
+ * @var array|\ArrayAccess
+ */
+ protected $serverData;
+
+ /**
+ * Default fields
+ *
+ * Array is structured as [key in record.extra => key in $serverData]
+ *
+ * @var array
+ */
+ protected $extraFields = array(
+ 'url' => 'REQUEST_URI',
+ 'ip' => 'REMOTE_ADDR',
+ 'http_method' => 'REQUEST_METHOD',
+ 'server' => 'SERVER_NAME',
+ 'referrer' => 'HTTP_REFERER',
+ );
+
+ /**
+ * @param array|\ArrayAccess $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data
+ * @param array|null $extraFields Field names and the related key inside $serverData to be added. If not provided it defaults to: url, ip, http_method, server, referrer
+ */
+ public function __construct($serverData = null, array $extraFields = null)
+ {
+ if (null === $serverData) {
+ $this->serverData = &$_SERVER;
+ } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) {
+ $this->serverData = $serverData;
+ } else {
+ throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.');
+ }
+
+ if (isset($this->serverData['UNIQUE_ID'])) {
+ $this->extraFields['unique_id'] = 'UNIQUE_ID';
+ }
+
+ if (null !== $extraFields) {
+ if (isset($extraFields[0])) {
+ foreach (array_keys($this->extraFields) as $fieldName) {
+ if (!in_array($fieldName, $extraFields)) {
+ unset($this->extraFields[$fieldName]);
+ }
+ }
+ } else {
+ $this->extraFields = $extraFields;
+ }
+ }
+ }
+
+ /**
+ * @param array $record
+ * @return array
+ */
+ public function __invoke(array $record)
+ {
+ // skip processing if for some reason request data
+ // is not present (CLI or wonky SAPIs)
+ if (!isset($this->serverData['REQUEST_URI'])) {
+ return $record;
+ }
+
+ $record['extra'] = $this->appendExtraFields($record['extra']);
+
+ return $record;
+ }
+
+ /**
+ * @param string $extraName
+ * @param string $serverName
+ * @return $this
+ */
+ public function addExtraField($extraName, $serverName)
+ {
+ $this->extraFields[$extraName] = $serverName;
+
+ return $this;
+ }
+
+ /**
+ * @param array $extra
+ * @return array
+ */
+ private function appendExtraFields(array $extra)
+ {
+ foreach ($this->extraFields as $extraName => $serverName) {
+ $extra[$extraName] = isset($this->serverData[$serverName]) ? $this->serverData[$serverName] : null;
+ }
+
+ return $extra;
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Registry.php b/vendor/monolog/monolog/src/Monolog/Registry.php
new file mode 100644
index 000000000..159b751cd
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Registry.php
@@ -0,0 +1,134 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+use InvalidArgumentException;
+
+/**
+ * Monolog log registry
+ *
+ * Allows to get `Logger` instances in the global scope
+ * via static method calls on this class.
+ *
+ *
+ * $application = new Monolog\Logger('application');
+ * $api = new Monolog\Logger('api');
+ *
+ * Monolog\Registry::addLogger($application);
+ * Monolog\Registry::addLogger($api);
+ *
+ * function testLogger()
+ * {
+ * Monolog\Registry::api()->addError('Sent to $api Logger instance');
+ * Monolog\Registry::application()->addError('Sent to $application Logger instance');
+ * }
+ *
+ *
+ * @author Tomas Tatarko
+ */
+class Registry
+{
+ /**
+ * List of all loggers in the registry (by named indexes)
+ *
+ * @var Logger[]
+ */
+ private static $loggers = array();
+
+ /**
+ * Adds new logging channel to the registry
+ *
+ * @param Logger $logger Instance of the logging channel
+ * @param string|null $name Name of the logging channel ($logger->getName() by default)
+ * @param bool $overwrite Overwrite instance in the registry if the given name already exists?
+ * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists
+ */
+ public static function addLogger(Logger $logger, $name = null, $overwrite = false)
+ {
+ $name = $name ?: $logger->getName();
+
+ if (isset(self::$loggers[$name]) && !$overwrite) {
+ throw new InvalidArgumentException('Logger with the given name already exists');
+ }
+
+ self::$loggers[$name] = $logger;
+ }
+
+ /**
+ * Checks if such logging channel exists by name or instance
+ *
+ * @param string|Logger $logger Name or logger instance
+ */
+ public static function hasLogger($logger)
+ {
+ if ($logger instanceof Logger) {
+ $index = array_search($logger, self::$loggers, true);
+
+ return false !== $index;
+ } else {
+ return isset(self::$loggers[$logger]);
+ }
+ }
+
+ /**
+ * Removes instance from registry by name or instance
+ *
+ * @param string|Logger $logger Name or logger instance
+ */
+ public static function removeLogger($logger)
+ {
+ if ($logger instanceof Logger) {
+ if (false !== ($idx = array_search($logger, self::$loggers, true))) {
+ unset(self::$loggers[$idx]);
+ }
+ } else {
+ unset(self::$loggers[$logger]);
+ }
+ }
+
+ /**
+ * Clears the registry
+ */
+ public static function clear()
+ {
+ self::$loggers = array();
+ }
+
+ /**
+ * Gets Logger instance from the registry
+ *
+ * @param string $name Name of the requested Logger instance
+ * @throws \InvalidArgumentException If named Logger instance is not in the registry
+ * @return Logger Requested instance of Logger
+ */
+ public static function getInstance($name)
+ {
+ if (!isset(self::$loggers[$name])) {
+ throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name));
+ }
+
+ return self::$loggers[$name];
+ }
+
+ /**
+ * Gets Logger instance from the registry via static method call
+ *
+ * @param string $name Name of the requested Logger instance
+ * @param array $arguments Arguments passed to static method call
+ * @throws \InvalidArgumentException If named Logger instance is not in the registry
+ * @return Logger Requested instance of Logger
+ */
+ public static function __callStatic($name, $arguments)
+ {
+ return self::getInstance($name);
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/ResettableInterface.php b/vendor/monolog/monolog/src/Monolog/ResettableInterface.php
new file mode 100644
index 000000000..635bc77dc
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/ResettableInterface.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+/**
+ * Handler or Processor implementing this interface will be reset when Logger::reset() is called.
+ *
+ * Resetting ends a log cycle gets them back to their initial state.
+ *
+ * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
+ * state, and getting it back to a state in which it can receive log records again.
+ *
+ * This is useful in case you want to avoid logs leaking between two requests or jobs when you
+ * have a long running process like a worker or an application server serving multiple requests
+ * in one process.
+ *
+ * @author Grégoire Pineau
+ */
+interface ResettableInterface
+{
+ public function reset();
+}
diff --git a/vendor/monolog/monolog/src/Monolog/SignalHandler.php b/vendor/monolog/monolog/src/Monolog/SignalHandler.php
new file mode 100644
index 000000000..d87018fed
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/SignalHandler.php
@@ -0,0 +1,115 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
+use ReflectionExtension;
+
+/**
+ * Monolog POSIX signal handler
+ *
+ * @author Robert Gust-Bardon
+ */
+class SignalHandler
+{
+ private $logger;
+
+ private $previousSignalHandler = array();
+ private $signalLevelMap = array();
+ private $signalRestartSyscalls = array();
+
+ public function __construct(LoggerInterface $logger)
+ {
+ $this->logger = $logger;
+ }
+
+ public function registerSignalHandler($signo, $level = LogLevel::CRITICAL, $callPrevious = true, $restartSyscalls = true, $async = true)
+ {
+ if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) {
+ return $this;
+ }
+
+ if ($callPrevious) {
+ if (function_exists('pcntl_signal_get_handler')) {
+ $handler = pcntl_signal_get_handler($signo);
+ if ($handler === false) {
+ return $this;
+ }
+ $this->previousSignalHandler[$signo] = $handler;
+ } else {
+ $this->previousSignalHandler[$signo] = true;
+ }
+ } else {
+ unset($this->previousSignalHandler[$signo]);
+ }
+ $this->signalLevelMap[$signo] = $level;
+ $this->signalRestartSyscalls[$signo] = $restartSyscalls;
+
+ if (function_exists('pcntl_async_signals') && $async !== null) {
+ pcntl_async_signals($async);
+ }
+
+ pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls);
+
+ return $this;
+ }
+
+ public function handleSignal($signo, array $siginfo = null)
+ {
+ static $signals = array();
+
+ if (!$signals && extension_loaded('pcntl')) {
+ $pcntl = new ReflectionExtension('pcntl');
+ $constants = $pcntl->getConstants();
+ if (!$constants) {
+ // HHVM 3.24.2 returns an empty array.
+ $constants = get_defined_constants(true);
+ $constants = $constants['Core'];
+ }
+ foreach ($constants as $name => $value) {
+ if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) {
+ $signals[$value] = $name;
+ }
+ }
+ unset($constants);
+ }
+
+ $level = isset($this->signalLevelMap[$signo]) ? $this->signalLevelMap[$signo] : LogLevel::CRITICAL;
+ $signal = isset($signals[$signo]) ? $signals[$signo] : $signo;
+ $context = isset($siginfo) ? $siginfo : array();
+ $this->logger->log($level, sprintf('Program received signal %s', $signal), $context);
+
+ if (!isset($this->previousSignalHandler[$signo])) {
+ return;
+ }
+
+ if ($this->previousSignalHandler[$signo] === true || $this->previousSignalHandler[$signo] === SIG_DFL) {
+ if (extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_sigprocmask') && function_exists('pcntl_signal_dispatch')
+ && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill')) {
+ $restartSyscalls = isset($this->signalRestartSyscalls[$signo]) ? $this->signalRestartSyscalls[$signo] : true;
+ pcntl_signal($signo, SIG_DFL, $restartSyscalls);
+ pcntl_sigprocmask(SIG_UNBLOCK, array($signo), $oldset);
+ posix_kill(posix_getpid(), $signo);
+ pcntl_signal_dispatch();
+ pcntl_sigprocmask(SIG_SETMASK, $oldset);
+ pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls);
+ }
+ } elseif (is_callable($this->previousSignalHandler[$signo])) {
+ if (PHP_VERSION_ID >= 70100) {
+ $this->previousSignalHandler[$signo]($signo, $siginfo);
+ } else {
+ $this->previousSignalHandler[$signo]($signo);
+ }
+ }
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Utils.php b/vendor/monolog/monolog/src/Monolog/Utils.php
new file mode 100644
index 000000000..7f1ba129e
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Utils.php
@@ -0,0 +1,189 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+class Utils
+{
+ /**
+ * @internal
+ */
+ public static function getClass($object)
+ {
+ $class = \get_class($object);
+
+ return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
+ }
+
+ /**
+ * Makes sure if a relative path is passed in it is turned into an absolute path
+ *
+ * @param string $streamUrl stream URL or path without protocol
+ *
+ * @return string
+ */
+ public static function canonicalizePath($streamUrl)
+ {
+ $prefix = '';
+ if ('file://' === substr($streamUrl, 0, 7)) {
+ $streamUrl = substr($streamUrl, 7);
+ $prefix = 'file://';
+ }
+
+ // other type of stream, not supported
+ if (false !== strpos($streamUrl, '://')) {
+ return $streamUrl;
+ }
+
+ // already absolute
+ if (substr($streamUrl, 0, 1) === '/' || substr($streamUrl, 1, 1) === ':' || substr($streamUrl, 0, 2) === '\\\\') {
+ return $prefix.$streamUrl;
+ }
+
+ $streamUrl = getcwd() . '/' . $streamUrl;
+
+ return $prefix.$streamUrl;
+ }
+
+ /**
+ * Return the JSON representation of a value
+ *
+ * @param mixed $data
+ * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
+ * @param bool $ignoreErrors whether to ignore encoding errors or to throw on error, when ignored and the encoding fails, "null" is returned which is valid json for null
+ * @throws \RuntimeException if encoding fails and errors are not ignored
+ * @return string
+ */
+ public static function jsonEncode($data, $encodeFlags = null, $ignoreErrors = false)
+ {
+ if (null === $encodeFlags && version_compare(PHP_VERSION, '5.4.0', '>=')) {
+ $encodeFlags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
+ }
+
+ if ($ignoreErrors) {
+ $json = @json_encode($data, $encodeFlags);
+ if (false === $json) {
+ return 'null';
+ }
+
+ return $json;
+ }
+
+ $json = json_encode($data, $encodeFlags);
+ if (false === $json) {
+ $json = self::handleJsonError(json_last_error(), $data);
+ }
+
+ return $json;
+ }
+
+ /**
+ * Handle a json_encode failure.
+ *
+ * If the failure is due to invalid string encoding, try to clean the
+ * input and encode again. If the second encoding attempt fails, the
+ * inital error is not encoding related or the input can't be cleaned then
+ * raise a descriptive exception.
+ *
+ * @param int $code return code of json_last_error function
+ * @param mixed $data data that was meant to be encoded
+ * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
+ * @throws \RuntimeException if failure can't be corrected
+ * @return string JSON encoded data after error correction
+ */
+ public static function handleJsonError($code, $data, $encodeFlags = null)
+ {
+ if ($code !== JSON_ERROR_UTF8) {
+ self::throwEncodeError($code, $data);
+ }
+
+ if (is_string($data)) {
+ self::detectAndCleanUtf8($data);
+ } elseif (is_array($data)) {
+ array_walk_recursive($data, array('Monolog\Utils', 'detectAndCleanUtf8'));
+ } else {
+ self::throwEncodeError($code, $data);
+ }
+
+ if (null === $encodeFlags && version_compare(PHP_VERSION, '5.4.0', '>=')) {
+ $encodeFlags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
+ }
+
+ $json = json_encode($data, $encodeFlags);
+
+ if ($json === false) {
+ self::throwEncodeError(json_last_error(), $data);
+ }
+
+ return $json;
+ }
+
+ /**
+ * Throws an exception according to a given code with a customized message
+ *
+ * @param int $code return code of json_last_error function
+ * @param mixed $data data that was meant to be encoded
+ * @throws \RuntimeException
+ */
+ private static function throwEncodeError($code, $data)
+ {
+ switch ($code) {
+ case JSON_ERROR_DEPTH:
+ $msg = 'Maximum stack depth exceeded';
+ break;
+ case JSON_ERROR_STATE_MISMATCH:
+ $msg = 'Underflow or the modes mismatch';
+ break;
+ case JSON_ERROR_CTRL_CHAR:
+ $msg = 'Unexpected control character found';
+ break;
+ case JSON_ERROR_UTF8:
+ $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
+ break;
+ default:
+ $msg = 'Unknown error';
+ }
+
+ throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($data, true));
+ }
+
+ /**
+ * Detect invalid UTF-8 string characters and convert to valid UTF-8.
+ *
+ * Valid UTF-8 input will be left unmodified, but strings containing
+ * invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed
+ * original encoding of ISO-8859-15. This conversion may result in
+ * incorrect output if the actual encoding was not ISO-8859-15, but it
+ * will be clean UTF-8 output and will not rely on expensive and fragile
+ * detection algorithms.
+ *
+ * Function converts the input in place in the passed variable so that it
+ * can be used as a callback for array_walk_recursive.
+ *
+ * @param mixed $data Input to check and convert if needed, passed by ref
+ * @private
+ */
+ public static function detectAndCleanUtf8(&$data)
+ {
+ if (is_string($data) && !preg_match('//u', $data)) {
+ $data = preg_replace_callback(
+ '/[\x80-\xFF]+/',
+ function ($m) { return utf8_encode($m[0]); },
+ $data
+ );
+ $data = str_replace(
+ array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'),
+ array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'),
+ $data
+ );
+ }
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/.editorconfig b/vendor/mtdowling/cron-expression/.editorconfig
new file mode 100644
index 000000000..1492202b4
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/.editorconfig
@@ -0,0 +1,16 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.yml]
+indent_style = space
+indent_size = 2
diff --git a/vendor/mtdowling/cron-expression/CHANGELOG.md b/vendor/mtdowling/cron-expression/CHANGELOG.md
new file mode 100644
index 000000000..8ddab9057
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/CHANGELOG.md
@@ -0,0 +1,36 @@
+# Change Log
+
+## [1.2.0] - 2017-01-22
+### Added
+- Added IDE, CodeSniffer, and StyleCI.IO support
+
+### Changed
+- Switched to PSR-4 Autoloading
+
+### Fixed
+- 0 step expressions are handled better
+- Fixed `DayOfMonth` validation to be more strict
+- Typos
+
+## [1.1.0] - 2016-01-26
+### Added
+- Support for non-hourly offset timezones
+- Checks for valid expressions
+
+### Changed
+- Max Iterations no longer hardcoded for `getRunDate()`
+- Supports DateTimeImmutable for newer PHP verions
+
+### Fixed
+- Fixed looping bug for PHP 7 when determining the last specified weekday of a month
+
+## [1.0.3] - 2013-11-23
+### Added
+- Now supports expressions with any number of extra spaces, tabs, or newlines
+
+### Changed
+- Using static instead of self in `CronExpression::factory`
+
+### Fixed
+- Fixes issue [#28](https://github.com/mtdowling/cron-expression/issues/28) where PHP increments of ranges were failing due to PHP casting hyphens to 0
+- Only set default timezone if the given $currentTime is not a DateTime instance ([#34](https://github.com/mtdowling/cron-expression/issues/34))
diff --git a/vendor/mtdowling/cron-expression/LICENSE b/vendor/mtdowling/cron-expression/LICENSE
new file mode 100644
index 000000000..c6d88ac6c
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Michael Dowling and contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/mtdowling/cron-expression/README.md b/vendor/mtdowling/cron-expression/README.md
new file mode 100644
index 000000000..c9e3bf3e5
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/README.md
@@ -0,0 +1,71 @@
+PHP Cron Expression Parser
+==========================
+
+[](https://packagist.org/packages/mtdowling/cron-expression) [](https://packagist.org/packages/mtdowling/cron-expression) [](http://travis-ci.org/mtdowling/cron-expression)
+
+The PHP cron expression parser can parse a CRON expression, determine if it is
+due to run, calculate the next run date of the expression, and calculate the previous
+run date of the expression. You can calculate dates far into the future or past by
+skipping n number of matching dates.
+
+The parser can handle increments of ranges (e.g. */12, 2-59/3), intervals (e.g. 0-9),
+lists (e.g. 1,2,3), W to find the nearest weekday for a given day of the month, L to
+find the last day of the month, L to find the last given weekday of a month, and hash
+(#) to find the nth weekday of a given month.
+
+Installing
+==========
+
+Add the dependency to your project:
+
+```bash
+composer require mtdowling/cron-expression
+```
+
+Usage
+=====
+```php
+isDue();
+echo $cron->getNextRunDate()->format('Y-m-d H:i:s');
+echo $cron->getPreviousRunDate()->format('Y-m-d H:i:s');
+
+// Works with complex expressions
+$cron = Cron\CronExpression::factory('3-59/15 2,6-12 */15 1 2-5');
+echo $cron->getNextRunDate()->format('Y-m-d H:i:s');
+
+// Calculate a run date two iterations into the future
+$cron = Cron\CronExpression::factory('@daily');
+echo $cron->getNextRunDate(null, 2)->format('Y-m-d H:i:s');
+
+// Calculate a run date relative to a specific time
+$cron = Cron\CronExpression::factory('@monthly');
+echo $cron->getNextRunDate('2010-01-12 00:00:00')->format('Y-m-d H:i:s');
+```
+
+CRON Expressions
+================
+
+A CRON expression is a string representing the schedule for a particular command to execute. The parts of a CRON schedule are as follows:
+
+ * * * * * *
+ - - - - - -
+ | | | | | |
+ | | | | | + year [optional]
+ | | | | +----- day of week (0 - 7) (Sunday=0 or 7)
+ | | | +---------- month (1 - 12)
+ | | +--------------- day of month (1 - 31)
+ | +-------------------- hour (0 - 23)
+ +------------------------- min (0 - 59)
+
+Requirements
+============
+
+- PHP 5.3+
+- PHPUnit is required to run the unit tests
+- Composer is required to run the unit tests
\ No newline at end of file
diff --git a/vendor/mtdowling/cron-expression/composer.json b/vendor/mtdowling/cron-expression/composer.json
new file mode 100644
index 000000000..d68c9ec1c
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "mtdowling/cron-expression",
+ "type": "library",
+ "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due",
+ "keywords": ["cron", "schedule"],
+ "license": "MIT",
+ "authors": [{
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }],
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0|~5.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Cron\\": "src/Cron/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Tests\\": "tests/Cron/"
+ }
+ },
+ "abandoned": "dragonmantank/cron-expression"
+}
diff --git a/vendor/mtdowling/cron-expression/src/Cron/AbstractField.php b/vendor/mtdowling/cron-expression/src/Cron/AbstractField.php
new file mode 100644
index 000000000..cd2410ab6
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/src/Cron/AbstractField.php
@@ -0,0 +1,148 @@
+isIncrementsOfRanges($value)) {
+ return $this->isInIncrementsOfRanges($dateValue, $value);
+ } elseif ($this->isRange($value)) {
+ return $this->isInRange($dateValue, $value);
+ }
+
+ return $value == '*' || $dateValue == $value;
+ }
+
+ /**
+ * Check if a value is a range
+ *
+ * @param string $value Value to test
+ *
+ * @return bool
+ */
+ public function isRange($value)
+ {
+ return strpos($value, '-') !== false;
+ }
+
+ /**
+ * Check if a value is an increments of ranges
+ *
+ * @param string $value Value to test
+ *
+ * @return bool
+ */
+ public function isIncrementsOfRanges($value)
+ {
+ return strpos($value, '/') !== false;
+ }
+
+ /**
+ * Test if a value is within a range
+ *
+ * @param string $dateValue Set date value
+ * @param string $value Value to test
+ *
+ * @return bool
+ */
+ public function isInRange($dateValue, $value)
+ {
+ $parts = array_map('trim', explode('-', $value, 2));
+
+ return $dateValue >= $parts[0] && $dateValue <= $parts[1];
+ }
+
+ /**
+ * Test if a value is within an increments of ranges (offset[-to]/step size)
+ *
+ * @param string $dateValue Set date value
+ * @param string $value Value to test
+ *
+ * @return bool
+ */
+ public function isInIncrementsOfRanges($dateValue, $value)
+ {
+ $parts = array_map('trim', explode('/', $value, 2));
+ $stepSize = isset($parts[1]) ? (int) $parts[1] : 0;
+
+ if ($stepSize === 0) {
+ return false;
+ }
+
+ if (($parts[0] == '*' || $parts[0] === '0')) {
+ return (int) $dateValue % $stepSize == 0;
+ }
+
+ $range = explode('-', $parts[0], 2);
+ $offset = $range[0];
+ $to = isset($range[1]) ? $range[1] : $dateValue;
+ // Ensure that the date value is within the range
+ if ($dateValue < $offset || $dateValue > $to) {
+ return false;
+ }
+
+ if ($dateValue > $offset && 0 === $stepSize) {
+ return false;
+ }
+
+ for ($i = $offset; $i <= $to; $i+= $stepSize) {
+ if ($i == $dateValue) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a range of values for the given cron expression
+ *
+ * @param string $expression The expression to evaluate
+ * @param int $max Maximum offset for range
+ *
+ * @return array
+ */
+ public function getRangeForExpression($expression, $max)
+ {
+ $values = array();
+
+ if ($this->isRange($expression) || $this->isIncrementsOfRanges($expression)) {
+ if (!$this->isIncrementsOfRanges($expression)) {
+ list ($offset, $to) = explode('-', $expression);
+ $stepSize = 1;
+ }
+ else {
+ $range = array_map('trim', explode('/', $expression, 2));
+ $stepSize = isset($range[1]) ? $range[1] : 0;
+ $range = $range[0];
+ $range = explode('-', $range, 2);
+ $offset = $range[0];
+ $to = isset($range[1]) ? $range[1] : $max;
+ }
+ $offset = $offset == '*' ? 0 : $offset;
+ for ($i = $offset; $i <= $to; $i += $stepSize) {
+ $values[] = $i;
+ }
+ sort($values);
+ }
+ else {
+ $values = array($expression);
+ }
+
+ return $values;
+ }
+
+}
diff --git a/vendor/mtdowling/cron-expression/src/Cron/CronExpression.php b/vendor/mtdowling/cron-expression/src/Cron/CronExpression.php
new file mode 100644
index 000000000..d69b4154e
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/src/Cron/CronExpression.php
@@ -0,0 +1,389 @@
+ '0 0 1 1 *',
+ '@annually' => '0 0 1 1 *',
+ '@monthly' => '0 0 1 * *',
+ '@weekly' => '0 0 * * 0',
+ '@daily' => '0 0 * * *',
+ '@hourly' => '0 * * * *'
+ );
+
+ if (isset($mappings[$expression])) {
+ $expression = $mappings[$expression];
+ }
+
+ return new static($expression, $fieldFactory ?: new FieldFactory());
+ }
+
+ /**
+ * Validate a CronExpression.
+ *
+ * @param string $expression The CRON expression to validate.
+ *
+ * @return bool True if a valid CRON expression was passed. False if not.
+ * @see \Cron\CronExpression::factory
+ */
+ public static function isValidExpression($expression)
+ {
+ try {
+ self::factory($expression);
+ } catch (InvalidArgumentException $e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Parse a CRON expression
+ *
+ * @param string $expression CRON expression (e.g. '8 * * * *')
+ * @param FieldFactory $fieldFactory Factory to create cron fields
+ */
+ public function __construct($expression, FieldFactory $fieldFactory)
+ {
+ $this->fieldFactory = $fieldFactory;
+ $this->setExpression($expression);
+ }
+
+ /**
+ * Set or change the CRON expression
+ *
+ * @param string $value CRON expression (e.g. 8 * * * *)
+ *
+ * @return CronExpression
+ * @throws \InvalidArgumentException if not a valid CRON expression
+ */
+ public function setExpression($value)
+ {
+ $this->cronParts = preg_split('/\s/', $value, -1, PREG_SPLIT_NO_EMPTY);
+ if (count($this->cronParts) < 5) {
+ throw new InvalidArgumentException(
+ $value . ' is not a valid CRON expression'
+ );
+ }
+
+ foreach ($this->cronParts as $position => $part) {
+ $this->setPart($position, $part);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set part of the CRON expression
+ *
+ * @param int $position The position of the CRON expression to set
+ * @param string $value The value to set
+ *
+ * @return CronExpression
+ * @throws \InvalidArgumentException if the value is not valid for the part
+ */
+ public function setPart($position, $value)
+ {
+ if (!$this->fieldFactory->getField($position)->validate($value)) {
+ throw new InvalidArgumentException(
+ 'Invalid CRON field value ' . $value . ' at position ' . $position
+ );
+ }
+
+ $this->cronParts[$position] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Set max iteration count for searching next run dates
+ *
+ * @param int $maxIterationCount Max iteration count when searching for next run date
+ *
+ * @return CronExpression
+ */
+ public function setMaxIterationCount($maxIterationCount)
+ {
+ $this->maxIterationCount = $maxIterationCount;
+
+ return $this;
+ }
+
+ /**
+ * Get a next run date relative to the current date or a specific date
+ *
+ * @param string|\DateTime $currentTime Relative calculation date
+ * @param int $nth Number of matches to skip before returning a
+ * matching next run date. 0, the default, will return the current
+ * date and time if the next run date falls on the current date and
+ * time. Setting this value to 1 will skip the first match and go to
+ * the second match. Setting this value to 2 will skip the first 2
+ * matches and so on.
+ * @param bool $allowCurrentDate Set to TRUE to return the current date if
+ * it matches the cron expression.
+ *
+ * @return \DateTime
+ * @throws \RuntimeException on too many iterations
+ */
+ public function getNextRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
+ {
+ return $this->getRunDate($currentTime, $nth, false, $allowCurrentDate);
+ }
+
+ /**
+ * Get a previous run date relative to the current date or a specific date
+ *
+ * @param string|\DateTime $currentTime Relative calculation date
+ * @param int $nth Number of matches to skip before returning
+ * @param bool $allowCurrentDate Set to TRUE to return the
+ * current date if it matches the cron expression
+ *
+ * @return \DateTime
+ * @throws \RuntimeException on too many iterations
+ * @see \Cron\CronExpression::getNextRunDate
+ */
+ public function getPreviousRunDate($currentTime = 'now', $nth = 0, $allowCurrentDate = false)
+ {
+ return $this->getRunDate($currentTime, $nth, true, $allowCurrentDate);
+ }
+
+ /**
+ * Get multiple run dates starting at the current date or a specific date
+ *
+ * @param int $total Set the total number of dates to calculate
+ * @param string|\DateTime $currentTime Relative calculation date
+ * @param bool $invert Set to TRUE to retrieve previous dates
+ * @param bool $allowCurrentDate Set to TRUE to return the
+ * current date if it matches the cron expression
+ *
+ * @return array Returns an array of run dates
+ */
+ public function getMultipleRunDates($total, $currentTime = 'now', $invert = false, $allowCurrentDate = false)
+ {
+ $matches = array();
+ for ($i = 0; $i < max(0, $total); $i++) {
+ try {
+ $matches[] = $this->getRunDate($currentTime, $i, $invert, $allowCurrentDate);
+ } catch (RuntimeException $e) {
+ break;
+ }
+ }
+
+ return $matches;
+ }
+
+ /**
+ * Get all or part of the CRON expression
+ *
+ * @param string $part Specify the part to retrieve or NULL to get the full
+ * cron schedule string.
+ *
+ * @return string|null Returns the CRON expression, a part of the
+ * CRON expression, or NULL if the part was specified but not found
+ */
+ public function getExpression($part = null)
+ {
+ if (null === $part) {
+ return implode(' ', $this->cronParts);
+ } elseif (array_key_exists($part, $this->cronParts)) {
+ return $this->cronParts[$part];
+ }
+
+ return null;
+ }
+
+ /**
+ * Helper method to output the full expression.
+ *
+ * @return string Full CRON expression
+ */
+ public function __toString()
+ {
+ return $this->getExpression();
+ }
+
+ /**
+ * Determine if the cron is due to run based on the current date or a
+ * specific date. This method assumes that the current number of
+ * seconds are irrelevant, and should be called once per minute.
+ *
+ * @param string|\DateTime $currentTime Relative calculation date
+ *
+ * @return bool Returns TRUE if the cron is due to run or FALSE if not
+ */
+ public function isDue($currentTime = 'now')
+ {
+ if ('now' === $currentTime) {
+ $currentDate = date('Y-m-d H:i');
+ $currentTime = strtotime($currentDate);
+ } elseif ($currentTime instanceof DateTime) {
+ $currentDate = clone $currentTime;
+ // Ensure time in 'current' timezone is used
+ $currentDate->setTimezone(new DateTimeZone(date_default_timezone_get()));
+ $currentDate = $currentDate->format('Y-m-d H:i');
+ $currentTime = strtotime($currentDate);
+ } elseif ($currentTime instanceof DateTimeImmutable) {
+ $currentDate = DateTime::createFromFormat('U', $currentTime->format('U'));
+ $currentDate->setTimezone(new DateTimeZone(date_default_timezone_get()));
+ $currentDate = $currentDate->format('Y-m-d H:i');
+ $currentTime = strtotime($currentDate);
+ } else {
+ $currentTime = new DateTime($currentTime);
+ $currentTime->setTime($currentTime->format('H'), $currentTime->format('i'), 0);
+ $currentDate = $currentTime->format('Y-m-d H:i');
+ $currentTime = $currentTime->getTimeStamp();
+ }
+
+ try {
+ return $this->getNextRunDate($currentDate, 0, true)->getTimestamp() == $currentTime;
+ } catch (Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * Get the next or previous run date of the expression relative to a date
+ *
+ * @param string|\DateTime $currentTime Relative calculation date
+ * @param int $nth Number of matches to skip before returning
+ * @param bool $invert Set to TRUE to go backwards in time
+ * @param bool $allowCurrentDate Set to TRUE to return the
+ * current date if it matches the cron expression
+ *
+ * @return \DateTime
+ * @throws \RuntimeException on too many iterations
+ */
+ protected function getRunDate($currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false)
+ {
+ if ($currentTime instanceof DateTime) {
+ $currentDate = clone $currentTime;
+ } elseif ($currentTime instanceof DateTimeImmutable) {
+ $currentDate = DateTime::createFromFormat('U', $currentTime->format('U'));
+ $currentDate->setTimezone($currentTime->getTimezone());
+ } else {
+ $currentDate = new DateTime($currentTime ?: 'now');
+ $currentDate->setTimezone(new DateTimeZone(date_default_timezone_get()));
+ }
+
+ $currentDate->setTime($currentDate->format('H'), $currentDate->format('i'), 0);
+ $nextRun = clone $currentDate;
+ $nth = (int) $nth;
+
+ // We don't have to satisfy * or null fields
+ $parts = array();
+ $fields = array();
+ foreach (self::$order as $position) {
+ $part = $this->getExpression($position);
+ if (null === $part || '*' === $part) {
+ continue;
+ }
+ $parts[$position] = $part;
+ $fields[$position] = $this->fieldFactory->getField($position);
+ }
+
+ // Set a hard limit to bail on an impossible date
+ for ($i = 0; $i < $this->maxIterationCount; $i++) {
+
+ foreach ($parts as $position => $part) {
+ $satisfied = false;
+ // Get the field object used to validate this part
+ $field = $fields[$position];
+ // Check if this is singular or a list
+ if (strpos($part, ',') === false) {
+ $satisfied = $field->isSatisfiedBy($nextRun, $part);
+ } else {
+ foreach (array_map('trim', explode(',', $part)) as $listPart) {
+ if ($field->isSatisfiedBy($nextRun, $listPart)) {
+ $satisfied = true;
+ break;
+ }
+ }
+ }
+
+ // If the field is not satisfied, then start over
+ if (!$satisfied) {
+ $field->increment($nextRun, $invert, $part);
+ continue 2;
+ }
+ }
+
+ // Skip this match if needed
+ if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) {
+ $this->fieldFactory->getField(0)->increment($nextRun, $invert, isset($parts[0]) ? $parts[0] : null);
+ continue;
+ }
+
+ return $nextRun;
+ }
+
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException('Impossible CRON expression');
+ // @codeCoverageIgnoreEnd
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/src/Cron/DayOfMonthField.php b/vendor/mtdowling/cron-expression/src/Cron/DayOfMonthField.php
new file mode 100644
index 000000000..53e15bc41
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/src/Cron/DayOfMonthField.php
@@ -0,0 +1,173 @@
+
+ */
+class DayOfMonthField extends AbstractField
+{
+ /**
+ * Get the nearest day of the week for a given day in a month
+ *
+ * @param int $currentYear Current year
+ * @param int $currentMonth Current month
+ * @param int $targetDay Target day of the month
+ *
+ * @return \DateTime Returns the nearest date
+ */
+ private static function getNearestWeekday($currentYear, $currentMonth, $targetDay)
+ {
+ $tday = str_pad($targetDay, 2, '0', STR_PAD_LEFT);
+ $target = DateTime::createFromFormat('Y-m-d', "$currentYear-$currentMonth-$tday");
+ $currentWeekday = (int) $target->format('N');
+
+ if ($currentWeekday < 6) {
+ return $target;
+ }
+
+ $lastDayOfMonth = $target->format('t');
+
+ foreach (array(-1, 1, -2, 2) as $i) {
+ $adjusted = $targetDay + $i;
+ if ($adjusted > 0 && $adjusted <= $lastDayOfMonth) {
+ $target->setDate($currentYear, $currentMonth, $adjusted);
+ if ($target->format('N') < 6 && $target->format('m') == $currentMonth) {
+ return $target;
+ }
+ }
+ }
+ }
+
+ public function isSatisfiedBy(DateTime $date, $value)
+ {
+ // ? states that the field value is to be skipped
+ if ($value == '?') {
+ return true;
+ }
+
+ $fieldValue = $date->format('d');
+
+ // Check to see if this is the last day of the month
+ if ($value == 'L') {
+ return $fieldValue == $date->format('t');
+ }
+
+ // Check to see if this is the nearest weekday to a particular value
+ if (strpos($value, 'W')) {
+ // Parse the target day
+ $targetDay = substr($value, 0, strpos($value, 'W'));
+ // Find out if the current day is the nearest day of the week
+ return $date->format('j') == self::getNearestWeekday(
+ $date->format('Y'),
+ $date->format('m'),
+ $targetDay
+ )->format('j');
+ }
+
+ return $this->isSatisfied($date->format('d'), $value);
+ }
+
+ public function increment(DateTime $date, $invert = false)
+ {
+ if ($invert) {
+ $date->modify('previous day');
+ $date->setTime(23, 59);
+ } else {
+ $date->modify('next day');
+ $date->setTime(0, 0);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Validates that the value is valid for the Day of the Month field
+ * Days of the month can contain values of 1-31, *, L, or ? by default. This can be augmented with lists via a ',',
+ * ranges via a '-', or with a '[0-9]W' to specify the closest weekday.
+ *
+ * @param string $value
+ * @return bool
+ */
+ public function validate($value)
+ {
+ // Allow wildcards and a single L
+ if ($value === '?' || $value === '*' || $value === 'L') {
+ return true;
+ }
+
+ // If you only contain numbers and are within 1-31
+ if ((bool) preg_match('/^\d{1,2}$/', $value) && ($value >= 1 && $value <= 31)) {
+ return true;
+ }
+
+ // If you have a -, we will deal with each of your chunks
+ if ((bool) preg_match('/-/', $value)) {
+ // We cannot have a range within a list or vice versa
+ if ((bool) preg_match('/,/', $value)) {
+ return false;
+ }
+
+ $chunks = explode('-', $value);
+ foreach ($chunks as $chunk) {
+ if (!$this->validate($chunk)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // If you have a comma, we will deal with each value
+ if ((bool) preg_match('/,/', $value)) {
+ // We cannot have a range within a list or vice versa
+ if ((bool) preg_match('/-/', $value)) {
+ return false;
+ }
+
+ $chunks = explode(',', $value);
+ foreach ($chunks as $chunk) {
+ if (!$this->validate($chunk)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // If you contain a /, we'll deal with it
+ if ((bool) preg_match('/\//', $value)) {
+ $chunks = explode('/', $value);
+ foreach ($chunks as $chunk) {
+ if (!$this->validate($chunk)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // If you end in W, make sure that it has a numeric in front of it
+ if ((bool) preg_match('/^\d{1,2}W$/', $value)) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/src/Cron/DayOfWeekField.php b/vendor/mtdowling/cron-expression/src/Cron/DayOfWeekField.php
new file mode 100644
index 000000000..83e2f4c16
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/src/Cron/DayOfWeekField.php
@@ -0,0 +1,141 @@
+convertLiterals($value);
+
+ $currentYear = $date->format('Y');
+ $currentMonth = $date->format('m');
+ $lastDayOfMonth = $date->format('t');
+
+ // Find out if this is the last specific weekday of the month
+ if (strpos($value, 'L')) {
+ $weekday = str_replace('7', '0', substr($value, 0, strpos($value, 'L')));
+ $tdate = clone $date;
+ $tdate->setDate($currentYear, $currentMonth, $lastDayOfMonth);
+ while ($tdate->format('w') != $weekday) {
+ $tdateClone = new DateTime();
+ $tdate = $tdateClone
+ ->setTimezone($tdate->getTimezone())
+ ->setDate($currentYear, $currentMonth, --$lastDayOfMonth);
+ }
+
+ return $date->format('j') == $lastDayOfMonth;
+ }
+
+ // Handle # hash tokens
+ if (strpos($value, '#')) {
+ list($weekday, $nth) = explode('#', $value);
+
+ // 0 and 7 are both Sunday, however 7 matches date('N') format ISO-8601
+ if ($weekday === '0') {
+ $weekday = 7;
+ }
+
+ // Validate the hash fields
+ if ($weekday < 0 || $weekday > 7) {
+ throw new InvalidArgumentException("Weekday must be a value between 0 and 7. {$weekday} given");
+ }
+ if ($nth > 5) {
+ throw new InvalidArgumentException('There are never more than 5 of a given weekday in a month');
+ }
+ // The current weekday must match the targeted weekday to proceed
+ if ($date->format('N') != $weekday) {
+ return false;
+ }
+
+ $tdate = clone $date;
+ $tdate->setDate($currentYear, $currentMonth, 1);
+ $dayCount = 0;
+ $currentDay = 1;
+ while ($currentDay < $lastDayOfMonth + 1) {
+ if ($tdate->format('N') == $weekday) {
+ if (++$dayCount >= $nth) {
+ break;
+ }
+ }
+ $tdate->setDate($currentYear, $currentMonth, ++$currentDay);
+ }
+
+ return $date->format('j') == $currentDay;
+ }
+
+ // Handle day of the week values
+ if (strpos($value, '-')) {
+ $parts = explode('-', $value);
+ if ($parts[0] == '7') {
+ $parts[0] = '0';
+ } elseif ($parts[1] == '0') {
+ $parts[1] = '7';
+ }
+ $value = implode('-', $parts);
+ }
+
+ // Test to see which Sunday to use -- 0 == 7 == Sunday
+ $format = in_array(7, str_split($value)) ? 'N' : 'w';
+ $fieldValue = $date->format($format);
+
+ return $this->isSatisfied($fieldValue, $value);
+ }
+
+ public function increment(DateTime $date, $invert = false)
+ {
+ if ($invert) {
+ $date->modify('-1 day');
+ $date->setTime(23, 59, 0);
+ } else {
+ $date->modify('+1 day');
+ $date->setTime(0, 0, 0);
+ }
+
+ return $this;
+ }
+
+ public function validate($value)
+ {
+ $value = $this->convertLiterals($value);
+
+ foreach (explode(',', $value) as $expr) {
+ if (!preg_match('/^(\*|[0-7](L?|#[1-5]))([\/\,\-][0-7]+)*$/', $expr)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private function convertLiterals($string)
+ {
+ return str_ireplace(
+ array('SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'),
+ range(0, 6),
+ $string
+ );
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/src/Cron/FieldFactory.php b/vendor/mtdowling/cron-expression/src/Cron/FieldFactory.php
new file mode 100644
index 000000000..fa0e6fe23
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/src/Cron/FieldFactory.php
@@ -0,0 +1,57 @@
+fields[$position])) {
+ switch ($position) {
+ case 0:
+ $this->fields[$position] = new MinutesField();
+ break;
+ case 1:
+ $this->fields[$position] = new HoursField();
+ break;
+ case 2:
+ $this->fields[$position] = new DayOfMonthField();
+ break;
+ case 3:
+ $this->fields[$position] = new MonthField();
+ break;
+ case 4:
+ $this->fields[$position] = new DayOfWeekField();
+ break;
+ case 5:
+ $this->fields[$position] = new YearField();
+ break;
+ default:
+ throw new InvalidArgumentException(
+ $position . ' is not a valid position'
+ );
+ }
+ }
+
+ return $this->fields[$position];
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/src/Cron/FieldInterface.php b/vendor/mtdowling/cron-expression/src/Cron/FieldInterface.php
new file mode 100644
index 000000000..be37b9389
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/src/Cron/FieldInterface.php
@@ -0,0 +1,40 @@
+isSatisfied($date->format('H'), $value);
+ }
+
+ public function increment(DateTime $date, $invert = false, $parts = null)
+ {
+ // Change timezone to UTC temporarily. This will
+ // allow us to go back or forwards and hour even
+ // if DST will be changed between the hours.
+ if (is_null($parts) || $parts == '*') {
+ $timezone = $date->getTimezone();
+ $date->setTimezone(new DateTimeZone('UTC'));
+ if ($invert) {
+ $date->modify('-1 hour');
+ } else {
+ $date->modify('+1 hour');
+ }
+ $date->setTimezone($timezone);
+
+ $date->setTime($date->format('H'), $invert ? 59 : 0);
+ return $this;
+ }
+
+ $parts = strpos($parts, ',') !== false ? explode(',', $parts) : array($parts);
+ $hours = array();
+ foreach ($parts as $part) {
+ $hours = array_merge($hours, $this->getRangeForExpression($part, 23));
+ }
+
+ $current_hour = $date->format('H');
+ $position = $invert ? count($hours) - 1 : 0;
+ if (count($hours) > 1) {
+ for ($i = 0; $i < count($hours) - 1; $i++) {
+ if ((!$invert && $current_hour >= $hours[$i] && $current_hour < $hours[$i + 1]) ||
+ ($invert && $current_hour > $hours[$i] && $current_hour <= $hours[$i + 1])) {
+ $position = $invert ? $i : $i + 1;
+ break;
+ }
+ }
+ }
+
+ $hour = $hours[$position];
+ if ((!$invert && $date->format('H') >= $hour) || ($invert && $date->format('H') <= $hour)) {
+ $date->modify(($invert ? '-' : '+') . '1 day');
+ $date->setTime($invert ? 23 : 0, $invert ? 59 : 0);
+ }
+ else {
+ $date->setTime($hour, $invert ? 59 : 0);
+ }
+
+ return $this;
+ }
+
+ public function validate($value)
+ {
+ return (bool) preg_match('/^[\*,\/\-0-9]+$/', $value);
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/src/Cron/MinutesField.php b/vendor/mtdowling/cron-expression/src/Cron/MinutesField.php
new file mode 100644
index 000000000..d8432b55e
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/src/Cron/MinutesField.php
@@ -0,0 +1,62 @@
+isSatisfied($date->format('i'), $value);
+ }
+
+ public function increment(DateTime $date, $invert = false, $parts = null)
+ {
+ if (is_null($parts)) {
+ if ($invert) {
+ $date->modify('-1 minute');
+ } else {
+ $date->modify('+1 minute');
+ }
+ return $this;
+ }
+
+ $parts = strpos($parts, ',') !== false ? explode(',', $parts) : array($parts);
+ $minutes = array();
+ foreach ($parts as $part) {
+ $minutes = array_merge($minutes, $this->getRangeForExpression($part, 59));
+ }
+
+ $current_minute = $date->format('i');
+ $position = $invert ? count($minutes) - 1 : 0;
+ if (count($minutes) > 1) {
+ for ($i = 0; $i < count($minutes) - 1; $i++) {
+ if ((!$invert && $current_minute >= $minutes[$i] && $current_minute < $minutes[$i + 1]) ||
+ ($invert && $current_minute > $minutes[$i] && $current_minute <= $minutes[$i + 1])) {
+ $position = $invert ? $i : $i + 1;
+ break;
+ }
+ }
+ }
+
+ if ((!$invert && $current_minute >= $minutes[$position]) || ($invert && $current_minute <= $minutes[$position])) {
+ $date->modify(($invert ? '-' : '+') . '1 hour');
+ $date->setTime($date->format('H'), $invert ? 59 : 0);
+ }
+ else {
+ $date->setTime($date->format('H'), $minutes[$position]);
+ }
+
+ return $this;
+ }
+
+ public function validate($value)
+ {
+ return (bool) preg_match('/^[\*,\/\-0-9]+$/', $value);
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/src/Cron/MonthField.php b/vendor/mtdowling/cron-expression/src/Cron/MonthField.php
new file mode 100644
index 000000000..0205c171a
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/src/Cron/MonthField.php
@@ -0,0 +1,44 @@
+isSatisfied($date->format('m'), $value);
+ }
+
+ public function increment(DateTime $date, $invert = false)
+ {
+ if ($invert) {
+ $date->modify('last day of previous month');
+ $date->setTime(23, 59);
+ } else {
+ $date->modify('first day of next month');
+ $date->setTime(0, 0);
+ }
+
+ return $this;
+ }
+
+ public function validate($value)
+ {
+ return (bool) preg_match('/^[\*,\/\-0-9A-Z]+$/', $value);
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/src/Cron/YearField.php b/vendor/mtdowling/cron-expression/src/Cron/YearField.php
new file mode 100644
index 000000000..db244fba2
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/src/Cron/YearField.php
@@ -0,0 +1,37 @@
+isSatisfied($date->format('Y'), $value);
+ }
+
+ public function increment(DateTime $date, $invert = false)
+ {
+ if ($invert) {
+ $date->modify('-1 year');
+ $date->setDate($date->format('Y'), 12, 31);
+ $date->setTime(23, 59, 0);
+ } else {
+ $date->modify('+1 year');
+ $date->setDate($date->format('Y'), 1, 1);
+ $date->setTime(0, 0, 0);
+ }
+
+ return $this;
+ }
+
+ public function validate($value)
+ {
+ return (bool) preg_match('/^[\*,\/\-0-9]+$/', $value);
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/tests/Cron/AbstractFieldTest.php b/vendor/mtdowling/cron-expression/tests/Cron/AbstractFieldTest.php
new file mode 100644
index 000000000..a1d653b27
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/tests/Cron/AbstractFieldTest.php
@@ -0,0 +1,86 @@
+
+ */
+class AbstractFieldTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Cron\AbstractField::isRange
+ */
+ public function testTestsIfRange()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->isRange('1-2'));
+ $this->assertFalse($f->isRange('2'));
+ }
+
+ /**
+ * @covers Cron\AbstractField::isIncrementsOfRanges
+ */
+ public function testTestsIfIncrementsOfRanges()
+ {
+ $f = new DayOfWeekField();
+ $this->assertFalse($f->isIncrementsOfRanges('1-2'));
+ $this->assertTrue($f->isIncrementsOfRanges('1/2'));
+ $this->assertTrue($f->isIncrementsOfRanges('*/2'));
+ $this->assertTrue($f->isIncrementsOfRanges('3-12/2'));
+ }
+
+ /**
+ * @covers Cron\AbstractField::isInRange
+ */
+ public function testTestsIfInRange()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->isInRange('1', '1-2'));
+ $this->assertTrue($f->isInRange('2', '1-2'));
+ $this->assertTrue($f->isInRange('5', '4-12'));
+ $this->assertFalse($f->isInRange('3', '4-12'));
+ $this->assertFalse($f->isInRange('13', '4-12'));
+ }
+
+ /**
+ * @covers Cron\AbstractField::isInIncrementsOfRanges
+ */
+ public function testTestsIfInIncrementsOfRanges()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->isInIncrementsOfRanges('3', '3-59/2'));
+ $this->assertTrue($f->isInIncrementsOfRanges('13', '3-59/2'));
+ $this->assertTrue($f->isInIncrementsOfRanges('15', '3-59/2'));
+ $this->assertTrue($f->isInIncrementsOfRanges('14', '*/2'));
+ $this->assertFalse($f->isInIncrementsOfRanges('2', '3-59/13'));
+ $this->assertFalse($f->isInIncrementsOfRanges('14', '*/13'));
+ $this->assertFalse($f->isInIncrementsOfRanges('14', '3-59/2'));
+ $this->assertFalse($f->isInIncrementsOfRanges('3', '2-59'));
+ $this->assertFalse($f->isInIncrementsOfRanges('3', '2'));
+ $this->assertFalse($f->isInIncrementsOfRanges('3', '*'));
+ $this->assertFalse($f->isInIncrementsOfRanges('0', '*/0'));
+ $this->assertFalse($f->isInIncrementsOfRanges('1', '*/0'));
+
+ $this->assertTrue($f->isInIncrementsOfRanges('4', '4/10'));
+ $this->assertTrue($f->isInIncrementsOfRanges('14', '4/10'));
+ $this->assertTrue($f->isInIncrementsOfRanges('34', '4/10'));
+ }
+
+ /**
+ * @covers Cron\AbstractField::isSatisfied
+ */
+ public function testTestsIfSatisfied()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->isSatisfied('12', '3-13'));
+ $this->assertTrue($f->isSatisfied('15', '3-59/12'));
+ $this->assertTrue($f->isSatisfied('12', '*'));
+ $this->assertTrue($f->isSatisfied('12', '12'));
+ $this->assertFalse($f->isSatisfied('12', '3-11'));
+ $this->assertFalse($f->isSatisfied('12', '3-59/13'));
+ $this->assertFalse($f->isSatisfied('12', '11'));
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/tests/Cron/CronExpressionTest.php b/vendor/mtdowling/cron-expression/tests/Cron/CronExpressionTest.php
new file mode 100644
index 000000000..f6fedb989
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/tests/Cron/CronExpressionTest.php
@@ -0,0 +1,414 @@
+
+ */
+class CronExpressionTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Cron\CronExpression::factory
+ */
+ public function testFactoryRecognizesTemplates()
+ {
+ $this->assertEquals('0 0 1 1 *', CronExpression::factory('@annually')->getExpression());
+ $this->assertEquals('0 0 1 1 *', CronExpression::factory('@yearly')->getExpression());
+ $this->assertEquals('0 0 * * 0', CronExpression::factory('@weekly')->getExpression());
+ }
+
+ /**
+ * @covers Cron\CronExpression::__construct
+ * @covers Cron\CronExpression::getExpression
+ * @covers Cron\CronExpression::__toString
+ */
+ public function testParsesCronSchedule()
+ {
+ // '2010-09-10 12:00:00'
+ $cron = CronExpression::factory('1 2-4 * 4,5,6 */3');
+ $this->assertEquals('1', $cron->getExpression(CronExpression::MINUTE));
+ $this->assertEquals('2-4', $cron->getExpression(CronExpression::HOUR));
+ $this->assertEquals('*', $cron->getExpression(CronExpression::DAY));
+ $this->assertEquals('4,5,6', $cron->getExpression(CronExpression::MONTH));
+ $this->assertEquals('*/3', $cron->getExpression(CronExpression::WEEKDAY));
+ $this->assertEquals('1 2-4 * 4,5,6 */3', $cron->getExpression());
+ $this->assertEquals('1 2-4 * 4,5,6 */3', (string) $cron);
+ $this->assertNull($cron->getExpression('foo'));
+
+ try {
+ $cron = CronExpression::factory('A 1 2 3 4');
+ $this->fail('Validation exception not thrown');
+ } catch (InvalidArgumentException $e) {
+ }
+ }
+
+ /**
+ * @covers Cron\CronExpression::__construct
+ * @covers Cron\CronExpression::getExpression
+ * @dataProvider scheduleWithDifferentSeparatorsProvider
+ */
+ public function testParsesCronScheduleWithAnySpaceCharsAsSeparators($schedule, array $expected)
+ {
+ $cron = CronExpression::factory($schedule);
+ $this->assertEquals($expected[0], $cron->getExpression(CronExpression::MINUTE));
+ $this->assertEquals($expected[1], $cron->getExpression(CronExpression::HOUR));
+ $this->assertEquals($expected[2], $cron->getExpression(CronExpression::DAY));
+ $this->assertEquals($expected[3], $cron->getExpression(CronExpression::MONTH));
+ $this->assertEquals($expected[4], $cron->getExpression(CronExpression::WEEKDAY));
+ $this->assertEquals($expected[5], $cron->getExpression(CronExpression::YEAR));
+ }
+
+ /**
+ * Data provider for testParsesCronScheduleWithAnySpaceCharsAsSeparators
+ *
+ * @return array
+ */
+ public static function scheduleWithDifferentSeparatorsProvider()
+ {
+ return array(
+ array("*\t*\t*\t*\t*\t*", array('*', '*', '*', '*', '*', '*')),
+ array("* * * * * *", array('*', '*', '*', '*', '*', '*')),
+ array("* \t * \t * \t * \t * \t *", array('*', '*', '*', '*', '*', '*')),
+ array("*\t \t*\t \t*\t \t*\t \t*\t \t*", array('*', '*', '*', '*', '*', '*')),
+ );
+ }
+
+ /**
+ * @covers Cron\CronExpression::__construct
+ * @covers Cron\CronExpression::setExpression
+ * @covers Cron\CronExpression::setPart
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidCronsWillFail()
+ {
+ // Only four values
+ $cron = CronExpression::factory('* * * 1');
+ }
+
+ /**
+ * @covers Cron\CronExpression::setPart
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidPartsWillFail()
+ {
+ // Only four values
+ $cron = CronExpression::factory('* * * * *');
+ $cron->setPart(1, 'abc');
+ }
+
+ /**
+ * Data provider for cron schedule
+ *
+ * @return array
+ */
+ public function scheduleProvider()
+ {
+ return array(
+ array('*/2 */2 * * *', '2015-08-10 21:47:27', '2015-08-10 22:00:00', false),
+ array('* * * * *', '2015-08-10 21:50:37', '2015-08-10 21:50:00', true),
+ array('* 20,21,22 * * *', '2015-08-10 21:50:00', '2015-08-10 21:50:00', true),
+ // Handles CSV values
+ array('* 20,22 * * *', '2015-08-10 21:50:00', '2015-08-10 22:00:00', false),
+ // CSV values can be complex
+ array('* 5,21-22 * * *', '2015-08-10 21:50:00', '2015-08-10 21:50:00', true),
+ array('7-9 * */9 * *', '2015-08-10 22:02:33', '2015-08-18 00:07:00', false),
+ // 15th minute, of the second hour, every 15 days, in January, every Friday
+ array('1 * * * 7', '2015-08-10 21:47:27', '2015-08-16 00:01:00', false),
+ // Test with exact times
+ array('47 21 * * *', strtotime('2015-08-10 21:47:30'), '2015-08-10 21:47:00', true),
+ // Test Day of the week (issue #1)
+ // According cron implementation, 0|7 = sunday, 1 => monday, etc
+ array('* * * * 0', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
+ array('* * * * 7', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
+ array('* * * * 1', strtotime('2011-06-15 23:09:00'), '2011-06-20 00:00:00', false),
+ // Should return the sunday date as 7 equals 0
+ array('0 0 * * MON,SUN', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
+ array('0 0 * * 1,7', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
+ array('0 0 * * 0-4', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
+ array('0 0 * * 7-4', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
+ array('0 0 * * 4-7', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
+ array('0 0 * * 7-3', strtotime('2011-06-15 23:09:00'), '2011-06-19 00:00:00', false),
+ array('0 0 * * 3-7', strtotime('2011-06-15 23:09:00'), '2011-06-16 00:00:00', false),
+ array('0 0 * * 3-7', strtotime('2011-06-18 23:09:00'), '2011-06-19 00:00:00', false),
+ // Test lists of values and ranges (Abhoryo)
+ array('0 0 * * 2-7', strtotime('2011-06-20 23:09:00'), '2011-06-21 00:00:00', false),
+ array('0 0 * * 0,2-6', strtotime('2011-06-20 23:09:00'), '2011-06-21 00:00:00', false),
+ array('0 0 * * 2-7', strtotime('2011-06-18 23:09:00'), '2011-06-19 00:00:00', false),
+ array('0 0 * * 4-7', strtotime('2011-07-19 00:00:00'), '2011-07-21 00:00:00', false),
+ // Test increments of ranges
+ array('0-12/4 * * * *', strtotime('2011-06-20 12:04:00'), '2011-06-20 12:04:00', true),
+ array('4-59/2 * * * *', strtotime('2011-06-20 12:04:00'), '2011-06-20 12:04:00', true),
+ array('4-59/2 * * * *', strtotime('2011-06-20 12:06:00'), '2011-06-20 12:06:00', true),
+ array('4-59/3 * * * *', strtotime('2011-06-20 12:06:00'), '2011-06-20 12:07:00', false),
+ //array('0 0 * * 0,2-6', strtotime('2011-06-20 23:09:00'), '2011-06-21 00:00:00', false),
+ // Test Day of the Week and the Day of the Month (issue #1)
+ array('0 0 1 1 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false),
+ array('0 0 1 JAN 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false),
+ array('0 0 1 * 0', strtotime('2011-06-15 23:09:00'), '2012-01-01 00:00:00', false),
+ array('0 0 L * *', strtotime('2011-07-15 00:00:00'), '2011-07-31 00:00:00', false),
+ // Test the W day of the week modifier for day of the month field
+ array('0 0 2W * *', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true),
+ array('0 0 1W * *', strtotime('2011-05-01 00:00:00'), '2011-05-02 00:00:00', false),
+ array('0 0 1W * *', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true),
+ array('0 0 3W * *', strtotime('2011-07-01 00:00:00'), '2011-07-04 00:00:00', false),
+ array('0 0 16W * *', strtotime('2011-07-01 00:00:00'), '2011-07-15 00:00:00', false),
+ array('0 0 28W * *', strtotime('2011-07-01 00:00:00'), '2011-07-28 00:00:00', false),
+ array('0 0 30W * *', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false),
+ array('0 0 31W * *', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false),
+ // Test the year field
+ array('* * * * * 2012', strtotime('2011-05-01 00:00:00'), '2012-01-01 00:00:00', false),
+ // Test the last weekday of a month
+ array('* * * * 5L', strtotime('2011-07-01 00:00:00'), '2011-07-29 00:00:00', false),
+ array('* * * * 6L', strtotime('2011-07-01 00:00:00'), '2011-07-30 00:00:00', false),
+ array('* * * * 7L', strtotime('2011-07-01 00:00:00'), '2011-07-31 00:00:00', false),
+ array('* * * * 1L', strtotime('2011-07-24 00:00:00'), '2011-07-25 00:00:00', false),
+ array('* * * * TUEL', strtotime('2011-07-24 00:00:00'), '2011-07-26 00:00:00', false),
+ array('* * * 1 5L', strtotime('2011-12-25 00:00:00'), '2012-01-27 00:00:00', false),
+ // Test the hash symbol for the nth weekday of a given month
+ array('* * * * 5#2', strtotime('2011-07-01 00:00:00'), '2011-07-08 00:00:00', false),
+ array('* * * * 5#1', strtotime('2011-07-01 00:00:00'), '2011-07-01 00:00:00', true),
+ array('* * * * 3#4', strtotime('2011-07-01 00:00:00'), '2011-07-27 00:00:00', false),
+ );
+ }
+
+ /**
+ * @covers Cron\CronExpression::isDue
+ * @covers Cron\CronExpression::getNextRunDate
+ * @covers Cron\DayOfMonthField
+ * @covers Cron\DayOfWeekField
+ * @covers Cron\MinutesField
+ * @covers Cron\HoursField
+ * @covers Cron\MonthField
+ * @covers Cron\YearField
+ * @covers Cron\CronExpression::getRunDate
+ * @dataProvider scheduleProvider
+ */
+ public function testDeterminesIfCronIsDue($schedule, $relativeTime, $nextRun, $isDue)
+ {
+ $relativeTimeString = is_int($relativeTime) ? date('Y-m-d H:i:s', $relativeTime) : $relativeTime;
+
+ // Test next run date
+ $cron = CronExpression::factory($schedule);
+ if (is_string($relativeTime)) {
+ $relativeTime = new DateTime($relativeTime);
+ } elseif (is_int($relativeTime)) {
+ $relativeTime = date('Y-m-d H:i:s', $relativeTime);
+ }
+ $this->assertEquals($isDue, $cron->isDue($relativeTime));
+ $next = $cron->getNextRunDate($relativeTime, 0, true);
+ $this->assertEquals(new DateTime($nextRun), $next);
+ }
+
+ /**
+ * @covers Cron\CronExpression::isDue
+ */
+ public function testIsDueHandlesDifferentDates()
+ {
+ $cron = CronExpression::factory('* * * * *');
+ $this->assertTrue($cron->isDue());
+ $this->assertTrue($cron->isDue('now'));
+ $this->assertTrue($cron->isDue(new DateTime('now')));
+ $this->assertTrue($cron->isDue(date('Y-m-d H:i')));
+ }
+
+ /**
+ * @covers Cron\CronExpression::isDue
+ */
+ public function testIsDueHandlesDifferentTimezones()
+ {
+ $cron = CronExpression::factory('0 15 * * 3'); //Wednesday at 15:00
+ $date = '2014-01-01 15:00'; //Wednesday
+ $utc = new DateTimeZone('UTC');
+ $amsterdam = new DateTimeZone('Europe/Amsterdam');
+ $tokyo = new DateTimeZone('Asia/Tokyo');
+
+ date_default_timezone_set('UTC');
+ $this->assertTrue($cron->isDue(new DateTime($date, $utc)));
+ $this->assertFalse($cron->isDue(new DateTime($date, $amsterdam)));
+ $this->assertFalse($cron->isDue(new DateTime($date, $tokyo)));
+
+ date_default_timezone_set('Europe/Amsterdam');
+ $this->assertFalse($cron->isDue(new DateTime($date, $utc)));
+ $this->assertTrue($cron->isDue(new DateTime($date, $amsterdam)));
+ $this->assertFalse($cron->isDue(new DateTime($date, $tokyo)));
+
+ date_default_timezone_set('Asia/Tokyo');
+ $this->assertFalse($cron->isDue(new DateTime($date, $utc)));
+ $this->assertFalse($cron->isDue(new DateTime($date, $amsterdam)));
+ $this->assertTrue($cron->isDue(new DateTime($date, $tokyo)));
+ }
+
+ /**
+ * @covers Cron\CronExpression::getPreviousRunDate
+ */
+ public function testCanGetPreviousRunDates()
+ {
+ $cron = CronExpression::factory('* * * * *');
+ $next = $cron->getNextRunDate('now');
+ $two = $cron->getNextRunDate('now', 1);
+ $this->assertEquals($next, $cron->getPreviousRunDate($two));
+
+ $cron = CronExpression::factory('* */2 * * *');
+ $next = $cron->getNextRunDate('now');
+ $two = $cron->getNextRunDate('now', 1);
+ $this->assertEquals($next, $cron->getPreviousRunDate($two));
+
+ $cron = CronExpression::factory('* * * */2 *');
+ $next = $cron->getNextRunDate('now');
+ $two = $cron->getNextRunDate('now', 1);
+ $this->assertEquals($next, $cron->getPreviousRunDate($two));
+ }
+
+ /**
+ * @covers Cron\CronExpression::getMultipleRunDates
+ */
+ public function testProvidesMultipleRunDates()
+ {
+ $cron = CronExpression::factory('*/2 * * * *');
+ $this->assertEquals(array(
+ new DateTime('2008-11-09 00:00:00'),
+ new DateTime('2008-11-09 00:02:00'),
+ new DateTime('2008-11-09 00:04:00'),
+ new DateTime('2008-11-09 00:06:00')
+ ), $cron->getMultipleRunDates(4, '2008-11-09 00:00:00', false, true));
+ }
+
+ /**
+ * @covers Cron\CronExpression::getMultipleRunDates
+ * @covers Cron\CronExpression::setMaxIterationCount
+ */
+ public function testProvidesMultipleRunDatesForTheFarFuture() {
+ // Fails with the default 1000 iteration limit
+ $cron = CronExpression::factory('0 0 12 1 * */2');
+ $cron->setMaxIterationCount(2000);
+ $this->assertEquals(array(
+ new DateTime('2016-01-12 00:00:00'),
+ new DateTime('2018-01-12 00:00:00'),
+ new DateTime('2020-01-12 00:00:00'),
+ new DateTime('2022-01-12 00:00:00'),
+ new DateTime('2024-01-12 00:00:00'),
+ new DateTime('2026-01-12 00:00:00'),
+ new DateTime('2028-01-12 00:00:00'),
+ new DateTime('2030-01-12 00:00:00'),
+ new DateTime('2032-01-12 00:00:00'),
+ ), $cron->getMultipleRunDates(9, '2015-04-28 00:00:00', false, true));
+ }
+
+ /**
+ * @covers Cron\CronExpression
+ */
+ public function testCanIterateOverNextRuns()
+ {
+ $cron = CronExpression::factory('@weekly');
+ $nextRun = $cron->getNextRunDate("2008-11-09 08:00:00");
+ $this->assertEquals($nextRun, new DateTime("2008-11-16 00:00:00"));
+
+ // true is cast to 1
+ $nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", true, true);
+ $this->assertEquals($nextRun, new DateTime("2008-11-16 00:00:00"));
+
+ // You can iterate over them
+ $nextRun = $cron->getNextRunDate($cron->getNextRunDate("2008-11-09 00:00:00", 1, true), 1, true);
+ $this->assertEquals($nextRun, new DateTime("2008-11-23 00:00:00"));
+
+ // You can skip more than one
+ $nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", 2, true);
+ $this->assertEquals($nextRun, new DateTime("2008-11-23 00:00:00"));
+ $nextRun = $cron->getNextRunDate("2008-11-09 00:00:00", 3, true);
+ $this->assertEquals($nextRun, new DateTime("2008-11-30 00:00:00"));
+ }
+
+ /**
+ * @covers Cron\CronExpression::getRunDate
+ */
+ public function testSkipsCurrentDateByDefault()
+ {
+ $cron = CronExpression::factory('* * * * *');
+ $current = new DateTime('now');
+ $next = $cron->getNextRunDate($current);
+ $nextPrev = $cron->getPreviousRunDate($next);
+ $this->assertEquals($current->format('Y-m-d H:i:00'), $nextPrev->format('Y-m-d H:i:s'));
+ }
+
+ /**
+ * @covers Cron\CronExpression::getRunDate
+ * @ticket 7
+ */
+ public function testStripsForSeconds()
+ {
+ $cron = CronExpression::factory('* * * * *');
+ $current = new DateTime('2011-09-27 10:10:54');
+ $this->assertEquals('2011-09-27 10:11:00', $cron->getNextRunDate($current)->format('Y-m-d H:i:s'));
+ }
+
+ /**
+ * @covers Cron\CronExpression::getRunDate
+ */
+ public function testFixesPhpBugInDateIntervalMonth()
+ {
+ $cron = CronExpression::factory('0 0 27 JAN *');
+ $this->assertEquals('2011-01-27 00:00:00', $cron->getPreviousRunDate('2011-08-22 00:00:00')->format('Y-m-d H:i:s'));
+ }
+
+ public function testIssue29()
+ {
+ $cron = CronExpression::factory('@weekly');
+ $this->assertEquals(
+ '2013-03-10 00:00:00',
+ $cron->getPreviousRunDate('2013-03-17 00:00:00')->format('Y-m-d H:i:s')
+ );
+ }
+
+ /**
+ * @see https://github.com/mtdowling/cron-expression/issues/20
+ */
+ public function testIssue20() {
+ $e = CronExpression::factory('* * * * MON#1');
+ $this->assertTrue($e->isDue(new DateTime('2014-04-07 00:00:00')));
+ $this->assertFalse($e->isDue(new DateTime('2014-04-14 00:00:00')));
+ $this->assertFalse($e->isDue(new DateTime('2014-04-21 00:00:00')));
+
+ $e = CronExpression::factory('* * * * SAT#2');
+ $this->assertFalse($e->isDue(new DateTime('2014-04-05 00:00:00')));
+ $this->assertTrue($e->isDue(new DateTime('2014-04-12 00:00:00')));
+ $this->assertFalse($e->isDue(new DateTime('2014-04-19 00:00:00')));
+
+ $e = CronExpression::factory('* * * * SUN#3');
+ $this->assertFalse($e->isDue(new DateTime('2014-04-13 00:00:00')));
+ $this->assertTrue($e->isDue(new DateTime('2014-04-20 00:00:00')));
+ $this->assertFalse($e->isDue(new DateTime('2014-04-27 00:00:00')));
+ }
+
+ /**
+ * @covers Cron\CronExpression::getRunDate
+ */
+ public function testKeepOriginalTime()
+ {
+ $now = new \DateTime;
+ $strNow = $now->format(DateTime::ISO8601);
+ $cron = CronExpression::factory('0 0 * * *');
+ $cron->getPreviousRunDate($now);
+ $this->assertEquals($strNow, $now->format(DateTime::ISO8601));
+ }
+
+ /**
+ * @covers Cron\CronExpression::__construct
+ * @covers Cron\CronExpression::factory
+ * @covers Cron\CronExpression::isValidExpression
+ * @covers Cron\CronExpression::setExpression
+ * @covers Cron\CronExpression::setPart
+ */
+ public function testValidationWorks()
+ {
+ // Invalid. Only four values
+ $this->assertFalse(CronExpression::isValidExpression('* * * 1'));
+ // Valid
+ $this->assertTrue(CronExpression::isValidExpression('* * * * 1'));
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/tests/Cron/DayOfMonthFieldTest.php b/vendor/mtdowling/cron-expression/tests/Cron/DayOfMonthFieldTest.php
new file mode 100644
index 000000000..eff04557f
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/tests/Cron/DayOfMonthFieldTest.php
@@ -0,0 +1,61 @@
+
+ */
+class DayOfMonthFieldTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Cron\DayOfMonthField::validate
+ */
+ public function testValidatesField()
+ {
+ $f = new DayOfMonthField();
+ $this->assertTrue($f->validate('1'));
+ $this->assertTrue($f->validate('*'));
+ $this->assertTrue($f->validate('5W,L'));
+ $this->assertFalse($f->validate('1.'));
+ }
+
+ /**
+ * @covers Cron\DayOfMonthField::isSatisfiedBy
+ */
+ public function testChecksIfSatisfied()
+ {
+ $f = new DayOfMonthField();
+ $this->assertTrue($f->isSatisfiedBy(new DateTime(), '?'));
+ }
+
+ /**
+ * @covers Cron\DayOfMonthField::increment
+ */
+ public function testIncrementsDate()
+ {
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f = new DayOfMonthField();
+ $f->increment($d);
+ $this->assertEquals('2011-03-16 00:00:00', $d->format('Y-m-d H:i:s'));
+
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f->increment($d, true);
+ $this->assertEquals('2011-03-14 23:59:00', $d->format('Y-m-d H:i:s'));
+ }
+
+ /**
+ * Day of the month cannot accept a 0 value, it must be between 1 and 31
+ * See Github issue #120
+ *
+ * @since 2017-01-22
+ */
+ public function testDoesNotAccept0Date()
+ {
+ $f = new DayOfMonthField();
+ $this->assertFalse($f->validate(0));
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/tests/Cron/DayOfWeekFieldTest.php b/vendor/mtdowling/cron-expression/tests/Cron/DayOfWeekFieldTest.php
new file mode 100644
index 000000000..182d5e906
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/tests/Cron/DayOfWeekFieldTest.php
@@ -0,0 +1,117 @@
+
+ */
+class DayOfWeekFieldTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Cron\DayOfWeekField::validate
+ */
+ public function testValidatesField()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->validate('1'));
+ $this->assertTrue($f->validate('*'));
+ $this->assertTrue($f->validate('*/3,1,1-12'));
+ $this->assertTrue($f->validate('SUN-2'));
+ $this->assertFalse($f->validate('1.'));
+ }
+
+ /**
+ * @covers Cron\DayOfWeekField::isSatisfiedBy
+ */
+ public function testChecksIfSatisfied()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->isSatisfiedBy(new DateTime(), '?'));
+ }
+
+ /**
+ * @covers Cron\DayOfWeekField::increment
+ */
+ public function testIncrementsDate()
+ {
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f = new DayOfWeekField();
+ $f->increment($d);
+ $this->assertEquals('2011-03-16 00:00:00', $d->format('Y-m-d H:i:s'));
+
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f->increment($d, true);
+ $this->assertEquals('2011-03-14 23:59:00', $d->format('Y-m-d H:i:s'));
+ }
+
+ /**
+ * @covers Cron\DayOfWeekField::isSatisfiedBy
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage Weekday must be a value between 0 and 7. 12 given
+ */
+ public function testValidatesHashValueWeekday()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->isSatisfiedBy(new DateTime(), '12#1'));
+ }
+
+ /**
+ * @covers Cron\DayOfWeekField::isSatisfiedBy
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage There are never more than 5 of a given weekday in a month
+ */
+ public function testValidatesHashValueNth()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->isSatisfiedBy(new DateTime(), '3#6'));
+ }
+
+ /**
+ * @covers Cron\DayOfWeekField::validate
+ */
+ public function testValidateWeekendHash()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->validate('MON#1'));
+ $this->assertTrue($f->validate('TUE#2'));
+ $this->assertTrue($f->validate('WED#3'));
+ $this->assertTrue($f->validate('THU#4'));
+ $this->assertTrue($f->validate('FRI#5'));
+ $this->assertTrue($f->validate('SAT#1'));
+ $this->assertTrue($f->validate('SUN#3'));
+ $this->assertTrue($f->validate('MON#1,MON#3'));
+ }
+
+ /**
+ * @covers Cron\DayOfWeekField::isSatisfiedBy
+ */
+ public function testHandlesZeroAndSevenDayOfTheWeekValues()
+ {
+ $f = new DayOfWeekField();
+ $this->assertTrue($f->isSatisfiedBy(new DateTime('2011-09-04 00:00:00'), '0-2'));
+ $this->assertTrue($f->isSatisfiedBy(new DateTime('2011-09-04 00:00:00'), '6-0'));
+
+ $this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), 'SUN'));
+ $this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), 'SUN#3'));
+ $this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), '0#3'));
+ $this->assertTrue($f->isSatisfiedBy(new DateTime('2014-04-20 00:00:00'), '7#3'));
+ }
+
+ /**
+ * @see https://github.com/mtdowling/cron-expression/issues/47
+ */
+ public function testIssue47() {
+ $f = new DayOfWeekField();
+ $this->assertFalse($f->validate('mon,'));
+ $this->assertFalse($f->validate('mon-'));
+ $this->assertFalse($f->validate('*/2,'));
+ $this->assertFalse($f->validate('-mon'));
+ $this->assertFalse($f->validate(',1'));
+ $this->assertFalse($f->validate('*-'));
+ $this->assertFalse($f->validate(',-'));
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/tests/Cron/FieldFactoryTest.php b/vendor/mtdowling/cron-expression/tests/Cron/FieldFactoryTest.php
new file mode 100644
index 000000000..f34cc9b58
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/tests/Cron/FieldFactoryTest.php
@@ -0,0 +1,43 @@
+
+ */
+class FieldFactoryTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Cron\FieldFactory::getField
+ */
+ public function testRetrievesFieldInstances()
+ {
+ $mappings = array(
+ 0 => 'Cron\MinutesField',
+ 1 => 'Cron\HoursField',
+ 2 => 'Cron\DayOfMonthField',
+ 3 => 'Cron\MonthField',
+ 4 => 'Cron\DayOfWeekField',
+ 5 => 'Cron\YearField'
+ );
+
+ $f = new FieldFactory();
+
+ foreach ($mappings as $position => $class) {
+ $this->assertEquals($class, get_class($f->getField($position)));
+ }
+ }
+
+ /**
+ * @covers Cron\FieldFactory::getField
+ * @expectedException InvalidArgumentException
+ */
+ public function testValidatesFieldPosition()
+ {
+ $f = new FieldFactory();
+ $f->getField(-1);
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/tests/Cron/HoursFieldTest.php b/vendor/mtdowling/cron-expression/tests/Cron/HoursFieldTest.php
new file mode 100644
index 000000000..d2d8a22a6
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/tests/Cron/HoursFieldTest.php
@@ -0,0 +1,75 @@
+
+ */
+class HoursFieldTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Cron\HoursField::validate
+ */
+ public function testValidatesField()
+ {
+ $f = new HoursField();
+ $this->assertTrue($f->validate('1'));
+ $this->assertTrue($f->validate('*'));
+ $this->assertTrue($f->validate('*/3,1,1-12'));
+ }
+
+ /**
+ * @covers Cron\HoursField::increment
+ */
+ public function testIncrementsDate()
+ {
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f = new HoursField();
+ $f->increment($d);
+ $this->assertEquals('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s'));
+
+ $d->setTime(11, 15, 0);
+ $f->increment($d, true);
+ $this->assertEquals('2011-03-15 10:59:00', $d->format('Y-m-d H:i:s'));
+ }
+
+ /**
+ * @covers Cron\HoursField::increment
+ */
+ public function testIncrementsDateWithThirtyMinuteOffsetTimezone()
+ {
+ $tz = date_default_timezone_get();
+ date_default_timezone_set('America/St_Johns');
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f = new HoursField();
+ $f->increment($d);
+ $this->assertEquals('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s'));
+
+ $d->setTime(11, 15, 0);
+ $f->increment($d, true);
+ $this->assertEquals('2011-03-15 10:59:00', $d->format('Y-m-d H:i:s'));
+ date_default_timezone_set($tz);
+ }
+
+ /**
+ * @covers Cron\HoursField::increment
+ */
+ public function testIncrementDateWithFifteenMinuteOffsetTimezone()
+ {
+ $tz = date_default_timezone_get();
+ date_default_timezone_set('Asia/Kathmandu');
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f = new HoursField();
+ $f->increment($d);
+ $this->assertEquals('2011-03-15 12:00:00', $d->format('Y-m-d H:i:s'));
+
+ $d->setTime(11, 15, 0);
+ $f->increment($d, true);
+ $this->assertEquals('2011-03-15 10:59:00', $d->format('Y-m-d H:i:s'));
+ date_default_timezone_set($tz);
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/tests/Cron/MinutesFieldTest.php b/vendor/mtdowling/cron-expression/tests/Cron/MinutesFieldTest.php
new file mode 100644
index 000000000..af3fef7ff
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/tests/Cron/MinutesFieldTest.php
@@ -0,0 +1,37 @@
+
+ */
+class MinutesFieldTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Cron\MinutesField::validate
+ */
+ public function testValidatesField()
+ {
+ $f = new MinutesField();
+ $this->assertTrue($f->validate('1'));
+ $this->assertTrue($f->validate('*'));
+ $this->assertTrue($f->validate('*/3,1,1-12'));
+ }
+
+ /**
+ * @covers Cron\MinutesField::increment
+ */
+ public function testIncrementsDate()
+ {
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f = new MinutesField();
+ $f->increment($d);
+ $this->assertEquals('2011-03-15 11:16:00', $d->format('Y-m-d H:i:s'));
+ $f->increment($d, true);
+ $this->assertEquals('2011-03-15 11:15:00', $d->format('Y-m-d H:i:s'));
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/tests/Cron/MonthFieldTest.php b/vendor/mtdowling/cron-expression/tests/Cron/MonthFieldTest.php
new file mode 100644
index 000000000..2d9b0ad2d
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/tests/Cron/MonthFieldTest.php
@@ -0,0 +1,81 @@
+
+ */
+class MonthFieldTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Cron\MonthField::validate
+ */
+ public function testValidatesField()
+ {
+ $f = new MonthField();
+ $this->assertTrue($f->validate('12'));
+ $this->assertTrue($f->validate('*'));
+ $this->assertTrue($f->validate('*/10,2,1-12'));
+ $this->assertFalse($f->validate('1.fix-regexp'));
+ }
+
+ /**
+ * @covers Cron\MonthField::increment
+ */
+ public function testIncrementsDate()
+ {
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f = new MonthField();
+ $f->increment($d);
+ $this->assertEquals('2011-04-01 00:00:00', $d->format('Y-m-d H:i:s'));
+
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f->increment($d, true);
+ $this->assertEquals('2011-02-28 23:59:00', $d->format('Y-m-d H:i:s'));
+ }
+
+ /**
+ * @covers Cron\MonthField::increment
+ */
+ public function testIncrementsDateWithThirtyMinuteTimezone()
+ {
+ $tz = date_default_timezone_get();
+ date_default_timezone_set('America/St_Johns');
+ $d = new DateTime('2011-03-31 11:59:59');
+ $f = new MonthField();
+ $f->increment($d);
+ $this->assertEquals('2011-04-01 00:00:00', $d->format('Y-m-d H:i:s'));
+
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f->increment($d, true);
+ $this->assertEquals('2011-02-28 23:59:00', $d->format('Y-m-d H:i:s'));
+ date_default_timezone_set($tz);
+ }
+
+
+ /**
+ * @covers Cron\MonthField::increment
+ */
+ public function testIncrementsYearAsNeeded()
+ {
+ $f = new MonthField();
+ $d = new DateTime('2011-12-15 00:00:00');
+ $f->increment($d);
+ $this->assertEquals('2012-01-01 00:00:00', $d->format('Y-m-d H:i:s'));
+ }
+
+ /**
+ * @covers Cron\MonthField::increment
+ */
+ public function testDecrementsYearAsNeeded()
+ {
+ $f = new MonthField();
+ $d = new DateTime('2011-01-15 00:00:00');
+ $f->increment($d, true);
+ $this->assertEquals('2010-12-31 23:59:00', $d->format('Y-m-d H:i:s'));
+ }
+}
diff --git a/vendor/mtdowling/cron-expression/tests/Cron/YearFieldTest.php b/vendor/mtdowling/cron-expression/tests/Cron/YearFieldTest.php
new file mode 100644
index 000000000..b5059ecec
--- /dev/null
+++ b/vendor/mtdowling/cron-expression/tests/Cron/YearFieldTest.php
@@ -0,0 +1,37 @@
+
+ */
+class YearFieldTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @covers Cron\YearField::validate
+ */
+ public function testValidatesField()
+ {
+ $f = new YearField();
+ $this->assertTrue($f->validate('2011'));
+ $this->assertTrue($f->validate('*'));
+ $this->assertTrue($f->validate('*/10,2012,1-12'));
+ }
+
+ /**
+ * @covers Cron\YearField::increment
+ */
+ public function testIncrementsDate()
+ {
+ $d = new DateTime('2011-03-15 11:15:00');
+ $f = new YearField();
+ $f->increment($d);
+ $this->assertEquals('2012-01-01 00:00:00', $d->format('Y-m-d H:i:s'));
+ $f->increment($d, true);
+ $this->assertEquals('2011-12-31 23:59:00', $d->format('Y-m-d H:i:s'));
+ }
+}
diff --git a/vendor/myclabs/deep-copy/.gitattributes b/vendor/myclabs/deep-copy/.gitattributes
new file mode 100644
index 000000000..8018068b4
--- /dev/null
+++ b/vendor/myclabs/deep-copy/.gitattributes
@@ -0,0 +1,7 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+*.png binary
+
+tests/ export-ignore
+phpunit.xml.dist export-ignore
diff --git a/vendor/myclabs/deep-copy/.gitignore b/vendor/myclabs/deep-copy/.gitignore
new file mode 100644
index 000000000..eef72f754
--- /dev/null
+++ b/vendor/myclabs/deep-copy/.gitignore
@@ -0,0 +1,3 @@
+/composer.phar
+/composer.lock
+/vendor/*
diff --git a/vendor/myclabs/deep-copy/.travis.yml b/vendor/myclabs/deep-copy/.travis.yml
new file mode 100644
index 000000000..89dc02af6
--- /dev/null
+++ b/vendor/myclabs/deep-copy/.travis.yml
@@ -0,0 +1,40 @@
+language: php
+
+sudo: false
+
+php:
+ - '5.6'
+ - '7.0'
+ - '7.1'
+ - nightly
+
+matrix:
+ fast_finish: true
+ include:
+ - php: '5.6'
+ env: COMPOSER_FLAGS="--prefer-lowest"
+ allow_failures:
+ - php: nightly
+
+cache:
+ directories:
+ - $HOME/.composer/cache/files
+
+before_install:
+ - |
+ if [ "$TRAVIS_PHP_VERSION" = "nightly" ]; then
+ COMPOSER_FLAGS="$COMPOSER_FLAGS --ignore-platform-reqs"
+ fi;
+
+install:
+ - composer update --no-interaction --no-progress --no-suggest --prefer-dist $COMPOSER_FLAGS
+ - wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.0/coveralls.phar
+
+before_script:
+ - mkdir -p build/logs
+
+script:
+ - vendor/bin/phpunit --coverage-clover build/logs/clover.xml
+
+after_script:
+ - php coveralls.phar -v
diff --git a/vendor/myclabs/deep-copy/LICENSE b/vendor/myclabs/deep-copy/LICENSE
new file mode 100644
index 000000000..c3e835001
--- /dev/null
+++ b/vendor/myclabs/deep-copy/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 My C-Sense
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/myclabs/deep-copy/README.md b/vendor/myclabs/deep-copy/README.md
new file mode 100644
index 000000000..7f010df2a
--- /dev/null
+++ b/vendor/myclabs/deep-copy/README.md
@@ -0,0 +1,372 @@
+# DeepCopy
+
+DeepCopy helps you create deep copies (clones) of your objects. It is designed to handle cycles in the association graph.
+
+[](https://travis-ci.org/myclabs/DeepCopy)
+[](https://coveralls.io/r/myclabs/DeepCopy?branch=master)
+[](https://scrutinizer-ci.com/g/myclabs/DeepCopy/)
+[](https://packagist.org/packages/myclabs/deep-copy)
+
+
+## Table of Contents
+
+1. [How](#how)
+1. [Why](#why)
+ 1. [Using simply `clone`](#using-simply-clone)
+ 1. [Overridding `__clone()`](#overridding-__clone)
+ 1. [With `DeepCopy`](#with-deepcopy)
+1. [How it works](#how-it-works)
+1. [Going further](#going-further)
+ 1. [Matchers](#matchers)
+ 1. [Property name](#property-name)
+ 1. [Specific property](#specific-property)
+ 1. [Type](#type)
+ 1. [Filters](#filters)
+ 1. [`SetNullFilter`](#setnullfilter-filter)
+ 1. [`KeepFilter`](#keepfilter-filter)
+ 1. [`DoctrineCollectionFilter`](#doctrinecollectionfilter-filter)
+ 1. [`DoctrineEmptyCollectionFilter`](#doctrineemptycollectionfilter-filter)
+ 1. [`DoctrineProxyFilter`](#doctrineproxyfilter-filter)
+ 1. [`ReplaceFilter`](#replacefilter-type-filter)
+ 1. [`ShallowCopyFilter`](#doctrinecollectionfilter-type-filter)
+1. [Edge cases](#edge-cases)
+1. [Contributing](#contributing)
+ 1. [Tests](#tests)
+
+
+## How?
+
+Install with Composer:
+
+```json
+composer require myclabs/deep-copy
+```
+
+Use simply:
+
+```php
+use DeepCopy\DeepCopy;
+
+$copier = new DeepCopy();
+$myCopy = $copier->copy($myObject);
+```
+
+
+## Why?
+
+- How do you create copies of your objects?
+
+```php
+$myCopy = clone $myObject;
+```
+
+- How do you create **deep** copies of your objects (i.e. copying also all the objects referenced in the properties)?
+
+You use [`__clone()`](http://www.php.net/manual/en/language.oop5.cloning.php#object.clone) and implement the behavior
+yourself.
+
+- But how do you handle **cycles** in the association graph?
+
+Now you're in for a big mess :(
+
+
+
+
+### Using simply `clone`
+
+
+
+
+### Overridding `__clone()`
+
+
+
+
+### With `DeepCopy`
+
+
+
+
+## How it works
+
+DeepCopy recursively traverses all the object's properties and clones them. To avoid cloning the same object twice it
+keeps a hash map of all instances and thus preserves the object graph.
+
+To use it:
+
+```php
+use function DeepCopy\deep_copy;
+
+$copy = deep_copy($var);
+```
+
+Alternatively, you can create your own `DeepCopy` instance to configure it differently for example:
+
+```php
+use DeepCopy\DeepCopy;
+
+$copier = new DeepCopy(true);
+
+$copy = $copier->copy($var);
+```
+
+You may want to roll your own deep copy function:
+
+```php
+namespace Acme;
+
+use DeepCopy\DeepCopy;
+
+function deep_copy($var)
+{
+ static $copier = null;
+
+ if (null === $copier) {
+ $copier = new DeepCopy(true);
+ }
+
+ return $copier->copy($var);
+}
+```
+
+
+## Going further
+
+You can add filters to customize the copy process.
+
+The method to add a filter is `DeepCopy\DeepCopy::addFilter($filter, $matcher)`,
+with `$filter` implementing `DeepCopy\Filter\Filter`
+and `$matcher` implementing `DeepCopy\Matcher\Matcher`.
+
+We provide some generic filters and matchers.
+
+
+### Matchers
+
+ - `DeepCopy\Matcher` applies on a object attribute.
+ - `DeepCopy\TypeMatcher` applies on any element found in graph, including array elements.
+
+
+#### Property name
+
+The `PropertyNameMatcher` will match a property by its name:
+
+```php
+use DeepCopy\Matcher\PropertyNameMatcher;
+
+// Will apply a filter to any property of any objects named "id"
+$matcher = new PropertyNameMatcher('id');
+```
+
+
+#### Specific property
+
+The `PropertyMatcher` will match a specific property of a specific class:
+
+```php
+use DeepCopy\Matcher\PropertyMatcher;
+
+// Will apply a filter to the property "id" of any objects of the class "MyClass"
+$matcher = new PropertyMatcher('MyClass', 'id');
+```
+
+
+#### Type
+
+The `TypeMatcher` will match any element by its type (instance of a class or any value that could be parameter of
+[gettype()](http://php.net/manual/en/function.gettype.php) function):
+
+```php
+use DeepCopy\TypeMatcher\TypeMatcher;
+
+// Will apply a filter to any object that is an instance of Doctrine\Common\Collections\Collection
+$matcher = new TypeMatcher('Doctrine\Common\Collections\Collection');
+```
+
+
+### Filters
+
+- `DeepCopy\Filter` applies a transformation to the object attribute matched by `DeepCopy\Matcher`
+- `DeepCopy\TypeFilter` applies a transformation to any element matched by `DeepCopy\TypeMatcher`
+
+
+#### `SetNullFilter` (filter)
+
+Let's say for example that you are copying a database record (or a Doctrine entity), so you want the copy not to have
+any ID:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\SetNullFilter;
+use DeepCopy\Matcher\PropertyNameMatcher;
+
+$object = MyClass::load(123);
+echo $object->id; // 123
+
+$copier = new DeepCopy();
+$copier->addFilter(new SetNullFilter(), new PropertyNameMatcher('id'));
+
+$copy = $copier->copy($object);
+
+echo $copy->id; // null
+```
+
+
+#### `KeepFilter` (filter)
+
+If you want a property to remain untouched (for example, an association to an object):
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\KeepFilter;
+use DeepCopy\Matcher\PropertyMatcher;
+
+$copier = new DeepCopy();
+$copier->addFilter(new KeepFilter(), new PropertyMatcher('MyClass', 'category'));
+
+$copy = $copier->copy($object);
+// $copy->category has not been touched
+```
+
+
+#### `DoctrineCollectionFilter` (filter)
+
+If you use Doctrine and want to copy an entity, you will need to use the `DoctrineCollectionFilter`:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter;
+use DeepCopy\Matcher\PropertyTypeMatcher;
+
+$copier = new DeepCopy();
+$copier->addFilter(new DoctrineCollectionFilter(), new PropertyTypeMatcher('Doctrine\Common\Collections\Collection'));
+
+$copy = $copier->copy($object);
+```
+
+
+#### `DoctrineEmptyCollectionFilter` (filter)
+
+If you use Doctrine and want to copy an entity who contains a `Collection` that you want to be reset, you can use the
+`DoctrineEmptyCollectionFilter`
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\Doctrine\DoctrineEmptyCollectionFilter;
+use DeepCopy\Matcher\PropertyMatcher;
+
+$copier = new DeepCopy();
+$copier->addFilter(new DoctrineEmptyCollectionFilter(), new PropertyMatcher('MyClass', 'myProperty'));
+
+$copy = $copier->copy($object);
+
+// $copy->myProperty will return an empty collection
+```
+
+
+#### `DoctrineProxyFilter` (filter)
+
+If you use Doctrine and use cloning on lazy loaded entities, you might encounter errors mentioning missing fields on a
+Doctrine proxy class (...\\\_\_CG\_\_\Proxy).
+You can use the `DoctrineProxyFilter` to load the actual entity behind the Doctrine proxy class.
+**Make sure, though, to put this as one of your very first filters in the filter chain so that the entity is loaded
+before other filters are applied!**
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\Doctrine\DoctrineProxyFilter;
+use DeepCopy\Matcher\Doctrine\DoctrineProxyMatcher;
+
+$copier = new DeepCopy();
+$copier->addFilter(new DoctrineProxyFilter(), new DoctrineProxyMatcher());
+
+$copy = $copier->copy($object);
+
+// $copy should now contain a clone of all entities, including those that were not yet fully loaded.
+```
+
+
+#### `ReplaceFilter` (type filter)
+
+1. If you want to replace the value of a property:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\Filter\ReplaceFilter;
+use DeepCopy\Matcher\PropertyMatcher;
+
+$copier = new DeepCopy();
+$callback = function ($currentValue) {
+ return $currentValue . ' (copy)'
+};
+$copier->addFilter(new ReplaceFilter($callback), new PropertyMatcher('MyClass', 'title'));
+
+$copy = $copier->copy($object);
+
+// $copy->title will contain the data returned by the callback, e.g. 'The title (copy)'
+```
+
+2. If you want to replace whole element:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\TypeFilter\ReplaceFilter;
+use DeepCopy\TypeMatcher\TypeMatcher;
+
+$copier = new DeepCopy();
+$callback = function (MyClass $myClass) {
+ return get_class($myClass);
+};
+$copier->addTypeFilter(new ReplaceFilter($callback), new TypeMatcher('MyClass'));
+
+$copy = $copier->copy([new MyClass, 'some string', new MyClass]);
+
+// $copy will contain ['MyClass', 'some string', 'MyClass']
+```
+
+
+The `$callback` parameter of the `ReplaceFilter` constructor accepts any PHP callable.
+
+
+#### `ShallowCopyFilter` (type filter)
+
+Stop *DeepCopy* from recursively copying element, using standard `clone` instead:
+
+```php
+use DeepCopy\DeepCopy;
+use DeepCopy\TypeFilter\ShallowCopyFilter;
+use DeepCopy\TypeMatcher\TypeMatcher;
+use Mockery as m;
+
+$this->deepCopy = new DeepCopy();
+$this->deepCopy->addTypeFilter(
+ new ShallowCopyFilter,
+ new TypeMatcher(m\MockInterface::class)
+);
+
+$myServiceWithMocks = new MyService(m::mock(MyDependency1::class), m::mock(MyDependency2::class));
+// All mocks will be just cloned, not deep copied
+```
+
+
+## Edge cases
+
+The following structures cannot be deep-copied with PHP Reflection. As a result they are shallow cloned and filters are
+not applied. There is two ways for you to handle them:
+
+- Implement your own `__clone()` method
+- Use a filter with a type matcher
+
+
+## Contributing
+
+DeepCopy is distributed under the MIT license.
+
+
+### Tests
+
+Running the tests is simple:
+
+```php
+vendor/bin/phpunit
+```
diff --git a/vendor/myclabs/deep-copy/composer.json b/vendor/myclabs/deep-copy/composer.json
new file mode 100644
index 000000000..d5d3a7798
--- /dev/null
+++ b/vendor/myclabs/deep-copy/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "myclabs/deep-copy",
+ "type": "library",
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": ["clone", "copy", "duplicate", "object", "object graph"],
+ "license": "MIT",
+
+ "autoload": {
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ },
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ]
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "DeepCopy\\": "fixtures/",
+ "DeepCopyTest\\": "tests/DeepCopyTest/"
+ }
+ },
+
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.0",
+ "doctrine/common": "^2.6",
+ "phpunit/phpunit": "^4.1"
+ },
+
+ "config": {
+ "sort-packages": true
+ }
+}
diff --git a/vendor/myclabs/deep-copy/doc/clone.png b/vendor/myclabs/deep-copy/doc/clone.png
new file mode 100644
index 000000000..376afd491
Binary files /dev/null and b/vendor/myclabs/deep-copy/doc/clone.png differ
diff --git a/vendor/myclabs/deep-copy/doc/deep-clone.png b/vendor/myclabs/deep-copy/doc/deep-clone.png
new file mode 100644
index 000000000..2b37a6d7d
Binary files /dev/null and b/vendor/myclabs/deep-copy/doc/deep-clone.png differ
diff --git a/vendor/myclabs/deep-copy/doc/deep-copy.png b/vendor/myclabs/deep-copy/doc/deep-copy.png
new file mode 100644
index 000000000..68c508ae4
Binary files /dev/null and b/vendor/myclabs/deep-copy/doc/deep-copy.png differ
diff --git a/vendor/myclabs/deep-copy/doc/graph.png b/vendor/myclabs/deep-copy/doc/graph.png
new file mode 100644
index 000000000..4d5c9428f
Binary files /dev/null and b/vendor/myclabs/deep-copy/doc/graph.png differ
diff --git a/vendor/myclabs/deep-copy/fixtures/f001/A.php b/vendor/myclabs/deep-copy/fixtures/f001/A.php
new file mode 100644
index 000000000..648d5dfff
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f001/A.php
@@ -0,0 +1,20 @@
+aProp;
+ }
+
+ public function setAProp($prop)
+ {
+ $this->aProp = $prop;
+
+ return $this;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/fixtures/f001/B.php b/vendor/myclabs/deep-copy/fixtures/f001/B.php
new file mode 100644
index 000000000..462bb44e8
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f001/B.php
@@ -0,0 +1,20 @@
+bProp;
+ }
+
+ public function setBProp($prop)
+ {
+ $this->bProp = $prop;
+
+ return $this;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/fixtures/f002/A.php b/vendor/myclabs/deep-copy/fixtures/f002/A.php
new file mode 100644
index 000000000..d9aa5c35b
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f002/A.php
@@ -0,0 +1,33 @@
+prop1;
+ }
+
+ public function setProp1($prop)
+ {
+ $this->prop1 = $prop;
+
+ return $this;
+ }
+
+ public function getProp2()
+ {
+ return $this->prop2;
+ }
+
+ public function setProp2($prop)
+ {
+ $this->prop2 = $prop;
+
+ return $this;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/fixtures/f003/Foo.php b/vendor/myclabs/deep-copy/fixtures/f003/Foo.php
new file mode 100644
index 000000000..9cd76224a
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f003/Foo.php
@@ -0,0 +1,26 @@
+name = $name;
+ }
+
+ public function getProp()
+ {
+ return $this->prop;
+ }
+
+ public function setProp($prop)
+ {
+ $this->prop = $prop;
+
+ return $this;
+ }
+}
\ No newline at end of file
diff --git a/vendor/myclabs/deep-copy/fixtures/f004/UnclonableItem.php b/vendor/myclabs/deep-copy/fixtures/f004/UnclonableItem.php
new file mode 100644
index 000000000..82c6c67cd
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f004/UnclonableItem.php
@@ -0,0 +1,13 @@
+cloned = true;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/fixtures/f006/A.php b/vendor/myclabs/deep-copy/fixtures/f006/A.php
new file mode 100644
index 000000000..d9efb1166
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f006/A.php
@@ -0,0 +1,26 @@
+aProp;
+ }
+
+ public function setAProp($prop)
+ {
+ $this->aProp = $prop;
+
+ return $this;
+ }
+
+ public function __clone()
+ {
+ $this->cloned = true;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/fixtures/f006/B.php b/vendor/myclabs/deep-copy/fixtures/f006/B.php
new file mode 100644
index 000000000..1f80b3d44
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f006/B.php
@@ -0,0 +1,26 @@
+bProp;
+ }
+
+ public function setBProp($prop)
+ {
+ $this->bProp = $prop;
+
+ return $this;
+ }
+
+ public function __clone()
+ {
+ $this->cloned = true;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/fixtures/f007/FooDateInterval.php b/vendor/myclabs/deep-copy/fixtures/f007/FooDateInterval.php
new file mode 100644
index 000000000..e16bc6aa6
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f007/FooDateInterval.php
@@ -0,0 +1,15 @@
+cloned = true;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/fixtures/f007/FooDateTimeZone.php b/vendor/myclabs/deep-copy/fixtures/f007/FooDateTimeZone.php
new file mode 100644
index 000000000..6f4e61fe9
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f007/FooDateTimeZone.php
@@ -0,0 +1,15 @@
+cloned = true;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/fixtures/f008/A.php b/vendor/myclabs/deep-copy/fixtures/f008/A.php
new file mode 100644
index 000000000..88471d013
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f008/A.php
@@ -0,0 +1,18 @@
+foo = $foo;
+ }
+
+ public function getFoo()
+ {
+ return $this->foo;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/fixtures/f008/B.php b/vendor/myclabs/deep-copy/fixtures/f008/B.php
new file mode 100644
index 000000000..6053092d7
--- /dev/null
+++ b/vendor/myclabs/deep-copy/fixtures/f008/B.php
@@ -0,0 +1,7 @@
+ Filter, 'matcher' => Matcher] pairs.
+ */
+ private $filters = [];
+
+ /**
+ * Type Filters to apply.
+ *
+ * @var array Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
+ */
+ private $typeFilters = [];
+
+ /**
+ * @var bool
+ */
+ private $skipUncloneable = false;
+
+ /**
+ * @var bool
+ */
+ private $useCloneMethod;
+
+ /**
+ * @param bool $useCloneMethod If set to true, when an object implements the __clone() function, it will be used
+ * instead of the regular deep cloning.
+ */
+ public function __construct($useCloneMethod = false)
+ {
+ $this->useCloneMethod = $useCloneMethod;
+
+ $this->addTypeFilter(new DateIntervalFilter(), new TypeMatcher(DateInterval::class));
+ $this->addTypeFilter(new SplDoublyLinkedListFilter($this), new TypeMatcher(SplDoublyLinkedList::class));
+ }
+
+ /**
+ * If enabled, will not throw an exception when coming across an uncloneable property.
+ *
+ * @param $skipUncloneable
+ *
+ * @return $this
+ */
+ public function skipUncloneable($skipUncloneable = true)
+ {
+ $this->skipUncloneable = $skipUncloneable;
+
+ return $this;
+ }
+
+ /**
+ * Deep copies the given object.
+ *
+ * @param mixed $object
+ *
+ * @return mixed
+ */
+ public function copy($object)
+ {
+ $this->hashMap = [];
+
+ return $this->recursiveCopy($object);
+ }
+
+ public function addFilter(Filter $filter, Matcher $matcher)
+ {
+ $this->filters[] = [
+ 'matcher' => $matcher,
+ 'filter' => $filter,
+ ];
+ }
+
+ public function addTypeFilter(TypeFilter $filter, TypeMatcher $matcher)
+ {
+ $this->typeFilters[] = [
+ 'matcher' => $matcher,
+ 'filter' => $filter,
+ ];
+ }
+
+ private function recursiveCopy($var)
+ {
+ // Matches Type Filter
+ if ($filter = $this->getFirstMatchedTypeFilter($this->typeFilters, $var)) {
+ return $filter->apply($var);
+ }
+
+ // Resource
+ if (is_resource($var)) {
+ return $var;
+ }
+
+ // Array
+ if (is_array($var)) {
+ return $this->copyArray($var);
+ }
+
+ // Scalar
+ if (! is_object($var)) {
+ return $var;
+ }
+
+ // Object
+ return $this->copyObject($var);
+ }
+
+ /**
+ * Copy an array
+ * @param array $array
+ * @return array
+ */
+ private function copyArray(array $array)
+ {
+ foreach ($array as $key => $value) {
+ $array[$key] = $this->recursiveCopy($value);
+ }
+
+ return $array;
+ }
+
+ /**
+ * Copies an object.
+ *
+ * @param object $object
+ *
+ * @throws CloneException
+ *
+ * @return object
+ */
+ private function copyObject($object)
+ {
+ $objectHash = spl_object_hash($object);
+
+ if (isset($this->hashMap[$objectHash])) {
+ return $this->hashMap[$objectHash];
+ }
+
+ $reflectedObject = new ReflectionObject($object);
+ $isCloneable = $reflectedObject->isCloneable();
+
+ if (false === $isCloneable) {
+ if ($this->skipUncloneable) {
+ $this->hashMap[$objectHash] = $object;
+
+ return $object;
+ }
+
+ throw new CloneException(
+ sprintf(
+ 'The class "%s" is not cloneable.',
+ $reflectedObject->getName()
+ )
+ );
+ }
+
+ $newObject = clone $object;
+ $this->hashMap[$objectHash] = $newObject;
+
+ if ($this->useCloneMethod && $reflectedObject->hasMethod('__clone')) {
+ return $newObject;
+ }
+
+ if ($newObject instanceof DateTimeInterface || $newObject instanceof DateTimeZone) {
+ return $newObject;
+ }
+
+ foreach (ReflectionHelper::getProperties($reflectedObject) as $property) {
+ $this->copyObjectProperty($newObject, $property);
+ }
+
+ return $newObject;
+ }
+
+ private function copyObjectProperty($object, ReflectionProperty $property)
+ {
+ // Ignore static properties
+ if ($property->isStatic()) {
+ return;
+ }
+
+ // Apply the filters
+ foreach ($this->filters as $item) {
+ /** @var Matcher $matcher */
+ $matcher = $item['matcher'];
+ /** @var Filter $filter */
+ $filter = $item['filter'];
+
+ if ($matcher->matches($object, $property->getName())) {
+ $filter->apply(
+ $object,
+ $property->getName(),
+ function ($object) {
+ return $this->recursiveCopy($object);
+ }
+ );
+
+ // If a filter matches, we stop processing this property
+ return;
+ }
+ }
+
+ $property->setAccessible(true);
+ $propertyValue = $property->getValue($object);
+
+ // Copy the property
+ $property->setValue($object, $this->recursiveCopy($propertyValue));
+ }
+
+ /**
+ * Returns first filter that matches variable, `null` if no such filter found.
+ *
+ * @param array $filterRecords Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and
+ * 'matcher' with value of type {@see TypeMatcher}
+ * @param mixed $var
+ *
+ * @return TypeFilter|null
+ */
+ private function getFirstMatchedTypeFilter(array $filterRecords, $var)
+ {
+ $matched = $this->first(
+ $filterRecords,
+ function (array $record) use ($var) {
+ /* @var TypeMatcher $matcher */
+ $matcher = $record['matcher'];
+
+ return $matcher->matches($var);
+ }
+ );
+
+ return isset($matched) ? $matched['filter'] : null;
+ }
+
+ /**
+ * Returns first element that matches predicate, `null` if no such element found.
+ *
+ * @param array $elements Array of ['filter' => Filter, 'matcher' => Matcher] pairs.
+ * @param callable $predicate Predicate arguments are: element.
+ *
+ * @return array|null Associative array with 2 members: 'filter' with value of type {@see TypeFilter} and 'matcher'
+ * with value of type {@see TypeMatcher} or `null`.
+ */
+ private function first(array $elements, callable $predicate)
+ {
+ foreach ($elements as $element) {
+ if (call_user_func($predicate, $element)) {
+ return $element;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php b/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php
new file mode 100644
index 000000000..c046706a2
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Exception/CloneException.php
@@ -0,0 +1,9 @@
+setAccessible(true);
+ $oldCollection = $reflectionProperty->getValue($object);
+
+ $newCollection = $oldCollection->map(
+ function ($item) use ($objectCopier) {
+ return $objectCopier($item);
+ }
+ );
+
+ $reflectionProperty->setValue($object, $newCollection);
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php
new file mode 100644
index 000000000..7b33fd547
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineEmptyCollectionFilter.php
@@ -0,0 +1,28 @@
+setAccessible(true);
+
+ $reflectionProperty->setValue($object, new ArrayCollection());
+ }
+}
\ No newline at end of file
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php
new file mode 100644
index 000000000..8bee8f769
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Doctrine/DoctrineProxyFilter.php
@@ -0,0 +1,22 @@
+__load();
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php
new file mode 100644
index 000000000..85ba18ce1
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/Filter.php
@@ -0,0 +1,18 @@
+callback = $callable;
+ }
+
+ /**
+ * Replaces the object property by the result of the callback called with the object property.
+ *
+ * {@inheritdoc}
+ */
+ public function apply($object, $property, $objectCopier)
+ {
+ $reflectionProperty = ReflectionHelper::getProperty($object, $property);
+ $reflectionProperty->setAccessible(true);
+
+ $value = call_user_func($this->callback, $reflectionProperty->getValue($object));
+
+ $reflectionProperty->setValue($object, $value);
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php
new file mode 100644
index 000000000..bea86b884
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Filter/SetNullFilter.php
@@ -0,0 +1,24 @@
+setAccessible(true);
+ $reflectionProperty->setValue($object, null);
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php
new file mode 100644
index 000000000..ec8856f50
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/Doctrine/DoctrineProxyMatcher.php
@@ -0,0 +1,22 @@
+class = $class;
+ $this->property = $property;
+ }
+
+ /**
+ * Matches a specific property of a specific class.
+ *
+ * {@inheritdoc}
+ */
+ public function matches($object, $property)
+ {
+ return ($object instanceof $this->class) && $property == $this->property;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php
new file mode 100644
index 000000000..c8ec0d2bc
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyNameMatcher.php
@@ -0,0 +1,32 @@
+property = $property;
+ }
+
+ /**
+ * Matches a property by its name.
+ *
+ * {@inheritdoc}
+ */
+ public function matches($object, $property)
+ {
+ return $property == $this->property;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php
new file mode 100644
index 000000000..a6b0c0bc5
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Matcher/PropertyTypeMatcher.php
@@ -0,0 +1,46 @@
+propertyType = $propertyType;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function matches($object, $property)
+ {
+ try {
+ $reflectionProperty = ReflectionHelper::getProperty($object, $property);
+ } catch (ReflectionException $exception) {
+ return false;
+ }
+
+ $reflectionProperty->setAccessible(true);
+
+ return $reflectionProperty->getValue($object) instanceof $this->propertyType;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php b/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php
new file mode 100644
index 000000000..742410cb2
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/Reflection/ReflectionHelper.php
@@ -0,0 +1,78 @@
+getProperties() does not return private properties from ancestor classes.
+ *
+ * @author muratyaman@gmail.com
+ * @see http://php.net/manual/en/reflectionclass.getproperties.php
+ *
+ * @param ReflectionClass $ref
+ *
+ * @return ReflectionProperty[]
+ */
+ public static function getProperties(ReflectionClass $ref)
+ {
+ $props = $ref->getProperties();
+ $propsArr = array();
+
+ foreach ($props as $prop) {
+ $propertyName = $prop->getName();
+ $propsArr[$propertyName] = $prop;
+ }
+
+ if ($parentClass = $ref->getParentClass()) {
+ $parentPropsArr = self::getProperties($parentClass);
+ foreach ($propsArr as $key => $property) {
+ $parentPropsArr[$key] = $property;
+ }
+
+ return $parentPropsArr;
+ }
+
+ return $propsArr;
+ }
+
+ /**
+ * Retrieves property by name from object and all its ancestors.
+ *
+ * @param object|string $object
+ * @param string $name
+ *
+ * @throws PropertyException
+ * @throws ReflectionException
+ *
+ * @return ReflectionProperty
+ */
+ public static function getProperty($object, $name)
+ {
+ $reflection = is_object($object) ? new ReflectionObject($object) : new ReflectionClass($object);
+
+ if ($reflection->hasProperty($name)) {
+ return $reflection->getProperty($name);
+ }
+
+ if ($parentClass = $reflection->getParentClass()) {
+ return self::getProperty($parentClass->getName(), $name);
+ }
+
+ throw new PropertyException(
+ sprintf(
+ 'The class "%s" doesn\'t have a property with the given name: "%s".',
+ is_object($object) ? get_class($object) : $object,
+ $name
+ )
+ );
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php
new file mode 100644
index 000000000..becd1cfff
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/Date/DateIntervalFilter.php
@@ -0,0 +1,33 @@
+ $propertyValue) {
+ $copy->{$propertyName} = $propertyValue;
+ }
+
+ return $copy;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php
new file mode 100644
index 000000000..164f8b8e2
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ReplaceFilter.php
@@ -0,0 +1,30 @@
+callback = $callable;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function apply($element)
+ {
+ return call_user_func($this->callback, $element);
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php
new file mode 100644
index 000000000..a5fbd7a2b
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/ShallowCopyFilter.php
@@ -0,0 +1,17 @@
+copier = $copier;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function apply($element)
+ {
+ $newElement = clone $element;
+
+ $copy = $this->createCopyClosure();
+
+ return $copy($newElement);
+ }
+
+ private function createCopyClosure()
+ {
+ $copier = $this->copier;
+
+ $copy = function (SplDoublyLinkedList $list) use ($copier) {
+ // Replace each element in the list with a deep copy of itself
+ for ($i = 1; $i <= $list->count(); $i++) {
+ $copy = $copier->recursiveCopy($list->shift());
+
+ $list->push($copy);
+ }
+
+ return $list;
+ };
+
+ return Closure::bind($copy, null, DeepCopy::class);
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php
new file mode 100644
index 000000000..5785a7da9
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/TypeFilter/TypeFilter.php
@@ -0,0 +1,13 @@
+type = $type;
+ }
+
+ /**
+ * @param mixed $element
+ *
+ * @return boolean
+ */
+ public function matches($element)
+ {
+ return is_object($element) ? is_a($element, $this->type) : gettype($element) === $this->type;
+ }
+}
diff --git a/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php b/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php
new file mode 100644
index 000000000..272652ca5
--- /dev/null
+++ b/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php
@@ -0,0 +1,16 @@
+copy($value);
+}
diff --git a/vendor/nesbot/carbon/LICENSE b/vendor/nesbot/carbon/LICENSE
new file mode 100644
index 000000000..6de45ebf8
--- /dev/null
+++ b/vendor/nesbot/carbon/LICENSE
@@ -0,0 +1,19 @@
+Copyright (C) Brian Nesbitt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/nesbot/carbon/bin/upgrade-carbon b/vendor/nesbot/carbon/bin/upgrade-carbon
new file mode 100644
index 000000000..49c4c9a80
--- /dev/null
+++ b/vendor/nesbot/carbon/bin/upgrade-carbon
@@ -0,0 +1,34 @@
+#!/usr/bin/env php
+=5.3.9",
+ "kylekatarnls/update-helper": "^1.1",
+ "symfony/translation": "~2.6 || ~3.0 || ~4.0"
+ },
+ "require-dev": {
+ "composer/composer": "^1.2",
+ "friendsofphp/php-cs-fixer": "~2",
+ "phpunit/phpunit": "^4.8.35 || ^5.7"
+ },
+ "autoload": {
+ "psr-4": {
+ "": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Tests\\": "tests/"
+ }
+ },
+ "config": {
+ "sort-packages": true
+ },
+ "scripts": {
+ "test": [
+ "@phpunit",
+ "@phpcs"
+ ],
+ "phpunit": "phpunit --verbose --coverage-clover=coverage.xml",
+ "phpcs": "php-cs-fixer fix -v --diff --dry-run",
+ "phpstan": "phpstan analyse --configuration phpstan.neon --level 3 src tests",
+ "post-autoload-dump": [
+ "UpdateHelper\\UpdateHelper::check"
+ ],
+ "upgrade-carbon": [
+ "Carbon\\Upgrade::upgrade"
+ ]
+ },
+ "extra": {
+ "update-helper": "Carbon\\Upgrade",
+ "laravel": {
+ "providers": [
+ "Carbon\\Laravel\\ServiceProvider"
+ ]
+ }
+ }
+}
diff --git a/vendor/nesbot/carbon/readme.md b/vendor/nesbot/carbon/readme.md
new file mode 100644
index 000000000..5e9d1ccbc
--- /dev/null
+++ b/vendor/nesbot/carbon/readme.md
@@ -0,0 +1,94 @@
+# Carbon
+
+[](https://packagist.org/packages/nesbot/carbon)
+[](https://packagist.org/packages/nesbot/carbon)
+[](https://travis-ci.org/briannesbitt/Carbon)
+[](https://styleci.io/repos/5724990)
+[](https://codecov.io/github/briannesbitt/Carbon?branch=master)
+[](https://php-eye.com/package/nesbot/carbon)
+[](https://github.com/phpstan/phpstan)
+
+A simple PHP API extension for DateTime. [http://carbon.nesbot.com](http://carbon.nesbot.com)
+
+```php
+use Carbon\Carbon;
+
+printf("Right now is %s", Carbon::now()->toDateTimeString());
+printf("Right now in Vancouver is %s", Carbon::now('America/Vancouver')); //implicit __toString()
+$tomorrow = Carbon::now()->addDay();
+$lastWeek = Carbon::now()->subWeek();
+$nextSummerOlympics = Carbon::createFromDate(2016)->addYears(4);
+
+$officialDate = Carbon::now()->toRfc2822String();
+
+$howOldAmI = Carbon::createFromDate(1975, 5, 21)->age;
+
+$noonTodayLondonTime = Carbon::createFromTime(12, 0, 0, 'Europe/London');
+
+$internetWillBlowUpOn = Carbon::create(2038, 01, 19, 3, 14, 7, 'GMT');
+
+// Don't really want this to happen so mock now
+Carbon::setTestNow(Carbon::createFromDate(2000, 1, 1));
+
+// comparisons are always done in UTC
+if (Carbon::now()->gte($internetWillBlowUpOn)) {
+ die();
+}
+
+// Phew! Return to normal behaviour
+Carbon::setTestNow();
+
+if (Carbon::now()->isWeekend()) {
+ echo 'Party!';
+}
+echo Carbon::now()->subMinutes(2)->diffForHumans(); // '2 minutes ago'
+
+// ... but also does 'from now', 'after' and 'before'
+// rolling up to seconds, minutes, hours, days, months, years
+
+$daysSinceEpoch = Carbon::createFromTimestamp(0)->diffInDays();
+```
+
+## Installation
+
+### With Composer
+
+```
+$ composer require nesbot/carbon
+```
+
+```json
+{
+ "require": {
+ "nesbot/carbon": "~1.21"
+ }
+}
+```
+
+```php
+
+
+### Without Composer
+
+Why are you not using [composer](http://getcomposer.org/)? Download [Carbon.php](https://github.com/briannesbitt/Carbon/blob/master/src/Carbon/Carbon.php) from the repo and save the file into your project path somewhere.
+
+```php
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Carbon;
+
+use Carbon\Exceptions\InvalidDateException;
+use Closure;
+use DateInterval;
+use DatePeriod;
+use DateTime;
+use DateTimeInterface;
+use DateTimeZone;
+use InvalidArgumentException;
+use JsonSerializable;
+use Symfony\Component\Translation\TranslatorInterface;
+
+/**
+ * A simple API extension for DateTime
+ *
+ * @property int $year
+ * @property int $yearIso
+ * @property int $month
+ * @property int $day
+ * @property int $hour
+ * @property int $minute
+ * @property int $second
+ * @property int $timestamp seconds since the Unix Epoch
+ * @property \DateTimeZone $timezone the current timezone
+ * @property \DateTimeZone $tz alias of timezone
+ * @property-read int $micro
+ * @property-read int $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
+ * @property-read int $dayOfWeekIso 1 (for Monday) through 7 (for Sunday)
+ * @property-read int $dayOfYear 0 through 365
+ * @property-read int $weekOfMonth 1 through 5
+ * @property-read int $weekNumberInMonth 1 through 5
+ * @property-read int $weekOfYear ISO-8601 week number of year, weeks starting on Monday
+ * @property-read int $daysInMonth number of days in the given month
+ * @property-read int $age does a diffInYears() with default parameters
+ * @property-read int $quarter the quarter of this instance, 1 - 4
+ * @property-read int $offset the timezone offset in seconds from UTC
+ * @property-read int $offsetHours the timezone offset in hours from UTC
+ * @property-read bool $dst daylight savings time indicator, true if DST, false otherwise
+ * @property-read bool $local checks if the timezone is local, true if local, false otherwise
+ * @property-read bool $utc checks if the timezone is UTC, true if UTC, false otherwise
+ * @property-read string $timezoneName
+ * @property-read string $tzName
+ * @property-read string $englishDayOfWeek the day of week in English
+ * @property-read string $shortEnglishDayOfWeek the abbreviated day of week in English
+ * @property-read string $englishMonth the day of week in English
+ * @property-read string $shortEnglishMonth the abbreviated day of week in English
+ * @property-read string $localeDayOfWeek the day of week in current locale LC_TIME
+ * @property-read string $shortLocaleDayOfWeek the abbreviated day of week in current locale LC_TIME
+ * @property-read string $localeMonth the month in current locale LC_TIME
+ * @property-read string $shortLocaleMonth the abbreviated month in current locale LC_TIME
+ */
+class Carbon extends DateTime implements JsonSerializable
+{
+ const NO_ZERO_DIFF = 01;
+ const JUST_NOW = 02;
+ const ONE_DAY_WORDS = 04;
+ const TWO_DAY_WORDS = 010;
+
+ // Substitutes for Carbon 2 modes
+ const DIFF_RELATIVE_TO_NOW = 'relative-to-now';
+ const DIFF_RELATIVE_TO_OTHER = 'relative-to-other';
+
+ /**
+ * The day constants.
+ */
+ const SUNDAY = 0;
+ const MONDAY = 1;
+ const TUESDAY = 2;
+ const WEDNESDAY = 3;
+ const THURSDAY = 4;
+ const FRIDAY = 5;
+ const SATURDAY = 6;
+
+ /**
+ * Names of days of the week.
+ *
+ * @var array
+ */
+ protected static $days = array(
+ self::SUNDAY => 'Sunday',
+ self::MONDAY => 'Monday',
+ self::TUESDAY => 'Tuesday',
+ self::WEDNESDAY => 'Wednesday',
+ self::THURSDAY => 'Thursday',
+ self::FRIDAY => 'Friday',
+ self::SATURDAY => 'Saturday',
+ );
+
+ /**
+ * Number of X in Y.
+ */
+ const YEARS_PER_MILLENNIUM = 1000;
+ const YEARS_PER_CENTURY = 100;
+ const YEARS_PER_DECADE = 10;
+ const MONTHS_PER_YEAR = 12;
+ const MONTHS_PER_QUARTER = 3;
+ const WEEKS_PER_YEAR = 52;
+ const WEEKS_PER_MONTH = 4;
+ const DAYS_PER_WEEK = 7;
+ const HOURS_PER_DAY = 24;
+ const MINUTES_PER_HOUR = 60;
+ const SECONDS_PER_MINUTE = 60;
+ const MICROSECONDS_PER_MILLISECOND = 1000;
+ const MICROSECONDS_PER_SECOND = 1000000;
+
+ /**
+ * RFC7231 DateTime format.
+ *
+ * @var string
+ */
+ const RFC7231_FORMAT = 'D, d M Y H:i:s \G\M\T';
+
+ /**
+ * Default format to use for __toString method when type juggling occurs.
+ *
+ * @var string
+ */
+ const DEFAULT_TO_STRING_FORMAT = 'Y-m-d H:i:s';
+
+ /**
+ * Format for converting mocked time, includes microseconds.
+ *
+ * @var string
+ */
+ const MOCK_DATETIME_FORMAT = 'Y-m-d H:i:s.u';
+
+ /**
+ * Customizable PHP_INT_SIZE override.
+ *
+ * @var int
+ */
+ public static $PHPIntSize = PHP_INT_SIZE;
+
+ /**
+ * Format to use for __toString method when type juggling occurs.
+ *
+ * @var string
+ */
+ protected static $toStringFormat = self::DEFAULT_TO_STRING_FORMAT;
+
+ /**
+ * First day of week.
+ *
+ * @var int
+ */
+ protected static $weekStartsAt = self::MONDAY;
+
+ /**
+ * Last day of week.
+ *
+ * @var int
+ */
+ protected static $weekEndsAt = self::SUNDAY;
+
+ /**
+ * Days of weekend.
+ *
+ * @var array
+ */
+ protected static $weekendDays = array(
+ self::SATURDAY,
+ self::SUNDAY,
+ );
+
+ /**
+ * Midday/noon hour.
+ *
+ * @var int
+ */
+ protected static $midDayAt = 12;
+
+ /**
+ * Format regex patterns.
+ *
+ * @var array
+ */
+ protected static $regexFormats = array(
+ 'd' => '(3[01]|[12][0-9]|0[1-9])',
+ 'D' => '([a-zA-Z]{3})',
+ 'j' => '([123][0-9]|[1-9])',
+ 'l' => '([a-zA-Z]{2,})',
+ 'N' => '([1-7])',
+ 'S' => '([a-zA-Z]{2})',
+ 'w' => '([0-6])',
+ 'z' => '(36[0-5]|3[0-5][0-9]|[12][0-9]{2}|[1-9]?[0-9])',
+ 'W' => '(5[012]|[1-4][0-9]|[1-9])',
+ 'F' => '([a-zA-Z]{2,})',
+ 'm' => '(1[012]|0[1-9])',
+ 'M' => '([a-zA-Z]{3})',
+ 'n' => '(1[012]|[1-9])',
+ 't' => '(2[89]|3[01])',
+ 'L' => '(0|1)',
+ 'o' => '([1-9][0-9]{0,4})',
+ 'Y' => '([1-9]?[0-9]{4})',
+ 'y' => '([0-9]{2})',
+ 'a' => '(am|pm)',
+ 'A' => '(AM|PM)',
+ 'B' => '([0-9]{3})',
+ 'g' => '(1[012]|[1-9])',
+ 'G' => '(2[0-3]|1?[0-9])',
+ 'h' => '(1[012]|0[1-9])',
+ 'H' => '(2[0-3]|[01][0-9])',
+ 'i' => '([0-5][0-9])',
+ 's' => '([0-5][0-9])',
+ 'u' => '([0-9]{1,6})',
+ 'v' => '([0-9]{1,3})',
+ 'e' => '([a-zA-Z]{1,5})|([a-zA-Z]*\/[a-zA-Z]*)',
+ 'I' => '(0|1)',
+ 'O' => '([\+\-](1[012]|0[0-9])[0134][05])',
+ 'P' => '([\+\-](1[012]|0[0-9]):[0134][05])',
+ 'T' => '([a-zA-Z]{1,5})',
+ 'Z' => '(-?[1-5]?[0-9]{1,4})',
+ 'U' => '([0-9]*)',
+
+ // The formats below are combinations of the above formats.
+ 'c' => '(([1-9]?[0-9]{4})\-(1[012]|0[1-9])\-(3[01]|[12][0-9]|0[1-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])[\+\-](1[012]|0[0-9]):([0134][05]))', // Y-m-dTH:i:sP
+ 'r' => '(([a-zA-Z]{3}), ([123][0-9]|[1-9]) ([a-zA-Z]{3}) ([1-9]?[0-9]{4}) (2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]) [\+\-](1[012]|0[0-9])([0134][05]))', // D, j M Y H:i:s O
+ );
+
+ /**
+ * A test Carbon instance to be returned when now instances are created.
+ *
+ * @var \Carbon\Carbon
+ */
+ protected static $testNow;
+
+ /**
+ * A translator to ... er ... translate stuff.
+ *
+ * @var \Symfony\Component\Translation\TranslatorInterface
+ */
+ protected static $translator;
+
+ /**
+ * The errors that can occur.
+ *
+ * @var array
+ */
+ protected static $lastErrors;
+
+ /**
+ * The custom Carbon JSON serializer.
+ *
+ * @var callable|null
+ */
+ protected static $serializer;
+
+ /**
+ * The registered string macros.
+ *
+ * @var array
+ */
+ protected static $localMacros = array();
+
+ /**
+ * Will UTF8 encoding be used to print localized date/time ?
+ *
+ * @var bool
+ */
+ protected static $utf8 = false;
+
+ /**
+ * Add microseconds to now on PHP < 7.1 and 7.1.3. true by default.
+ *
+ * @var bool
+ */
+ protected static $microsecondsFallback = true;
+
+ /**
+ * Indicates if months should be calculated with overflow.
+ *
+ * @var bool
+ */
+ protected static $monthsOverflow = true;
+
+ /**
+ * Indicates if years should be calculated with overflow.
+ *
+ * @var bool
+ */
+ protected static $yearsOverflow = true;
+
+ /**
+ * Indicates if years are compared with month by default so isSameMonth and isSameQuarter have $ofSameYear set
+ * to true by default.
+ *
+ * @var bool
+ */
+ protected static $compareYearWithMonth = false;
+
+ /**
+ * Options for diffForHumans().
+ *
+ * @var int
+ */
+ protected static $humanDiffOptions = self::NO_ZERO_DIFF;
+
+ /**
+ * @param int $humanDiffOptions
+ */
+ public static function setHumanDiffOptions($humanDiffOptions)
+ {
+ static::$humanDiffOptions = $humanDiffOptions;
+ }
+
+ /**
+ * @param int $humanDiffOption
+ */
+ public static function enableHumanDiffOption($humanDiffOption)
+ {
+ static::$humanDiffOptions = static::getHumanDiffOptions() | $humanDiffOption;
+ }
+
+ /**
+ * @param int $humanDiffOption
+ */
+ public static function disableHumanDiffOption($humanDiffOption)
+ {
+ static::$humanDiffOptions = static::getHumanDiffOptions() & ~$humanDiffOption;
+ }
+
+ /**
+ * @return int
+ */
+ public static function getHumanDiffOptions()
+ {
+ return static::$humanDiffOptions;
+ }
+
+ /**
+ * Add microseconds to now on PHP < 7.1 and 7.1.3 if set to true,
+ * let microseconds to 0 on those PHP versions if false.
+ *
+ * @param bool $microsecondsFallback
+ */
+ public static function useMicrosecondsFallback($microsecondsFallback = true)
+ {
+ static::$microsecondsFallback = $microsecondsFallback;
+ }
+
+ /**
+ * Return true if microseconds fallback on PHP < 7.1 and 7.1.3 is
+ * enabled. false if disabled.
+ *
+ * @return bool
+ */
+ public static function isMicrosecondsFallbackEnabled()
+ {
+ return static::$microsecondsFallback;
+ }
+
+ /**
+ * Indicates if months should be calculated with overflow.
+ *
+ * @param bool $monthsOverflow
+ *
+ * @return void
+ */
+ public static function useMonthsOverflow($monthsOverflow = true)
+ {
+ static::$monthsOverflow = $monthsOverflow;
+ }
+
+ /**
+ * Reset the month overflow behavior.
+ *
+ * @return void
+ */
+ public static function resetMonthsOverflow()
+ {
+ static::$monthsOverflow = true;
+ }
+
+ /**
+ * Get the month overflow behavior.
+ *
+ * @return bool
+ */
+ public static function shouldOverflowMonths()
+ {
+ return static::$monthsOverflow;
+ }
+
+ /**
+ * Indicates if years should be calculated with overflow.
+ *
+ * @param bool $yearsOverflow
+ *
+ * @return void
+ */
+ public static function useYearsOverflow($yearsOverflow = true)
+ {
+ static::$yearsOverflow = $yearsOverflow;
+ }
+
+ /**
+ * Reset the month overflow behavior.
+ *
+ * @return void
+ */
+ public static function resetYearsOverflow()
+ {
+ static::$yearsOverflow = true;
+ }
+
+ /**
+ * Get the month overflow behavior.
+ *
+ * @return bool
+ */
+ public static function shouldOverflowYears()
+ {
+ return static::$yearsOverflow;
+ }
+
+ /**
+ * Get the month comparison default behavior.
+ *
+ * @return bool
+ */
+ public static function compareYearWithMonth($compareYearWithMonth = true)
+ {
+ static::$compareYearWithMonth = $compareYearWithMonth;
+ }
+
+ /**
+ * Get the month comparison default behavior.
+ *
+ * @return bool
+ */
+ public static function shouldCompareYearWithMonth()
+ {
+ return static::$compareYearWithMonth;
+ }
+
+ /**
+ * Creates a DateTimeZone from a string, DateTimeZone or integer offset.
+ *
+ * @param \DateTimeZone|string|int|null $object
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return \DateTimeZone
+ */
+ protected static function safeCreateDateTimeZone($object)
+ {
+ if ($object === null) {
+ // Don't return null... avoid Bug #52063 in PHP <5.3.6
+ return new DateTimeZone(date_default_timezone_get());
+ }
+
+ if ($object instanceof DateTimeZone) {
+ return $object;
+ }
+
+ if (is_numeric($object)) {
+ $tzName = timezone_name_from_abbr(null, $object * 3600, true);
+
+ if ($tzName === false) {
+ throw new InvalidArgumentException('Unknown or bad timezone ('.$object.')');
+ }
+
+ $object = $tzName;
+ }
+
+ $tz = @timezone_open($object = (string) $object);
+
+ if ($tz !== false) {
+ return $tz;
+ }
+
+ // Work-around for a bug fixed in PHP 5.5.10 https://bugs.php.net/bug.php?id=45528
+ // See: https://stackoverflow.com/q/14068594/2646927
+ // @codeCoverageIgnoreStart
+ if (strpos($object, ':') !== false) {
+ try {
+ return static::createFromFormat('O', $object)->getTimezone();
+ } catch (InvalidArgumentException $e) {
+ //
+ }
+ }
+ // @codeCoverageIgnoreEnd
+
+ throw new InvalidArgumentException('Unknown or bad timezone ('.$object.')');
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //////////////////////////// CONSTRUCTORS /////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Create a new Carbon instance.
+ *
+ * Please see the testing aids section (specifically static::setTestNow())
+ * for more on the possibility of this constructor returning a test instance.
+ *
+ * @param string|null $time
+ * @param \DateTimeZone|string|null $tz
+ */
+ public function __construct($time = null, $tz = null)
+ {
+ // If the class has a test now set and we are trying to create a now()
+ // instance then override as required
+ $isNow = empty($time) || $time === 'now';
+ if (static::hasTestNow() && ($isNow || static::hasRelativeKeywords($time))) {
+ $testInstance = clone static::getTestNow();
+
+ //shift the time according to the given time zone
+ if ($tz !== null && $tz !== static::getTestNow()->getTimezone()) {
+ $testInstance->setTimezone($tz);
+ } else {
+ $tz = $testInstance->getTimezone();
+ }
+
+ if (static::hasRelativeKeywords($time)) {
+ $testInstance->modify($time);
+ }
+
+ $time = $testInstance->format(static::MOCK_DATETIME_FORMAT);
+ }
+
+ $timezone = static::safeCreateDateTimeZone($tz);
+ // @codeCoverageIgnoreStart
+ if ($isNow && !isset($testInstance) && static::isMicrosecondsFallbackEnabled() && (
+ version_compare(PHP_VERSION, '7.1.0-dev', '<')
+ ||
+ version_compare(PHP_VERSION, '7.1.3-dev', '>=') && version_compare(PHP_VERSION, '7.1.4-dev', '<')
+ )
+ ) {
+ // Get microseconds from microtime() if "now" asked and PHP < 7.1 and PHP 7.1.3 if fallback enabled.
+ list($microTime, $timeStamp) = explode(' ', microtime());
+ $dateTime = new DateTime('now', $timezone);
+ $dateTime->setTimestamp($timeStamp); // Use the timestamp returned by microtime as now can happen in the next second
+ $time = $dateTime->format(static::DEFAULT_TO_STRING_FORMAT).substr($microTime, 1, 7);
+ }
+ // @codeCoverageIgnoreEnd
+
+ // Work-around for PHP bug https://bugs.php.net/bug.php?id=67127
+ if (strpos((string) .1, '.') === false) {
+ $locale = setlocale(LC_NUMERIC, '0');
+ setlocale(LC_NUMERIC, 'C');
+ }
+ parent::__construct($time, $timezone);
+ if (isset($locale)) {
+ setlocale(LC_NUMERIC, $locale);
+ }
+ static::setLastErrors(parent::getLastErrors());
+ }
+
+ /**
+ * Create a Carbon instance from a DateTime one.
+ *
+ * @param \DateTime|\DateTimeInterface $date
+ *
+ * @return static
+ */
+ public static function instance($date)
+ {
+ if ($date instanceof static) {
+ return clone $date;
+ }
+
+ static::expectDateTime($date);
+
+ return new static($date->format('Y-m-d H:i:s.u'), $date->getTimezone());
+ }
+
+ /**
+ * Create a carbon instance from a string.
+ *
+ * This is an alias for the constructor that allows better fluent syntax
+ * as it allows you to do Carbon::parse('Monday next week')->fn() rather
+ * than (new Carbon('Monday next week'))->fn().
+ *
+ * @param string|null $time
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function parse($time = null, $tz = null)
+ {
+ return new static($time, $tz);
+ }
+
+ /**
+ * Get a Carbon instance for the current date and time.
+ *
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function now($tz = null)
+ {
+ return new static(null, $tz);
+ }
+
+ /**
+ * Create a Carbon instance for today.
+ *
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function today($tz = null)
+ {
+ return static::parse('today', $tz);
+ }
+
+ /**
+ * Create a Carbon instance for tomorrow.
+ *
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function tomorrow($tz = null)
+ {
+ return static::parse('tomorrow', $tz);
+ }
+
+ /**
+ * Create a Carbon instance for yesterday.
+ *
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function yesterday($tz = null)
+ {
+ return static::parse('yesterday', $tz);
+ }
+
+ /**
+ * Create a Carbon instance for the greatest supported date.
+ *
+ * @return static
+ */
+ public static function maxValue()
+ {
+ if (self::$PHPIntSize === 4) {
+ // 32 bit
+ return static::createFromTimestamp(PHP_INT_MAX); // @codeCoverageIgnore
+ }
+
+ // 64 bit
+ return static::create(9999, 12, 31, 23, 59, 59);
+ }
+
+ /**
+ * Create a Carbon instance for the lowest supported date.
+ *
+ * @return static
+ */
+ public static function minValue()
+ {
+ if (self::$PHPIntSize === 4) {
+ // 32 bit
+ return static::createFromTimestamp(~PHP_INT_MAX); // @codeCoverageIgnore
+ }
+
+ // 64 bit
+ return static::create(1, 1, 1, 0, 0, 0);
+ }
+
+ /**
+ * Create a new Carbon instance from a specific date and time.
+ *
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ *
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ *
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return static
+ */
+ public static function create($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
+ {
+ $now = static::hasTestNow() ? static::getTestNow() : static::now($tz);
+
+ $defaults = array_combine(array(
+ 'year',
+ 'month',
+ 'day',
+ 'hour',
+ 'minute',
+ 'second',
+ ), explode('-', $now->format('Y-n-j-G-i-s')));
+
+ $year = $year === null ? $defaults['year'] : $year;
+ $month = $month === null ? $defaults['month'] : $month;
+ $day = $day === null ? $defaults['day'] : $day;
+
+ if ($hour === null) {
+ $hour = $defaults['hour'];
+ $minute = $minute === null ? $defaults['minute'] : $minute;
+ $second = $second === null ? $defaults['second'] : $second;
+ } else {
+ $minute = $minute === null ? 0 : $minute;
+ $second = $second === null ? 0 : $second;
+ }
+
+ $fixYear = null;
+
+ if ($year < 0) {
+ $fixYear = $year;
+ $year = 0;
+ } elseif ($year > 9999) {
+ $fixYear = $year - 9999;
+ $year = 9999;
+ }
+
+ $instance = static::createFromFormat('!Y-n-j G:i:s', sprintf('%s-%s-%s %s:%02s:%02s', $year, $month, $day, $hour, $minute, $second), $tz);
+
+ if ($fixYear !== null) {
+ $instance->addYears($fixYear);
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Create a new safe Carbon instance from a specific date and time.
+ *
+ * If any of $year, $month or $day are set to null their now() values will
+ * be used.
+ *
+ * If $hour is null it will be set to its now() value and the default
+ * values for $minute and $second will be their now() values.
+ *
+ * If $hour is not null then the default values for $minute and $second
+ * will be 0.
+ *
+ * If one of the set values is not valid, an \InvalidArgumentException
+ * will be thrown.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @throws \Carbon\Exceptions\InvalidDateException|\InvalidArgumentException
+ *
+ * @return static
+ */
+ public static function createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
+ {
+ $fields = array(
+ 'year' => array(0, 9999),
+ 'month' => array(0, 12),
+ 'day' => array(0, 31),
+ 'hour' => array(0, 24),
+ 'minute' => array(0, 59),
+ 'second' => array(0, 59),
+ );
+
+ foreach ($fields as $field => $range) {
+ if ($$field !== null && (!is_int($$field) || $$field < $range[0] || $$field > $range[1])) {
+ throw new InvalidDateException($field, $$field);
+ }
+ }
+
+ $instance = static::create($year, $month, $day, $hour, $minute, $second, $tz);
+
+ foreach (array_reverse($fields) as $field => $range) {
+ if ($$field !== null && (!is_int($$field) || $$field !== $instance->$field)) {
+ throw new InvalidDateException($field, $$field);
+ }
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Create a Carbon instance from just a date. The time portion is set to now.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return static
+ */
+ public static function createFromDate($year = null, $month = null, $day = null, $tz = null)
+ {
+ return static::create($year, $month, $day, null, null, null, $tz);
+ }
+
+ /**
+ * Create a Carbon instance from just a date. The time portion is set to midnight.
+ *
+ * @param int|null $year
+ * @param int|null $month
+ * @param int|null $day
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function createMidnightDate($year = null, $month = null, $day = null, $tz = null)
+ {
+ return static::create($year, $month, $day, 0, 0, 0, $tz);
+ }
+
+ /**
+ * Create a Carbon instance from just a time. The date portion is set to today.
+ *
+ * @param int|null $hour
+ * @param int|null $minute
+ * @param int|null $second
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return static
+ */
+ public static function createFromTime($hour = null, $minute = null, $second = null, $tz = null)
+ {
+ return static::create(null, null, null, $hour, $minute, $second, $tz);
+ }
+
+ /**
+ * Create a Carbon instance from a time string. The date portion is set to today.
+ *
+ * @param string $time
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return static
+ */
+ public static function createFromTimeString($time, $tz = null)
+ {
+ return static::today($tz)->setTimeFromTimeString($time);
+ }
+
+ private static function createFromFormatAndTimezone($format, $time, $tz)
+ {
+ return $tz !== null
+ ? parent::createFromFormat($format, $time, static::safeCreateDateTimeZone($tz))
+ : parent::createFromFormat($format, $time);
+ }
+
+ /**
+ * Create a Carbon instance from a specific format.
+ *
+ * @param string $format Datetime format
+ * @param string $time
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return static
+ */
+ public static function createFromFormat($format, $time, $tz = null)
+ {
+ // First attempt to create an instance, so that error messages are based on the unmodified format.
+ $date = self::createFromFormatAndTimezone($format, $time, $tz);
+ $lastErrors = parent::getLastErrors();
+
+ if (($mock = static::getTestNow()) && ($date instanceof DateTime || $date instanceof DateTimeInterface)) {
+ // Set timezone from mock if custom timezone was neither given directly nor as a part of format.
+ // First let's skip the part that will be ignored by the parser.
+ $nonEscaped = '(?getTimezone();
+ }
+
+ // Prepend mock datetime only if the format does not contain non escaped unix epoch reset flag.
+ if (!preg_match("/{$nonEscaped}[!|]/", $format)) {
+ $format = static::MOCK_DATETIME_FORMAT.' '.$format;
+ $time = $mock->format(static::MOCK_DATETIME_FORMAT).' '.$time;
+ }
+
+ // Regenerate date from the modified format to base result on the mocked instance instead of now.
+ $date = self::createFromFormatAndTimezone($format, $time, $tz);
+ }
+
+ if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
+ $instance = static::instance($date);
+ $instance::setLastErrors($lastErrors);
+
+ return $instance;
+ }
+
+ throw new InvalidArgumentException(implode(PHP_EOL, $lastErrors['errors']));
+ }
+
+ /**
+ * Set last errors.
+ *
+ * @param array $lastErrors
+ *
+ * @return void
+ */
+ private static function setLastErrors(array $lastErrors)
+ {
+ static::$lastErrors = $lastErrors;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getLastErrors()
+ {
+ return static::$lastErrors;
+ }
+
+ /**
+ * Create a Carbon instance from a timestamp.
+ *
+ * @param int $timestamp
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function createFromTimestamp($timestamp, $tz = null)
+ {
+ return static::today($tz)->setTimestamp($timestamp);
+ }
+
+ /**
+ * Create a Carbon instance from a timestamp in milliseconds.
+ *
+ * @param int $timestamp
+ * @param \DateTimeZone|string|null $tz
+ *
+ * @return static
+ */
+ public static function createFromTimestampMs($timestamp, $tz = null)
+ {
+ return static::createFromFormat('U.u', sprintf('%F', $timestamp / 1000))
+ ->setTimezone($tz);
+ }
+
+ /**
+ * Create a Carbon instance from an UTC timestamp.
+ *
+ * @param int $timestamp
+ *
+ * @return static
+ */
+ public static function createFromTimestampUTC($timestamp)
+ {
+ return new static('@'.$timestamp);
+ }
+
+ /**
+ * Make a Carbon instance from given variable if possible.
+ *
+ * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals
+ * and recurrences). Throw an exception for invalid format, but otherwise return null.
+ *
+ * @param mixed $var
+ *
+ * @return static|null
+ */
+ public static function make($var)
+ {
+ if ($var instanceof DateTime || $var instanceof DateTimeInterface) {
+ return static::instance($var);
+ }
+
+ if (is_string($var)) {
+ $var = trim($var);
+ $first = substr($var, 0, 1);
+
+ if (is_string($var) && $first !== 'P' && $first !== 'R' && preg_match('/[a-z0-9]/i', $var)) {
+ return static::parse($var);
+ }
+ }
+ }
+
+ /**
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function copy()
+ {
+ return clone $this;
+ }
+
+ /**
+ * Returns a present instance in the same timezone.
+ *
+ * @return static
+ */
+ public function nowWithSameTz()
+ {
+ return static::now($this->getTimezone());
+ }
+
+ /**
+ * Throws an exception if the given object is not a DateTime and does not implement DateTimeInterface
+ * and not in $other.
+ *
+ * @param mixed $date
+ * @param string|array $other
+ *
+ * @throws \InvalidArgumentException
+ */
+ protected static function expectDateTime($date, $other = array())
+ {
+ $message = 'Expected ';
+ foreach ((array) $other as $expect) {
+ $message .= "{$expect}, ";
+ }
+
+ if (!$date instanceof DateTime && !$date instanceof DateTimeInterface) {
+ throw new InvalidArgumentException(
+ $message.'DateTime or DateTimeInterface, '.
+ (is_object($date) ? get_class($date) : gettype($date)).' given'
+ );
+ }
+ }
+
+ /**
+ * Return the Carbon instance passed through, a now instance in the same timezone
+ * if null given or parse the input if string given.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ *
+ * @return static
+ */
+ protected function resolveCarbon($date = null)
+ {
+ if (!$date) {
+ return $this->nowWithSameTz();
+ }
+
+ if (is_string($date)) {
+ return static::parse($date, $this->getTimezone());
+ }
+
+ static::expectDateTime($date, array('null', 'string'));
+
+ return $date instanceof self ? $date : static::instance($date);
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ ///////////////////////// GETTERS AND SETTERS /////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Get a part of the Carbon object
+ *
+ * @param string $name
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return string|int|bool|\DateTimeZone
+ */
+ public function __get($name)
+ {
+ static $formats = array(
+ 'year' => 'Y',
+ 'yearIso' => 'o',
+ 'month' => 'n',
+ 'day' => 'j',
+ 'hour' => 'G',
+ 'minute' => 'i',
+ 'second' => 's',
+ 'micro' => 'u',
+ 'dayOfWeek' => 'w',
+ 'dayOfWeekIso' => 'N',
+ 'dayOfYear' => 'z',
+ 'weekOfYear' => 'W',
+ 'daysInMonth' => 't',
+ 'timestamp' => 'U',
+ 'englishDayOfWeek' => 'l',
+ 'shortEnglishDayOfWeek' => 'D',
+ 'englishMonth' => 'F',
+ 'shortEnglishMonth' => 'M',
+ 'localeDayOfWeek' => '%A',
+ 'shortLocaleDayOfWeek' => '%a',
+ 'localeMonth' => '%B',
+ 'shortLocaleMonth' => '%b',
+ );
+
+ switch (true) {
+ case isset($formats[$name]):
+ $format = $formats[$name];
+ $method = substr($format, 0, 1) === '%' ? 'formatLocalized' : 'format';
+ $value = $this->$method($format);
+
+ return is_numeric($value) ? (int) $value : $value;
+
+ case $name === 'weekOfMonth':
+ return (int) ceil($this->day / static::DAYS_PER_WEEK);
+
+ case $name === 'weekNumberInMonth':
+ return (int) ceil(($this->day + $this->copy()->startOfMonth()->dayOfWeek - 1) / static::DAYS_PER_WEEK);
+
+ case $name === 'age':
+ return $this->diffInYears();
+
+ case $name === 'quarter':
+ return (int) ceil($this->month / static::MONTHS_PER_QUARTER);
+
+ case $name === 'offset':
+ return $this->getOffset();
+
+ case $name === 'offsetHours':
+ return $this->getOffset() / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR;
+
+ case $name === 'dst':
+ return $this->format('I') === '1';
+
+ case $name === 'local':
+ return $this->getOffset() === $this->copy()->setTimezone(date_default_timezone_get())->getOffset();
+
+ case $name === 'utc':
+ return $this->getOffset() === 0;
+
+ case $name === 'timezone' || $name === 'tz':
+ return $this->getTimezone();
+
+ case $name === 'timezoneName' || $name === 'tzName':
+ return $this->getTimezone()->getName();
+
+ default:
+ throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
+ }
+ }
+
+ /**
+ * Check if an attribute exists on the object
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public function __isset($name)
+ {
+ try {
+ $this->__get($name);
+ } catch (InvalidArgumentException $e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Set a part of the Carbon object
+ *
+ * @param string $name
+ * @param string|int|\DateTimeZone $value
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function __set($name, $value)
+ {
+ switch ($name) {
+ case 'year':
+ case 'month':
+ case 'day':
+ case 'hour':
+ case 'minute':
+ case 'second':
+ list($year, $month, $day, $hour, $minute, $second) = explode('-', $this->format('Y-n-j-G-i-s'));
+ $$name = $value;
+ $this->setDateTime($year, $month, $day, $hour, $minute, $second);
+ break;
+
+ case 'timestamp':
+ parent::setTimestamp($value);
+ break;
+
+ case 'timezone':
+ case 'tz':
+ $this->setTimezone($value);
+ break;
+
+ default:
+ throw new InvalidArgumentException(sprintf("Unknown setter '%s'", $name));
+ }
+ }
+
+ /**
+ * Set the instance's year
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function year($value)
+ {
+ $this->year = $value;
+
+ return $this;
+ }
+
+ /**
+ * Set the instance's month
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function month($value)
+ {
+ $this->month = $value;
+
+ return $this;
+ }
+
+ /**
+ * Set the instance's day
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function day($value)
+ {
+ $this->day = $value;
+
+ return $this;
+ }
+
+ /**
+ * Set the instance's hour
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function hour($value)
+ {
+ $this->hour = $value;
+
+ return $this;
+ }
+
+ /**
+ * Set the instance's minute
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function minute($value)
+ {
+ $this->minute = $value;
+
+ return $this;
+ }
+
+ /**
+ * Set the instance's second
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function second($value)
+ {
+ $this->second = $value;
+
+ return $this;
+ }
+
+ /**
+ * Sets the current date of the DateTime object to a different date.
+ * Calls modify as a workaround for a php bug
+ *
+ * @param int $year
+ * @param int $month
+ * @param int $day
+ *
+ * @return static
+ *
+ * @see https://github.com/briannesbitt/Carbon/issues/539
+ * @see https://bugs.php.net/bug.php?id=63863
+ */
+ public function setDate($year, $month, $day)
+ {
+ $this->modify('+0 day');
+
+ return parent::setDate($year, $month, $day);
+ }
+
+ /**
+ * Set the date and time all together
+ *
+ * @param int $year
+ * @param int $month
+ * @param int $day
+ * @param int $hour
+ * @param int $minute
+ * @param int $second
+ *
+ * @return static
+ */
+ public function setDateTime($year, $month, $day, $hour, $minute, $second = 0)
+ {
+ return $this->setDate($year, $month, $day)->setTime($hour, $minute, $second);
+ }
+
+ /**
+ * Set the time by time string
+ *
+ * @param string $time
+ *
+ * @return static
+ */
+ public function setTimeFromTimeString($time)
+ {
+ if (strpos($time, ':') === false) {
+ $time .= ':0';
+ }
+
+ return $this->modify($time);
+ }
+
+ /**
+ * Set the instance's timestamp
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function timestamp($value)
+ {
+ return $this->setTimestamp($value);
+ }
+
+ /**
+ * Alias for setTimezone()
+ *
+ * @param \DateTimeZone|string $value
+ *
+ * @return static
+ */
+ public function timezone($value)
+ {
+ return $this->setTimezone($value);
+ }
+
+ /**
+ * Alias for setTimezone()
+ *
+ * @param \DateTimeZone|string $value
+ *
+ * @return static
+ */
+ public function tz($value)
+ {
+ return $this->setTimezone($value);
+ }
+
+ /**
+ * Set the instance's timezone from a string or object
+ *
+ * @param \DateTimeZone|string $value
+ *
+ * @return static
+ */
+ public function setTimezone($value)
+ {
+ parent::setTimezone(static::safeCreateDateTimeZone($value));
+ // https://bugs.php.net/bug.php?id=72338
+ // just workaround on this bug
+ $this->getTimestamp();
+
+ return $this;
+ }
+
+ /**
+ * Set the year, month, and date for this instance to that of the passed instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface $date
+ *
+ * @return static
+ */
+ public function setDateFrom($date)
+ {
+ $date = static::instance($date);
+
+ $this->setDate($date->year, $date->month, $date->day);
+
+ return $this;
+ }
+
+ /**
+ * Set the hour, day, and time for this instance to that of the passed instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface $date
+ *
+ * @return static
+ */
+ public function setTimeFrom($date)
+ {
+ $date = static::instance($date);
+
+ $this->setTime($date->hour, $date->minute, $date->second);
+
+ return $this;
+ }
+
+ /**
+ * Get the days of the week
+ *
+ * @return array
+ */
+ public static function getDays()
+ {
+ return static::$days;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////// WEEK SPECIAL DAYS /////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Get the first day of week
+ *
+ * @return int
+ */
+ public static function getWeekStartsAt()
+ {
+ return static::$weekStartsAt;
+ }
+
+ /**
+ * Set the first day of week
+ *
+ * @param int $day week start day
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return void
+ */
+ public static function setWeekStartsAt($day)
+ {
+ if ($day > static::SATURDAY || $day < static::SUNDAY) {
+ throw new InvalidArgumentException('Day of a week should be greater than or equal to 0 and less than or equal to 6.');
+ }
+
+ static::$weekStartsAt = $day;
+ }
+
+ /**
+ * Get the last day of week
+ *
+ * @return int
+ */
+ public static function getWeekEndsAt()
+ {
+ return static::$weekEndsAt;
+ }
+
+ /**
+ * Set the last day of week
+ *
+ * @param int $day
+ *
+ * @throws InvalidArgumentException
+ *
+ * @return void
+ */
+ public static function setWeekEndsAt($day)
+ {
+ if ($day > static::SATURDAY || $day < static::SUNDAY) {
+ throw new InvalidArgumentException('Day of a week should be greater than or equal to 0 and less than or equal to 6.');
+ }
+
+ static::$weekEndsAt = $day;
+ }
+
+ /**
+ * Get weekend days
+ *
+ * @return array
+ */
+ public static function getWeekendDays()
+ {
+ return static::$weekendDays;
+ }
+
+ /**
+ * Set weekend days
+ *
+ * @param array $days
+ *
+ * @return void
+ */
+ public static function setWeekendDays($days)
+ {
+ static::$weekendDays = $days;
+ }
+
+ /**
+ * get midday/noon hour
+ *
+ * @return int
+ */
+ public static function getMidDayAt()
+ {
+ return static::$midDayAt;
+ }
+
+ /**
+ * Set midday/noon hour
+ *
+ * @param int $hour midday hour
+ *
+ * @return void
+ */
+ public static function setMidDayAt($hour)
+ {
+ static::$midDayAt = $hour;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ ///////////////////////// TESTING AIDS ////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Set a Carbon instance (real or mock) to be returned when a "now"
+ * instance is created. The provided instance will be returned
+ * specifically under the following conditions:
+ * - A call to the static now() method, ex. Carbon::now()
+ * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
+ * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
+ * - When a string containing the desired time is passed to Carbon::parse().
+ *
+ * Note the timezone parameter was left out of the examples above and
+ * has no affect as the mock value will be returned regardless of its value.
+ *
+ * To clear the test instance call this method using the default
+ * parameter of null.
+ *
+ * @param \Carbon\Carbon|null $testNow real or mock Carbon instance
+ * @param \Carbon\Carbon|string|null $testNow
+ */
+ public static function setTestNow($testNow = null)
+ {
+ static::$testNow = is_string($testNow) ? static::parse($testNow) : $testNow;
+ }
+
+ /**
+ * Get the Carbon instance (real or mock) to be returned when a "now"
+ * instance is created.
+ *
+ * @return static the current instance used for testing
+ */
+ public static function getTestNow()
+ {
+ return static::$testNow;
+ }
+
+ /**
+ * Determine if there is a valid test instance set. A valid test instance
+ * is anything that is not null.
+ *
+ * @return bool true if there is a test instance, otherwise false
+ */
+ public static function hasTestNow()
+ {
+ return static::getTestNow() !== null;
+ }
+
+ /**
+ * Determine if a time string will produce a relative date.
+ *
+ * @param string $time
+ *
+ * @return bool true if time match a relative date, false if absolute or invalid time string
+ */
+ public static function hasRelativeKeywords($time)
+ {
+ if (strtotime($time) === false) {
+ return false;
+ }
+
+ $date1 = new DateTime('2000-01-01T00:00:00Z');
+ $date1->modify($time);
+ $date2 = new DateTime('2001-12-25T00:00:00Z');
+ $date2->modify($time);
+
+ return $date1 != $date2;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////// LOCALIZATION //////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Initialize the translator instance if necessary.
+ *
+ * @return \Symfony\Component\Translation\TranslatorInterface
+ */
+ protected static function translator()
+ {
+ if (static::$translator === null) {
+ static::$translator = Translator::get();
+ }
+
+ return static::$translator;
+ }
+
+ /**
+ * Get the translator instance in use
+ *
+ * @return \Symfony\Component\Translation\TranslatorInterface
+ */
+ public static function getTranslator()
+ {
+ return static::translator();
+ }
+
+ /**
+ * Set the translator instance to use
+ *
+ * @param \Symfony\Component\Translation\TranslatorInterface $translator
+ *
+ * @return void
+ */
+ public static function setTranslator(TranslatorInterface $translator)
+ {
+ static::$translator = $translator;
+ }
+
+ /**
+ * Get the current translator locale
+ *
+ * @return string
+ */
+ public static function getLocale()
+ {
+ return static::translator()->getLocale();
+ }
+
+ /**
+ * Set the current translator locale and indicate if the source locale file exists
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function setLocale($locale)
+ {
+ return static::translator()->setLocale($locale) !== false;
+ }
+
+ /**
+ * Set the current locale to the given, execute the passed function, reset the locale to previous one,
+ * then return the result of the closure (or null if the closure was void).
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return mixed
+ */
+ public static function executeWithLocale($locale, $func)
+ {
+ $currentLocale = static::getLocale();
+ $result = call_user_func($func, static::setLocale($locale) ? static::getLocale() : false, static::translator());
+ static::setLocale($currentLocale);
+
+ return $result;
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has short-units support.
+ * Support is considered enabled if either year, day or hour has a short variant translated.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasShortUnits($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ return $newLocale &&
+ (
+ ($y = $translator->trans('y')) !== 'y' &&
+ $y !== $translator->trans('year')
+ ) || (
+ ($y = $translator->trans('d')) !== 'd' &&
+ $y !== $translator->trans('day')
+ ) || (
+ ($y = $translator->trans('h')) !== 'h' &&
+ $y !== $translator->trans('hour')
+ );
+ });
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasDiffSyntax($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ return $newLocale &&
+ $translator->trans('ago') !== 'ago' &&
+ $translator->trans('from_now') !== 'from_now' &&
+ $translator->trans('before') !== 'before' &&
+ $translator->trans('after') !== 'after';
+ });
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow).
+ * Support is considered enabled if the 3 words are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasDiffOneDayWords($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ return $newLocale &&
+ $translator->trans('diff_now') !== 'diff_now' &&
+ $translator->trans('diff_yesterday') !== 'diff_yesterday' &&
+ $translator->trans('diff_tomorrow') !== 'diff_tomorrow';
+ });
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow).
+ * Support is considered enabled if the 2 words are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasDiffTwoDayWords($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ return $newLocale &&
+ $translator->trans('diff_before_yesterday') !== 'diff_before_yesterday' &&
+ $translator->trans('diff_after_tomorrow') !== 'diff_after_tomorrow';
+ });
+ }
+
+ /**
+ * Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X).
+ * Support is considered enabled if the 4 sentences are translated in the given locale.
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public static function localeHasPeriodSyntax($locale)
+ {
+ return static::executeWithLocale($locale, function ($newLocale, TranslatorInterface $translator) {
+ return $newLocale &&
+ $translator->trans('period_recurrences') !== 'period_recurrences' &&
+ $translator->trans('period_interval') !== 'period_interval' &&
+ $translator->trans('period_start_date') !== 'period_start_date' &&
+ $translator->trans('period_end_date') !== 'period_end_date';
+ });
+ }
+
+ /**
+ * Returns the list of internally available locales and already loaded custom locales.
+ * (It will ignore custom translator dynamic loading.)
+ *
+ * @return array
+ */
+ public static function getAvailableLocales()
+ {
+ $translator = static::translator();
+ $locales = array();
+ if ($translator instanceof Translator) {
+ foreach (glob(__DIR__.'/Lang/*.php') as $file) {
+ $locales[] = substr($file, strrpos($file, '/') + 1, -4);
+ }
+
+ $locales = array_unique(array_merge($locales, array_keys($translator->getMessages())));
+ }
+
+ return $locales;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////// STRING FORMATTING /////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Set if UTF8 will be used for localized date/time
+ *
+ * @param bool $utf8
+ */
+ public static function setUtf8($utf8)
+ {
+ static::$utf8 = $utf8;
+ }
+
+ /**
+ * Format the instance with the current locale. You can set the current
+ * locale using setlocale() http://php.net/setlocale.
+ *
+ * @param string $format
+ *
+ * @return string
+ */
+ public function formatLocalized($format)
+ {
+ // Check for Windows to find and replace the %e modifier correctly.
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ $format = preg_replace('#(?toDateTimeString()));
+
+ return static::$utf8 ? utf8_encode($formatted) : $formatted;
+ }
+
+ /**
+ * Reset the format used to the default when type juggling a Carbon instance to a string
+ *
+ * @return void
+ */
+ public static function resetToStringFormat()
+ {
+ static::setToStringFormat(static::DEFAULT_TO_STRING_FORMAT);
+ }
+
+ /**
+ * Set the default format used when type juggling a Carbon instance to a string
+ *
+ * @param string|Closure $format
+ *
+ * @return void
+ */
+ public static function setToStringFormat($format)
+ {
+ static::$toStringFormat = $format;
+ }
+
+ /**
+ * Format the instance as a string using the set format
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ $format = static::$toStringFormat;
+
+ return $this->format($format instanceof Closure ? $format($this) : $format);
+ }
+
+ /**
+ * Format the instance as date
+ *
+ * @return string
+ */
+ public function toDateString()
+ {
+ return $this->format('Y-m-d');
+ }
+
+ /**
+ * Format the instance as a readable date
+ *
+ * @return string
+ */
+ public function toFormattedDateString()
+ {
+ return $this->format('M j, Y');
+ }
+
+ /**
+ * Format the instance as time
+ *
+ * @return string
+ */
+ public function toTimeString()
+ {
+ return $this->format('H:i:s');
+ }
+
+ /**
+ * Format the instance as date and time
+ *
+ * @return string
+ */
+ public function toDateTimeString()
+ {
+ return $this->format('Y-m-d H:i:s');
+ }
+
+ /**
+ * Format the instance as date and time T-separated with no timezone
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toDateTimeLocalString();
+ * ```
+ *
+ * @return string
+ */
+ public function toDateTimeLocalString()
+ {
+ return $this->format('Y-m-d\TH:i:s');
+ }
+
+ /**
+ * Format the instance with day, date and time
+ *
+ * @return string
+ */
+ public function toDayDateTimeString()
+ {
+ return $this->format('D, M j, Y g:i A');
+ }
+
+ /**
+ * Format the instance as ATOM
+ *
+ * @return string
+ */
+ public function toAtomString()
+ {
+ return $this->format(static::ATOM);
+ }
+
+ /**
+ * Format the instance as COOKIE
+ *
+ * @return string
+ */
+ public function toCookieString()
+ {
+ return $this->format(static::COOKIE);
+ }
+
+ /**
+ * Format the instance as ISO8601
+ *
+ * @return string
+ */
+ public function toIso8601String()
+ {
+ return $this->toAtomString();
+ }
+
+ /**
+ * Format the instance as RFC822
+ *
+ * @return string
+ */
+ public function toRfc822String()
+ {
+ return $this->format(static::RFC822);
+ }
+
+ /**
+ * Convert the instance to UTC and return as Zulu ISO8601
+ *
+ * @return string
+ */
+ public function toIso8601ZuluString()
+ {
+ return $this->copy()->setTimezone('UTC')->format('Y-m-d\TH:i:s\Z');
+ }
+
+ /**
+ * Format the instance as RFC850
+ *
+ * @return string
+ */
+ public function toRfc850String()
+ {
+ return $this->format(static::RFC850);
+ }
+
+ /**
+ * Format the instance as RFC1036
+ *
+ * @return string
+ */
+ public function toRfc1036String()
+ {
+ return $this->format(static::RFC1036);
+ }
+
+ /**
+ * Format the instance as RFC1123
+ *
+ * @return string
+ */
+ public function toRfc1123String()
+ {
+ return $this->format(static::RFC1123);
+ }
+
+ /**
+ * Format the instance as RFC2822
+ *
+ * @return string
+ */
+ public function toRfc2822String()
+ {
+ return $this->format(static::RFC2822);
+ }
+
+ /**
+ * Format the instance as RFC3339
+ *
+ * @return string
+ */
+ public function toRfc3339String()
+ {
+ return $this->format(static::RFC3339);
+ }
+
+ /**
+ * Format the instance as RSS
+ *
+ * @return string
+ */
+ public function toRssString()
+ {
+ return $this->format(static::RSS);
+ }
+
+ /**
+ * Format the instance as W3C
+ *
+ * @return string
+ */
+ public function toW3cString()
+ {
+ return $this->format(static::W3C);
+ }
+
+ /**
+ * Format the instance as RFC7231
+ *
+ * @return string
+ */
+ public function toRfc7231String()
+ {
+ return $this->copy()
+ ->setTimezone('GMT')
+ ->format(static::RFC7231_FORMAT);
+ }
+
+ /**
+ * Get default array representation
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ return array(
+ 'year' => $this->year,
+ 'month' => $this->month,
+ 'day' => $this->day,
+ 'dayOfWeek' => $this->dayOfWeek,
+ 'dayOfYear' => $this->dayOfYear,
+ 'hour' => $this->hour,
+ 'minute' => $this->minute,
+ 'second' => $this->second,
+ 'micro' => $this->micro,
+ 'timestamp' => $this->timestamp,
+ 'formatted' => $this->format(self::DEFAULT_TO_STRING_FORMAT),
+ 'timezone' => $this->timezone,
+ );
+ }
+
+ /**
+ * Get default object representation.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toObject());
+ * ```
+ *
+ * @return object
+ */
+ public function toObject()
+ {
+ return (object) $this->toArray();
+ }
+
+ /**
+ * Returns english human readable complete date string.
+ *
+ * @example
+ * ```
+ * echo Carbon::now()->toString();
+ * ```
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return $this->format('D M j Y H:i:s \G\M\TO');
+ }
+
+ /**
+ * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept:
+ * 1977-04-22T01:00:00-05:00).
+ *
+ * @example
+ * ```
+ * echo Carbon::now('America/Toronto')->toISOString() . "\n";
+ * echo Carbon::now('America/Toronto')->toISOString(true) . "\n";
+ * ```
+ *
+ * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC.
+ *
+ * @return null|string
+ */
+ public function toISOString($keepOffset = false)
+ {
+ if ($this->year === 0) {
+ return null;
+ }
+
+ $year = $this->year < 0 || $this->year > 9999
+ ? ($this->year < 0 ? '-' : '+').str_pad(abs($this->year), 6, '0', STR_PAD_LEFT)
+ : str_pad($this->year, 4, '0', STR_PAD_LEFT);
+ $tz = $keepOffset ? $this->format('P') : 'Z';
+ $date = $keepOffset ? $this : $this->copy()->setTimezone('UTC');
+
+ return $year.$date->format('-m-d\TH:i:s.u').$tz;
+ }
+
+ /**
+ * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone.
+ *
+ * @example
+ * ```
+ * echo Carbon::now('America/Toronto')->toJSON();
+ * ```
+ *
+ * @return null|string
+ */
+ public function toJSON()
+ {
+ return $this->toISOString();
+ }
+
+ /**
+ * Return native DateTime PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toDateTime());
+ * ```
+ *
+ * @return DateTime
+ */
+ public function toDateTime()
+ {
+ return new DateTime($this->format('Y-m-d H:i:s.u'), $this->getTimezone());
+ }
+
+ /**
+ * @alias toDateTime
+ *
+ * Return native DateTime PHP object matching the current instance.
+ *
+ * @example
+ * ```
+ * var_dump(Carbon::now()->toDate());
+ * ```
+ *
+ * @return DateTime
+ */
+ public function toDate()
+ {
+ return $this->toDateTime();
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ ////////////////////////// COMPARISONS ////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Determines if the instance is equal to another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function eq($date)
+ {
+ return $this == $date;
+ }
+
+ /**
+ * Determines if the instance is equal to another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see eq()
+ *
+ * @return bool
+ */
+ public function equalTo($date)
+ {
+ return $this->eq($date);
+ }
+
+ /**
+ * Determines if the instance is not equal to another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function ne($date)
+ {
+ return !$this->eq($date);
+ }
+
+ /**
+ * Determines if the instance is not equal to another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see ne()
+ *
+ * @return bool
+ */
+ public function notEqualTo($date)
+ {
+ return $this->ne($date);
+ }
+
+ /**
+ * Determines if the instance is greater (after) than another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function gt($date)
+ {
+ return $this > $date;
+ }
+
+ /**
+ * Determines if the instance is greater (after) than another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see gt()
+ *
+ * @return bool
+ */
+ public function greaterThan($date)
+ {
+ return $this->gt($date);
+ }
+
+ /**
+ * Determines if the instance is greater (after) than another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see gt()
+ *
+ * @return bool
+ */
+ public function isAfter($date)
+ {
+ return $this->gt($date);
+ }
+
+ /**
+ * Determines if the instance is greater (after) than or equal to another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function gte($date)
+ {
+ return $this >= $date;
+ }
+
+ /**
+ * Determines if the instance is greater (after) than or equal to another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see gte()
+ *
+ * @return bool
+ */
+ public function greaterThanOrEqualTo($date)
+ {
+ return $this->gte($date);
+ }
+
+ /**
+ * Determines if the instance is less (before) than another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function lt($date)
+ {
+ return $this < $date;
+ }
+
+ /**
+ * Determines if the instance is less (before) than another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see lt()
+ *
+ * @return bool
+ */
+ public function lessThan($date)
+ {
+ return $this->lt($date);
+ }
+
+ /**
+ * Determines if the instance is less (before) than another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see lt()
+ *
+ * @return bool
+ */
+ public function isBefore($date)
+ {
+ return $this->lt($date);
+ }
+
+ /**
+ * Determines if the instance is less (before) or equal to another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @return bool
+ */
+ public function lte($date)
+ {
+ return $this <= $date;
+ }
+
+ /**
+ * Determines if the instance is less (before) or equal to another
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see lte()
+ *
+ * @return bool
+ */
+ public function lessThanOrEqualTo($date)
+ {
+ return $this->lte($date);
+ }
+
+ /**
+ * Determines if the instance is between two others
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ * @param bool $equal Indicates if an equal to comparison should be done
+ *
+ * @return bool
+ */
+ public function between($date1, $date2, $equal = true)
+ {
+ if ($date1->gt($date2)) {
+ $temp = $date1;
+ $date1 = $date2;
+ $date2 = $temp;
+ }
+
+ if ($equal) {
+ return $this->gte($date1) && $this->lte($date2);
+ }
+
+ return $this->gt($date1) && $this->lt($date2);
+ }
+
+ protected function floatDiffInSeconds($date)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return abs($this->diffInRealSeconds($date, false) + ($date->micro - $this->micro) / 1000000);
+ }
+
+ /**
+ * Determines if the instance is between two others
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ * @param bool $equal Indicates if a > and < comparison should be used or <= or >=
+ *
+ * @return bool
+ */
+ public function isBetween($date1, $date2, $equal = true)
+ {
+ return $this->between($date1, $date2, $equal);
+ }
+
+ /**
+ * Get the closest date from the instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return static
+ */
+ public function closest($date1, $date2)
+ {
+ return $this->floatDiffInSeconds($date1) < $this->floatDiffInSeconds($date2) ? $date1 : $date2;
+ }
+
+ /**
+ * Get the farthest date from the instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date1
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date2
+ *
+ * @return static
+ */
+ public function farthest($date1, $date2)
+ {
+ return $this->floatDiffInSeconds($date1) > $this->floatDiffInSeconds($date2) ? $date1 : $date2;
+ }
+
+ /**
+ * Get the minimum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ *
+ * @return static
+ */
+ public function min($date = null)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->lt($date) ? $this : $date;
+ }
+
+ /**
+ * Get the minimum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see min()
+ *
+ * @return static
+ */
+ public function minimum($date = null)
+ {
+ return $this->min($date);
+ }
+
+ /**
+ * Get the maximum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ *
+ * @return static
+ */
+ public function max($date = null)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->gt($date) ? $this : $date;
+ }
+
+ /**
+ * Get the maximum instance between a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|mixed $date
+ *
+ * @see max()
+ *
+ * @return static
+ */
+ public function maximum($date = null)
+ {
+ return $this->max($date);
+ }
+
+ /**
+ * Determines if the instance is a weekday.
+ *
+ * @return bool
+ */
+ public function isWeekday()
+ {
+ return !$this->isWeekend();
+ }
+
+ /**
+ * Determines if the instance is a weekend day.
+ *
+ * @return bool
+ */
+ public function isWeekend()
+ {
+ return in_array($this->dayOfWeek, static::$weekendDays);
+ }
+
+ /**
+ * Determines if the instance is yesterday.
+ *
+ * @return bool
+ */
+ public function isYesterday()
+ {
+ return $this->toDateString() === static::yesterday($this->getTimezone())->toDateString();
+ }
+
+ /**
+ * Determines if the instance is today.
+ *
+ * @return bool
+ */
+ public function isToday()
+ {
+ return $this->toDateString() === $this->nowWithSameTz()->toDateString();
+ }
+
+ /**
+ * Determines if the instance is tomorrow.
+ *
+ * @return bool
+ */
+ public function isTomorrow()
+ {
+ return $this->toDateString() === static::tomorrow($this->getTimezone())->toDateString();
+ }
+
+ /**
+ * Determines if the instance is within the next week.
+ *
+ * @return bool
+ */
+ public function isNextWeek()
+ {
+ return $this->weekOfYear === $this->nowWithSameTz()->addWeek()->weekOfYear;
+ }
+
+ /**
+ * Determines if the instance is within the last week.
+ *
+ * @return bool
+ */
+ public function isLastWeek()
+ {
+ return $this->weekOfYear === $this->nowWithSameTz()->subWeek()->weekOfYear;
+ }
+
+ /**
+ * Determines if the instance is within the next quarter.
+ *
+ * @return bool
+ */
+ public function isNextQuarter()
+ {
+ return $this->quarter === $this->nowWithSameTz()->addQuarter()->quarter;
+ }
+
+ /**
+ * Determines if the instance is within the last quarter.
+ *
+ * @return bool
+ */
+ public function isLastQuarter()
+ {
+ return $this->quarter === $this->nowWithSameTz()->subQuarter()->quarter;
+ }
+
+ /**
+ * Determines if the instance is within the next month.
+ *
+ * @return bool
+ */
+ public function isNextMonth()
+ {
+ return $this->month === $this->nowWithSameTz()->addMonthNoOverflow()->month;
+ }
+
+ /**
+ * Determines if the instance is within the last month.
+ *
+ * @return bool
+ */
+ public function isLastMonth()
+ {
+ return $this->month === $this->nowWithSameTz()->subMonthNoOverflow()->month;
+ }
+
+ /**
+ * Determines if the instance is within next year.
+ *
+ * @return bool
+ */
+ public function isNextYear()
+ {
+ return $this->year === $this->nowWithSameTz()->addYear()->year;
+ }
+
+ /**
+ * Determines if the instance is within the previous year.
+ *
+ * @return bool
+ */
+ public function isLastYear()
+ {
+ return $this->year === $this->nowWithSameTz()->subYear()->year;
+ }
+
+ /**
+ * Determines if the instance is in the future, ie. greater (after) than now.
+ *
+ * @return bool
+ */
+ public function isFuture()
+ {
+ return $this->gt($this->nowWithSameTz());
+ }
+
+ /**
+ * Determines if the instance is in the past, ie. less (before) than now.
+ *
+ * @return bool
+ */
+ public function isPast()
+ {
+ return $this->lt($this->nowWithSameTz());
+ }
+
+ /**
+ * Determines if the instance is a leap year.
+ *
+ * @return bool
+ */
+ public function isLeapYear()
+ {
+ return $this->format('L') === '1';
+ }
+
+ /**
+ * Determines if the instance is a long year
+ *
+ * @see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
+ *
+ * @return bool
+ */
+ public function isLongYear()
+ {
+ return static::create($this->year, 12, 28, 0, 0, 0, $this->tz)->weekOfYear === 53;
+ }
+
+ /**
+ * Compares the formatted values of the two dates.
+ *
+ * @param string $format The date formats to compare.
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return bool
+ */
+ public function isSameAs($format, $date = null)
+ {
+ $date = $date ?: static::now($this->tz);
+
+ static::expectDateTime($date, 'null');
+
+ return $this->format($format) === $date->format($format);
+ }
+
+ /**
+ * Determines if the instance is in the current year.
+ *
+ * @return bool
+ */
+ public function isCurrentYear()
+ {
+ return $this->isSameYear();
+ }
+
+ /**
+ * Checks if the passed in date is in the same year as the instance year.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
+ *
+ * @return bool
+ */
+ public function isSameYear($date = null)
+ {
+ return $this->isSameAs('Y', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current month.
+ *
+ * @return bool
+ */
+ public function isCurrentQuarter()
+ {
+ return $this->isSameQuarter();
+ }
+
+ /**
+ * Checks if the passed in date is in the same quarter as the instance quarter (and year if needed).
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
+ * @param bool $ofSameYear Check if it is the same month in the same year.
+ *
+ * @return bool
+ */
+ public function isSameQuarter($date = null, $ofSameYear = null)
+ {
+ $date = $date ? static::instance($date) : static::now($this->tz);
+
+ static::expectDateTime($date, 'null');
+
+ $ofSameYear = is_null($ofSameYear) ? static::shouldCompareYearWithMonth() : $ofSameYear;
+
+ return $this->quarter === $date->quarter && (!$ofSameYear || $this->isSameYear($date));
+ }
+
+ /**
+ * Determines if the instance is in the current month.
+ *
+ * @param bool $ofSameYear Check if it is the same month in the same year.
+ *
+ * @return bool
+ */
+ public function isCurrentMonth($ofSameYear = null)
+ {
+ return $this->isSameMonth(null, $ofSameYear);
+ }
+
+ /**
+ * Checks if the passed in date is in the same month as the instance´s month.
+ *
+ * Note that this defaults to only comparing the month while ignoring the year.
+ * To test if it is the same exact month of the same year, pass in true as the second parameter.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ * @param bool $ofSameYear Check if it is the same month in the same year.
+ *
+ * @return bool
+ */
+ public function isSameMonth($date = null, $ofSameYear = null)
+ {
+ $ofSameYear = is_null($ofSameYear) ? static::shouldCompareYearWithMonth() : $ofSameYear;
+
+ return $this->isSameAs($ofSameYear ? 'Y-m' : 'm', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current day.
+ *
+ * @return bool
+ */
+ public function isCurrentDay()
+ {
+ return $this->isSameDay();
+ }
+
+ /**
+ * Checks if the passed in date is the same exact day as the instance´s day.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ *
+ * @return bool
+ */
+ public function isSameDay($date = null)
+ {
+ return $this->isSameAs('Y-m-d', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current hour.
+ *
+ * @return bool
+ */
+ public function isCurrentHour()
+ {
+ return $this->isSameHour();
+ }
+
+ /**
+ * Checks if the passed in date is the same exact hour as the instance´s hour.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ *
+ * @return bool
+ */
+ public function isSameHour($date = null)
+ {
+ return $this->isSameAs('Y-m-d H', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current minute.
+ *
+ * @return bool
+ */
+ public function isCurrentMinute()
+ {
+ return $this->isSameMinute();
+ }
+
+ /**
+ * Checks if the passed in date is the same exact minute as the instance´s minute.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ *
+ * @return bool
+ */
+ public function isSameMinute($date = null)
+ {
+ return $this->isSameAs('Y-m-d H:i', $date);
+ }
+
+ /**
+ * Determines if the instance is in the current second.
+ *
+ * @return bool
+ */
+ public function isCurrentSecond()
+ {
+ return $this->isSameSecond();
+ }
+
+ /**
+ * Checks if the passed in date is the same exact second as the instance´s second.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use the current date.
+ *
+ * @return bool
+ */
+ public function isSameSecond($date = null)
+ {
+ return $this->isSameAs('Y-m-d H:i:s', $date);
+ }
+
+ /**
+ * Checks if this day is a specific day of the week.
+ *
+ * @param int $dayOfWeek
+ *
+ * @return bool
+ */
+ public function isDayOfWeek($dayOfWeek)
+ {
+ return $this->dayOfWeek === $dayOfWeek;
+ }
+
+ /**
+ * Checks if this day is a Sunday.
+ *
+ * @return bool
+ */
+ public function isSunday()
+ {
+ return $this->dayOfWeek === static::SUNDAY;
+ }
+
+ /**
+ * Checks if this day is a Monday.
+ *
+ * @return bool
+ */
+ public function isMonday()
+ {
+ return $this->dayOfWeek === static::MONDAY;
+ }
+
+ /**
+ * Checks if this day is a Tuesday.
+ *
+ * @return bool
+ */
+ public function isTuesday()
+ {
+ return $this->dayOfWeek === static::TUESDAY;
+ }
+
+ /**
+ * Checks if this day is a Wednesday.
+ *
+ * @return bool
+ */
+ public function isWednesday()
+ {
+ return $this->dayOfWeek === static::WEDNESDAY;
+ }
+
+ /**
+ * Checks if this day is a Thursday.
+ *
+ * @return bool
+ */
+ public function isThursday()
+ {
+ return $this->dayOfWeek === static::THURSDAY;
+ }
+
+ /**
+ * Checks if this day is a Friday.
+ *
+ * @return bool
+ */
+ public function isFriday()
+ {
+ return $this->dayOfWeek === static::FRIDAY;
+ }
+
+ /**
+ * Checks if this day is a Saturday.
+ *
+ * @return bool
+ */
+ public function isSaturday()
+ {
+ return $this->dayOfWeek === static::SATURDAY;
+ }
+
+ /**
+ * Check if its the birthday. Compares the date/month values of the two dates.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|null $date The instance to compare with or null to use current day.
+ *
+ * @return bool
+ */
+ public function isBirthday($date = null)
+ {
+ return $this->isSameAs('md', $date);
+ }
+
+ /**
+ * Check if today is the last day of the Month
+ *
+ * @return bool
+ */
+ public function isLastOfMonth()
+ {
+ return $this->day === $this->daysInMonth;
+ }
+
+ /**
+ * Check if the instance is start of day / midnight.
+ *
+ * @param bool $checkMicroseconds check time at microseconds precision
+ * /!\ Warning, this is not reliable with PHP < 7.1.4
+ *
+ * @return bool
+ */
+ public function isStartOfDay($checkMicroseconds = false)
+ {
+ return $checkMicroseconds
+ ? $this->format('H:i:s.u') === '00:00:00.000000'
+ : $this->format('H:i:s') === '00:00:00';
+ }
+
+ /**
+ * Check if the instance is end of day.
+ *
+ * @param bool $checkMicroseconds check time at microseconds precision
+ * /!\ Warning, this is not reliable with PHP < 7.1.4
+ *
+ * @return bool
+ */
+ public function isEndOfDay($checkMicroseconds = false)
+ {
+ return $checkMicroseconds
+ ? $this->format('H:i:s.u') === '23:59:59.999999'
+ : $this->format('H:i:s') === '23:59:59';
+ }
+
+ /**
+ * Check if the instance is start of day / midnight.
+ *
+ * @return bool
+ */
+ public function isMidnight()
+ {
+ return $this->isStartOfDay();
+ }
+
+ /**
+ * Check if the instance is midday.
+ *
+ * @return bool
+ */
+ public function isMidday()
+ {
+ return $this->format('G:i:s') === static::$midDayAt.':00:00';
+ }
+
+ /**
+ * Checks if the (date)time string is in a given format.
+ *
+ * @param string $date
+ * @param string $format
+ *
+ * @return bool
+ */
+ public static function hasFormat($date, $format)
+ {
+ try {
+ // Try to create a DateTime object. Throws an InvalidArgumentException if the provided time string
+ // doesn't match the format in any way.
+ static::createFromFormat($format, $date);
+
+ // createFromFormat() is known to handle edge cases silently.
+ // E.g. "1975-5-1" (Y-n-j) will still be parsed correctly when "Y-m-d" is supplied as the format.
+ // To ensure we're really testing against our desired format, perform an additional regex validation.
+ $regex = strtr(
+ preg_quote($format, '/'),
+ static::$regexFormats
+ );
+
+ return (bool) preg_match('/^'.$regex.'$/', $date);
+ } catch (InvalidArgumentException $e) {
+ }
+
+ return false;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////// ADDITIONS AND SUBTRACTIONS ////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Add centuries to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addCenturies($value)
+ {
+ return $this->addYears(static::YEARS_PER_CENTURY * $value);
+ }
+
+ /**
+ * Add a century to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addCentury($value = 1)
+ {
+ return $this->addCenturies($value);
+ }
+
+ /**
+ * Remove centuries from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subCenturies($value)
+ {
+ return $this->addCenturies(-1 * $value);
+ }
+
+ /**
+ * Remove a century from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subCentury($value = 1)
+ {
+ return $this->subCenturies($value);
+ }
+
+ /**
+ * Add years to the instance. Positive $value travel forward while
+ * negative $value travel into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addYears($value)
+ {
+ if ($this->shouldOverflowYears()) {
+ return $this->addYearsWithOverflow($value);
+ }
+
+ return $this->addYearsNoOverflow($value);
+ }
+
+ /**
+ * Add a year to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addYear($value = 1)
+ {
+ return $this->addYears($value);
+ }
+
+ /**
+ * Add years to the instance with no overflow of months
+ * Positive $value travel forward while
+ * negative $value travel into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addYearsNoOverflow($value)
+ {
+ return $this->addMonthsNoOverflow($value * static::MONTHS_PER_YEAR);
+ }
+
+ /**
+ * Add year with overflow months set to false
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addYearNoOverflow($value = 1)
+ {
+ return $this->addYearsNoOverflow($value);
+ }
+
+ /**
+ * Add years to the instance.
+ * Positive $value travel forward while
+ * negative $value travel into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addYearsWithOverflow($value)
+ {
+ return $this->modify((int) $value.' year');
+ }
+
+ /**
+ * Add year with overflow.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addYearWithOverflow($value = 1)
+ {
+ return $this->addYearsWithOverflow($value);
+ }
+
+ /**
+ * Remove years from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYears($value)
+ {
+ return $this->addYears(-1 * $value);
+ }
+
+ /**
+ * Remove a year from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYear($value = 1)
+ {
+ return $this->subYears($value);
+ }
+
+ /**
+ * Remove years from the instance with no month overflow.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYearsNoOverflow($value)
+ {
+ return $this->subMonthsNoOverflow($value * static::MONTHS_PER_YEAR);
+ }
+
+ /**
+ * Remove year from the instance with no month overflow
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYearNoOverflow($value = 1)
+ {
+ return $this->subYearsNoOverflow($value);
+ }
+
+ /**
+ * Remove years from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYearsWithOverflow($value)
+ {
+ return $this->subMonthsWithOverflow($value * static::MONTHS_PER_YEAR);
+ }
+
+ /**
+ * Remove year from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subYearWithOverflow($value = 1)
+ {
+ return $this->subYearsWithOverflow($value);
+ }
+
+ /**
+ * Add quarters to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addQuarters($value)
+ {
+ return $this->addMonths(static::MONTHS_PER_QUARTER * $value);
+ }
+
+ /**
+ * Add a quarter to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addQuarter($value = 1)
+ {
+ return $this->addQuarters($value);
+ }
+
+ /**
+ * Remove quarters from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subQuarters($value)
+ {
+ return $this->addQuarters(-1 * $value);
+ }
+
+ /**
+ * Remove a quarter from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subQuarter($value = 1)
+ {
+ return $this->subQuarters($value);
+ }
+
+ /**
+ * Add months to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMonths($value)
+ {
+ if (static::shouldOverflowMonths()) {
+ return $this->addMonthsWithOverflow($value);
+ }
+
+ return $this->addMonthsNoOverflow($value);
+ }
+
+ /**
+ * Add a month to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMonth($value = 1)
+ {
+ return $this->addMonths($value);
+ }
+
+ /**
+ * Remove months from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subMonths($value)
+ {
+ return $this->addMonths(-1 * $value);
+ }
+
+ /**
+ * Remove a month from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subMonth($value = 1)
+ {
+ return $this->subMonths($value);
+ }
+
+ /**
+ * Add months to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMonthsWithOverflow($value)
+ {
+ return $this->modify((int) $value.' month');
+ }
+
+ /**
+ * Add a month to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMonthWithOverflow($value = 1)
+ {
+ return $this->addMonthsWithOverflow($value);
+ }
+
+ /**
+ * Remove months from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subMonthsWithOverflow($value)
+ {
+ return $this->addMonthsWithOverflow(-1 * $value);
+ }
+
+ /**
+ * Remove a month from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subMonthWithOverflow($value = 1)
+ {
+ return $this->subMonthsWithOverflow($value);
+ }
+
+ /**
+ * Add months without overflowing to the instance. Positive $value
+ * travels forward while negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMonthsNoOverflow($value)
+ {
+ $day = $this->day;
+
+ $this->modify((int) $value.' month');
+
+ if ($day !== $this->day) {
+ $this->modify('last day of previous month');
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add a month with no overflow to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMonthNoOverflow($value = 1)
+ {
+ return $this->addMonthsNoOverflow($value);
+ }
+
+ /**
+ * Remove months with no overflow from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subMonthsNoOverflow($value)
+ {
+ return $this->addMonthsNoOverflow(-1 * $value);
+ }
+
+ /**
+ * Remove a month with no overflow from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subMonthNoOverflow($value = 1)
+ {
+ return $this->subMonthsNoOverflow($value);
+ }
+
+ /**
+ * Add days to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addDays($value)
+ {
+ return $this->modify((int) $value.' day');
+ }
+
+ /**
+ * Add a day to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addDay($value = 1)
+ {
+ return $this->addDays($value);
+ }
+
+ /**
+ * Remove days from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subDays($value)
+ {
+ return $this->addDays(-1 * $value);
+ }
+
+ /**
+ * Remove a day from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subDay($value = 1)
+ {
+ return $this->subDays($value);
+ }
+
+ /**
+ * Add weekdays to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addWeekdays($value)
+ {
+ // Fix for weekday bug https://bugs.php.net/bug.php?id=54909
+ $t = $this->toTimeString();
+ $this->modify((int) $value.' weekday');
+
+ return $this->setTimeFromTimeString($t);
+ }
+
+ /**
+ * Add a weekday to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addWeekday($value = 1)
+ {
+ return $this->addWeekdays($value);
+ }
+
+ /**
+ * Remove weekdays from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subWeekdays($value)
+ {
+ return $this->addWeekdays(-1 * $value);
+ }
+
+ /**
+ * Remove a weekday from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subWeekday($value = 1)
+ {
+ return $this->subWeekdays($value);
+ }
+
+ /**
+ * Add weeks to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addWeeks($value)
+ {
+ return $this->modify((int) $value.' week');
+ }
+
+ /**
+ * Add a week to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addWeek($value = 1)
+ {
+ return $this->addWeeks($value);
+ }
+
+ /**
+ * Remove weeks to the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subWeeks($value)
+ {
+ return $this->addWeeks(-1 * $value);
+ }
+
+ /**
+ * Remove a week from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subWeek($value = 1)
+ {
+ return $this->subWeeks($value);
+ }
+
+ /**
+ * Add hours to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addHours($value)
+ {
+ return $this->modify((int) $value.' hour');
+ }
+
+ /**
+ * Add hours to the instance using timestamp. Positive $value travels
+ * forward while negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealHours($value)
+ {
+ return $this->addRealMinutes($value * static::MINUTES_PER_HOUR);
+ }
+
+ /**
+ * Add an hour to the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addHour($value = 1)
+ {
+ return $this->addHours($value);
+ }
+
+ /**
+ * Add an hour to the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealHour($value = 1)
+ {
+ return $this->addRealHours($value);
+ }
+
+ /**
+ * Remove hours from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subHours($value)
+ {
+ return $this->addHours(-1 * $value);
+ }
+
+ /**
+ * Remove hours from the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subRealHours($value)
+ {
+ return $this->addRealHours(-1 * $value);
+ }
+
+ /**
+ * Remove an hour from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subHour($value = 1)
+ {
+ return $this->subHours($value);
+ }
+
+ /**
+ * Remove an hour from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subRealHour($value = 1)
+ {
+ return $this->subRealHours($value);
+ }
+
+ /**
+ * Add minutes to the instance using timestamp. Positive $value
+ * travels forward while negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMinutes($value)
+ {
+ return $this->modify((int) $value.' minute');
+ }
+
+ /**
+ * Add minutes to the instance using timestamp. Positive $value travels
+ * forward while negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealMinutes($value)
+ {
+ return $this->addRealSeconds($value * static::SECONDS_PER_MINUTE);
+ }
+
+ /**
+ * Add a minute to the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addMinute($value = 1)
+ {
+ return $this->addMinutes($value);
+ }
+
+ /**
+ * Add a minute to the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealMinute($value = 1)
+ {
+ return $this->addRealMinutes($value);
+ }
+
+ /**
+ * Remove a minute from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subMinute($value = 1)
+ {
+ return $this->subMinutes($value);
+ }
+
+ /**
+ * Remove a minute from the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subRealMinute($value = 1)
+ {
+ return $this->addRealMinutes(-1 * $value);
+ }
+
+ /**
+ * Remove minutes from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subMinutes($value)
+ {
+ return $this->addMinutes(-1 * $value);
+ }
+
+ /**
+ * Remove a minute from the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subRealMinutes($value = 1)
+ {
+ return $this->subRealMinute($value);
+ }
+
+ /**
+ * Add seconds to the instance. Positive $value travels forward while
+ * negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addSeconds($value)
+ {
+ return $this->modify((int) $value.' second');
+ }
+
+ /**
+ * Add seconds to the instance using timestamp. Positive $value travels
+ * forward while negative $value travels into the past.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealSeconds($value)
+ {
+ return $this->setTimestamp($this->getTimestamp() + $value);
+ }
+
+ /**
+ * Add a second to the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addSecond($value = 1)
+ {
+ return $this->addSeconds($value);
+ }
+
+ /**
+ * Add a second to the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function addRealSecond($value = 1)
+ {
+ return $this->addRealSeconds($value);
+ }
+
+ /**
+ * Remove seconds from the instance.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subSeconds($value)
+ {
+ return $this->addSeconds(-1 * $value);
+ }
+
+ /**
+ * Remove seconds from the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subRealSeconds($value)
+ {
+ return $this->addRealSeconds(-1 * $value);
+ }
+
+ /**
+ * Remove a second from the instance
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subSecond($value = 1)
+ {
+ return $this->subSeconds($value);
+ }
+
+ /**
+ * Remove a second from the instance using timestamp.
+ *
+ * @param int $value
+ *
+ * @return static
+ */
+ public function subRealSecond($value = 1)
+ {
+ return $this->subRealSeconds($value);
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////////// DIFFERENCES ///////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * @param DateInterval $diff
+ * @param bool $absolute
+ * @param bool $trimMicroseconds
+ *
+ * @return CarbonInterval
+ */
+ protected static function fixDiffInterval(DateInterval $diff, $absolute, $trimMicroseconds)
+ {
+ $diff = CarbonInterval::instance($diff, $trimMicroseconds);
+
+ // @codeCoverageIgnoreStart
+ if (version_compare(PHP_VERSION, '7.1.0-dev', '<')) {
+ return $diff;
+ }
+
+ // Work-around for https://bugs.php.net/bug.php?id=77145
+ if ($diff->f > 0 && $diff->y === -1 && $diff->m === 11 && $diff->d >= 27 && $diff->h === 23 && $diff->i === 59 && $diff->s === 59) {
+ $diff->y = 0;
+ $diff->m = 0;
+ $diff->d = 0;
+ $diff->h = 0;
+ $diff->i = 0;
+ $diff->s = 0;
+ $diff->f = (1000000 - round($diff->f * 1000000)) / 1000000;
+ $diff->invert();
+ } elseif ($diff->f < 0) {
+ if ($diff->s !== 0 || $diff->i !== 0 || $diff->h !== 0 || $diff->d !== 0 || $diff->m !== 0 || $diff->y !== 0) {
+ $diff->f = (round($diff->f * 1000000) + 1000000) / 1000000;
+ $diff->s--;
+ if ($diff->s < 0) {
+ $diff->s += 60;
+ $diff->i--;
+ if ($diff->i < 0) {
+ $diff->i += 60;
+ $diff->h--;
+ if ($diff->h < 0) {
+ $diff->h += 24;
+ $diff->d--;
+ if ($diff->d < 0) {
+ $diff->d += 30;
+ $diff->m--;
+ if ($diff->m < 0) {
+ $diff->m += 12;
+ $diff->y--;
+ }
+ }
+ }
+ }
+ }
+ } else {
+ $diff->f *= -1;
+ $diff->invert();
+ }
+ }
+ // @codeCoverageIgnoreEnd
+ if ($absolute && $diff->invert) {
+ $diff->invert();
+ }
+
+ return $diff;
+ }
+
+ /**
+ * Get the difference as a CarbonInterval instance.
+ *
+ * Pass false as second argument to get a microseconds-precise interval. Else
+ * microseconds in the original interval will not be kept.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ * @param bool $trimMicroseconds (true by default)
+ *
+ * @return CarbonInterval
+ */
+ public function diffAsCarbonInterval($date = null, $absolute = true, $trimMicroseconds = true)
+ {
+ $from = $this;
+ $to = $this->resolveCarbon($date);
+
+ if ($trimMicroseconds) {
+ $from = $from->copy()->startOfSecond();
+ $to = $to->copy()->startOfSecond();
+ }
+
+ return static::fixDiffInterval($from->diff($to, $absolute), $absolute, $trimMicroseconds);
+ }
+
+ /**
+ * Get the difference in years
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInYears($date = null, $absolute = true)
+ {
+ return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%y');
+ }
+
+ /**
+ * Get the difference in months
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMonths($date = null, $absolute = true)
+ {
+ $date = $this->resolveCarbon($date);
+
+ return $this->diffInYears($date, $absolute) * static::MONTHS_PER_YEAR + (int) $this->diff($date, $absolute)->format('%r%m');
+ }
+
+ /**
+ * Get the difference in weeks
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInWeeks($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInDays($date, $absolute) / static::DAYS_PER_WEEK);
+ }
+
+ /**
+ * Get the difference in days
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInDays($date = null, $absolute = true)
+ {
+ return (int) $this->diff($this->resolveCarbon($date), $absolute)->format('%r%a');
+ }
+
+ /**
+ * Get the difference in days using a filter closure
+ *
+ * @param Closure $callback
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInDaysFiltered(Closure $callback, $date = null, $absolute = true)
+ {
+ return $this->diffFiltered(CarbonInterval::day(), $callback, $date, $absolute);
+ }
+
+ /**
+ * Get the difference in hours using a filter closure
+ *
+ * @param Closure $callback
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInHoursFiltered(Closure $callback, $date = null, $absolute = true)
+ {
+ return $this->diffFiltered(CarbonInterval::hour(), $callback, $date, $absolute);
+ }
+
+ /**
+ * Get the difference by the given interval using a filter closure
+ *
+ * @param CarbonInterval $ci An interval to traverse by
+ * @param Closure $callback
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffFiltered(CarbonInterval $ci, Closure $callback, $date = null, $absolute = true)
+ {
+ $start = $this;
+ $end = $this->resolveCarbon($date);
+ $inverse = false;
+
+ if ($end < $start) {
+ $start = $end;
+ $end = $this;
+ $inverse = true;
+ }
+
+ $period = new DatePeriod($start, $ci, $end);
+ $values = array_filter(iterator_to_array($period), function ($date) use ($callback) {
+ return call_user_func($callback, Carbon::instance($date));
+ });
+
+ $diff = count($values);
+
+ return $inverse && !$absolute ? -$diff : $diff;
+ }
+
+ /**
+ * Get the difference in weekdays
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInWeekdays($date = null, $absolute = true)
+ {
+ return $this->diffInDaysFiltered(function (Carbon $date) {
+ return $date->isWeekday();
+ }, $date, $absolute);
+ }
+
+ /**
+ * Get the difference in weekend days using a filter
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInWeekendDays($date = null, $absolute = true)
+ {
+ return $this->diffInDaysFiltered(function (Carbon $date) {
+ return $date->isWeekend();
+ }, $date, $absolute);
+ }
+
+ /**
+ * Get the difference in hours.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInHours($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
+ }
+
+ /**
+ * Get the difference in hours using timestamps.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealHours($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE / static::MINUTES_PER_HOUR);
+ }
+
+ /**
+ * Get the difference in minutes.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMinutes($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
+ }
+
+ /**
+ * Get the difference in minutes using timestamps.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealMinutes($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInRealSeconds($date, $absolute) / static::SECONDS_PER_MINUTE);
+ }
+
+ /**
+ * Get the difference in seconds.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInSeconds($date = null, $absolute = true)
+ {
+ $diff = $this->diff($this->resolveCarbon($date));
+ if (!$diff->days && version_compare(PHP_VERSION, '5.4.0-dev', '>=')) {
+ $diff = static::fixDiffInterval($diff, $absolute, false);
+ }
+ $value = $diff->days * static::HOURS_PER_DAY * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE +
+ $diff->h * static::MINUTES_PER_HOUR * static::SECONDS_PER_MINUTE +
+ $diff->i * static::SECONDS_PER_MINUTE +
+ $diff->s;
+
+ return $absolute || !$diff->invert ? $value : -$value;
+ }
+
+ /**
+ * Get the difference in seconds using timestamps.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealSeconds($date = null, $absolute = true)
+ {
+ $date = $this->resolveCarbon($date);
+ $value = $date->getTimestamp() - $this->getTimestamp();
+
+ return $absolute ? abs($value) : $value;
+ }
+
+ /**
+ * Get the difference in milliseconds.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMilliseconds($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND);
+ }
+
+ /**
+ * Get the difference in milliseconds using timestamps.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealMilliseconds($date = null, $absolute = true)
+ {
+ return (int) ($this->diffInRealMicroseconds($date, $absolute) / static::MICROSECONDS_PER_MILLISECOND);
+ }
+
+ /**
+ * Get the difference in microseconds.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInMicroseconds($date = null, $absolute = true)
+ {
+ $diff = $this->diff($this->resolveCarbon($date));
+ $micro = isset($diff->f) ? $diff->f : 0;
+ $value = (int) round((((($diff->days * static::HOURS_PER_DAY) +
+ $diff->h) * static::MINUTES_PER_HOUR +
+ $diff->i) * static::SECONDS_PER_MINUTE +
+ ($micro + $diff->s)) * static::MICROSECONDS_PER_SECOND);
+
+ return $absolute || !$diff->invert ? $value : -$value;
+ }
+
+ /**
+ * Get the difference in microseconds using timestamps.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ * @param bool $absolute Get the absolute of the difference
+ *
+ * @return int
+ */
+ public function diffInRealMicroseconds($date = null, $absolute = true)
+ {
+ /** @var Carbon $date */
+ $date = $this->resolveCarbon($date);
+ $value = ($date->timestamp - $this->timestamp) * static::MICROSECONDS_PER_SECOND +
+ $date->micro - $this->micro;
+
+ return $absolute ? abs($value) : $value;
+ }
+
+ /**
+ * The number of seconds since midnight.
+ *
+ * @return int
+ */
+ public function secondsSinceMidnight()
+ {
+ return $this->diffInSeconds($this->copy()->startOfDay());
+ }
+
+ /**
+ * The number of seconds until 23:59:59.
+ *
+ * @return int
+ */
+ public function secondsUntilEndOfDay()
+ {
+ return $this->diffInSeconds($this->copy()->endOfDay());
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale.
+ *
+ * When comparing a value in the past to default now:
+ * 1 hour ago
+ * 5 months ago
+ *
+ * When comparing a value in the future to default now:
+ * 1 hour from now
+ * 5 months from now
+ *
+ * When comparing a value in the past to another value:
+ * 1 hour before
+ * 5 months before
+ *
+ * When comparing a value in the future to another value:
+ * 1 hour after
+ * 5 months after
+ *
+ * @param Carbon|null $other
+ * @param bool $absolute removes time difference modifiers ago, after, etc
+ * @param bool $short displays short format of time units
+ * @param int $parts displays number of parts in the interval
+ *
+ * @return string
+ */
+ public function diffForHumans($other = null, $absolute = false, $short = false, $parts = 1)
+ {
+ $isNow = $other === null;
+ $relativeToNow = $isNow;
+
+ if ($absolute === static::DIFF_RELATIVE_TO_NOW) {
+ $absolute = false;
+ $relativeToNow = true;
+ } elseif ($absolute === static::DIFF_RELATIVE_TO_OTHER) {
+ $absolute = false;
+ $relativeToNow = false;
+ }
+
+ $interval = array();
+
+ $parts = min(6, max(1, (int) $parts));
+ $count = 1;
+ $unit = $short ? 's' : 'second';
+
+ if ($isNow) {
+ $other = $this->nowWithSameTz();
+ } elseif (!$other instanceof DateTime && !$other instanceof DateTimeInterface) {
+ $other = static::parse($other);
+ }
+
+ $diffInterval = $this->diff($other);
+
+ $diffIntervalArray = array(
+ array('value' => $diffInterval->y, 'unit' => 'year', 'unitShort' => 'y'),
+ array('value' => $diffInterval->m, 'unit' => 'month', 'unitShort' => 'm'),
+ array('value' => $diffInterval->d, 'unit' => 'day', 'unitShort' => 'd'),
+ array('value' => $diffInterval->h, 'unit' => 'hour', 'unitShort' => 'h'),
+ array('value' => $diffInterval->i, 'unit' => 'minute', 'unitShort' => 'min'),
+ array('value' => $diffInterval->s, 'unit' => 'second', 'unitShort' => 's'),
+ );
+
+ foreach ($diffIntervalArray as $diffIntervalData) {
+ if ($diffIntervalData['value'] > 0) {
+ $unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
+ $count = $diffIntervalData['value'];
+
+ if ($diffIntervalData['unit'] === 'day' && $count >= static::DAYS_PER_WEEK) {
+ $unit = $short ? 'w' : 'week';
+ $count = (int) ($count / static::DAYS_PER_WEEK);
+
+ $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count));
+
+ // get the count days excluding weeks (might be zero)
+ $numOfDaysCount = (int) ($diffIntervalData['value'] - ($count * static::DAYS_PER_WEEK));
+
+ if ($numOfDaysCount > 0 && count($interval) < $parts) {
+ $unit = $short ? 'd' : 'day';
+ $count = $numOfDaysCount;
+ $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count));
+ }
+ } else {
+ $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count));
+ }
+ }
+
+ // break the loop after we get the required number of parts in array
+ if (count($interval) >= $parts) {
+ break;
+ }
+ }
+
+ if (count($interval) === 0) {
+ if ($isNow && static::getHumanDiffOptions() & self::JUST_NOW) {
+ $key = 'diff_now';
+ $translation = static::translator()->trans($key);
+ if ($translation !== $key) {
+ return $translation;
+ }
+ }
+ $count = static::getHumanDiffOptions() & self::NO_ZERO_DIFF ? 1 : 0;
+ $unit = $short ? 's' : 'second';
+ $interval[] = static::translator()->transChoice($unit, $count, array(':count' => $count));
+ }
+
+ // join the interval parts by a space
+ $time = implode(' ', $interval);
+
+ unset($diffIntervalArray, $interval);
+
+ if ($absolute) {
+ return $time;
+ }
+
+ $isFuture = $diffInterval->invert === 1;
+
+ $transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
+
+ if ($parts === 1) {
+ if ($isNow && $unit === 'day') {
+ if ($count === 1 && static::getHumanDiffOptions() & self::ONE_DAY_WORDS) {
+ $key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday';
+ $translation = static::translator()->trans($key);
+ if ($translation !== $key) {
+ return $translation;
+ }
+ }
+ if ($count === 2 && static::getHumanDiffOptions() & self::TWO_DAY_WORDS) {
+ $key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday';
+ $translation = static::translator()->trans($key);
+ if ($translation !== $key) {
+ return $translation;
+ }
+ }
+ }
+ // Some languages have special pluralization for past and future tense.
+ $key = $unit.'_'.$transId;
+ if ($key !== static::translator()->transChoice($key, $count)) {
+ $time = static::translator()->transChoice($key, $count, array(':count' => $count));
+ }
+ }
+
+ return static::translator()->trans($transId, array(':time' => $time));
+ }
+
+ /**
+ * @alias diffForHumans
+ *
+ * Get the difference in a human readable format in the current locale.
+ *
+ * When comparing a value in the past to default now:
+ * 1 hour ago
+ * 5 months ago
+ *
+ * When comparing a value in the future to default now:
+ * 1 hour from now
+ * 5 months from now
+ *
+ * When comparing a value in the past to another value:
+ * 1 hour before
+ * 5 months before
+ *
+ * When comparing a value in the future to another value:
+ * 1 hour after
+ * 5 months after
+ *
+ * @param Carbon|null $other
+ * @param bool $absolute removes time difference modifiers ago, after, etc
+ * @param bool $short displays short format of time units
+ * @param int $parts displays number of parts in the interval
+ *
+ * @return string
+ */
+ public function from($other = null, $absolute = false, $short = false, $parts = 1)
+ {
+ if (!$other && !$absolute) {
+ $absolute = static::DIFF_RELATIVE_TO_NOW;
+ }
+
+ return $this->diffForHumans($other, $absolute, $short, $parts);
+ }
+
+ /**
+ * @alias diffForHumans
+ *
+ * Get the difference in a human readable format in the current locale.
+ *
+ * When comparing a value in the past to default now:
+ * 1 hour ago
+ * 5 months ago
+ *
+ * When comparing a value in the future to default now:
+ * 1 hour from now
+ * 5 months from now
+ *
+ * When comparing a value in the past to another value:
+ * 1 hour before
+ * 5 months before
+ *
+ * When comparing a value in the future to another value:
+ * 1 hour after
+ * 5 months after
+ *
+ * @param Carbon|null $other
+ * @param bool $absolute removes time difference modifiers ago, after, etc
+ * @param bool $short displays short format of time units
+ * @param int $parts displays number of parts in the interval
+ *
+ * @return string
+ */
+ public function since($other = null, $absolute = false, $short = false, $parts = 1)
+ {
+ return $this->diffForHumans($other, $absolute, $short, $parts);
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given (or now if null given) to current instance.
+ *
+ * When comparing a value in the past to default now:
+ * 1 hour from now
+ * 5 months from now
+ *
+ * When comparing a value in the future to default now:
+ * 1 hour ago
+ * 5 months ago
+ *
+ * When comparing a value in the past to another value:
+ * 1 hour after
+ * 5 months after
+ *
+ * When comparing a value in the future to another value:
+ * 1 hour before
+ * 5 months before
+ *
+ * @param Carbon|null $other
+ * @param bool $absolute removes time difference modifiers ago, after, etc
+ * @param bool $short displays short format of time units
+ * @param int $parts displays number of parts in the interval
+ *
+ * @return string
+ */
+ public function to($other = null, $absolute = false, $short = false, $parts = 1)
+ {
+ if (!$other && !$absolute) {
+ $absolute = static::DIFF_RELATIVE_TO_NOW;
+ }
+
+ return $this->resolveCarbon($other)->diffForHumans($this, $absolute, $short, $parts);
+ }
+
+ /**
+ * @alias to
+ *
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given (or now if null given) to current instance.
+ *
+ * @param Carbon|null $other
+ * @param bool $absolute removes time difference modifiers ago, after, etc
+ * @param bool $short displays short format of time units
+ * @param int $parts displays number of parts in the interval
+ *
+ * @return string
+ */
+ public function until($other = null, $absolute = false, $short = false, $parts = 1)
+ {
+ return $this->to($other, $absolute, $short, $parts);
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from current
+ * instance to now.
+ *
+ * @param bool $absolute removes time difference modifiers ago, after, etc
+ * @param bool $short displays short format of time units
+ * @param int $parts displays number of parts in the interval
+ *
+ * @return string
+ */
+ public function fromNow($absolute = null, $short = false, $parts = 1)
+ {
+ $other = null;
+
+ if ($absolute instanceof DateTimeInterface) {
+ list($other, $absolute, $short, $parts) = array_pad(func_get_args(), 5, null);
+ }
+
+ return $this->from($other, $absolute, $short, $parts);
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given to now
+ *
+ * @param bool $absolute removes time difference modifiers ago, after, etc
+ * @param bool $short displays short format of time units
+ * @param int $parts displays number of parts in the interval
+ *
+ * @return string
+ */
+ public function toNow($absolute = null, $short = false, $parts = 1)
+ {
+ return $this->to(null, $absolute, $short, $parts);
+ }
+
+ /**
+ * Get the difference in a human readable format in the current locale from an other
+ * instance given to now
+ *
+ * @param bool $absolute removes time difference modifiers ago, after, etc
+ * @param bool $short displays short format of time units
+ * @param int $parts displays number of parts in the interval
+ *
+ * @return string
+ */
+ public function ago($absolute = null, $short = false, $parts = 1)
+ {
+ $other = null;
+
+ if ($absolute instanceof DateTimeInterface) {
+ list($other, $absolute, $short, $parts) = array_pad(func_get_args(), 5, null);
+ }
+
+ return $this->from($other, $absolute, $short, $parts);
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //////////////////////////// MODIFIERS ////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Resets the time to 00:00:00 start of day
+ *
+ * @return static
+ */
+ public function startOfDay()
+ {
+ return $this->modify('00:00:00.000000');
+ }
+
+ /**
+ * Resets the time to 23:59:59 end of day
+ *
+ * @return static
+ */
+ public function endOfDay()
+ {
+ return $this->modify('23:59:59.999999');
+ }
+
+ /**
+ * Resets the date to the first day of the month and the time to 00:00:00
+ *
+ * @return static
+ */
+ public function startOfMonth()
+ {
+ return $this->setDate($this->year, $this->month, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the month and time to 23:59:59
+ *
+ * @return static
+ */
+ public function endOfMonth()
+ {
+ return $this->setDate($this->year, $this->month, $this->daysInMonth)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of the quarter and the time to 00:00:00
+ *
+ * @return static
+ */
+ public function startOfQuarter()
+ {
+ $month = ($this->quarter - 1) * static::MONTHS_PER_QUARTER + 1;
+
+ return $this->setDate($this->year, $month, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the quarter and time to 23:59:59
+ *
+ * @return static
+ */
+ public function endOfQuarter()
+ {
+ return $this->startOfQuarter()->addMonths(static::MONTHS_PER_QUARTER - 1)->endOfMonth();
+ }
+
+ /**
+ * Resets the date to the first day of the year and the time to 00:00:00
+ *
+ * @return static
+ */
+ public function startOfYear()
+ {
+ return $this->setDate($this->year, 1, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the year and time to 23:59:59
+ *
+ * @return static
+ */
+ public function endOfYear()
+ {
+ return $this->setDate($this->year, 12, 31)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of the decade and the time to 00:00:00
+ *
+ * @return static
+ */
+ public function startOfDecade()
+ {
+ $year = $this->year - $this->year % static::YEARS_PER_DECADE;
+
+ return $this->setDate($year, 1, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the decade and time to 23:59:59
+ *
+ * @return static
+ */
+ public function endOfDecade()
+ {
+ $year = $this->year - $this->year % static::YEARS_PER_DECADE + static::YEARS_PER_DECADE - 1;
+
+ return $this->setDate($year, 12, 31)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of the century and the time to 00:00:00
+ *
+ * @return static
+ */
+ public function startOfCentury()
+ {
+ $year = $this->year - ($this->year - 1) % static::YEARS_PER_CENTURY;
+
+ return $this->setDate($year, 1, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the century and time to 23:59:59
+ *
+ * @return static
+ */
+ public function endOfCentury()
+ {
+ $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_CENTURY + static::YEARS_PER_CENTURY;
+
+ return $this->setDate($year, 12, 31)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of the century and the time to 00:00:00
+ *
+ * @return static
+ */
+ public function startOfMillennium()
+ {
+ $year = $this->year - ($this->year - 1) % static::YEARS_PER_MILLENNIUM;
+
+ return $this->setDate($year, 1, 1)->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of the century and time to 23:59:59
+ *
+ * @return static
+ */
+ public function endOfMillennium()
+ {
+ $year = $this->year - 1 - ($this->year - 1) % static::YEARS_PER_MILLENNIUM + static::YEARS_PER_MILLENNIUM;
+
+ return $this->setDate($year, 12, 31)->endOfDay();
+ }
+
+ /**
+ * Resets the date to the first day of week (defined in $weekStartsAt) and the time to 00:00:00
+ *
+ * @return static
+ */
+ public function startOfWeek()
+ {
+ while ($this->dayOfWeek !== static::$weekStartsAt) {
+ $this->subDay();
+ }
+
+ return $this->startOfDay();
+ }
+
+ /**
+ * Resets the date to end of week (defined in $weekEndsAt) and time to 23:59:59
+ *
+ * @return static
+ */
+ public function endOfWeek()
+ {
+ while ($this->dayOfWeek !== static::$weekEndsAt) {
+ $this->addDay();
+ }
+
+ return $this->endOfDay();
+ }
+
+ /**
+ * Modify to start of current hour, minutes and seconds become 0
+ *
+ * @return static
+ */
+ public function startOfHour()
+ {
+ return $this->setTime($this->hour, 0, 0);
+ }
+
+ /**
+ * Modify to end of current hour, minutes and seconds become 59
+ *
+ * @return static
+ */
+ public function endOfHour()
+ {
+ return $this->modify("$this->hour:59:59.999999");
+ }
+
+ /**
+ * Modify to start of current minute, seconds become 0
+ *
+ * @return static
+ */
+ public function startOfMinute()
+ {
+ return $this->setTime($this->hour, $this->minute, 0);
+ }
+
+ /**
+ * Modify to end of current minute, seconds become 59
+ *
+ * @return static
+ */
+ public function endOfMinute()
+ {
+ return $this->modify("$this->hour:$this->minute:59.999999");
+ }
+
+ /**
+ * Modify to start of current minute, seconds become 0
+ *
+ * @return static
+ */
+ public function startOfSecond()
+ {
+ return $this->modify("$this->hour:$this->minute:$this->second.0");
+ }
+
+ /**
+ * Modify to end of current minute, seconds become 59
+ *
+ * @return static
+ */
+ public function endOfSecond()
+ {
+ return $this->modify("$this->hour:$this->minute:$this->second.999999");
+ }
+
+ /**
+ * Modify to midday, default to self::$midDayAt
+ *
+ * @return static
+ */
+ public function midDay()
+ {
+ return $this->setTime(self::$midDayAt, 0, 0);
+ }
+
+ /**
+ * Modify to the next occurrence of a given day of the week.
+ * If no dayOfWeek is provided, modify to the next occurrence
+ * of the current day of the week. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek
+ *
+ * @return static
+ */
+ public function next($dayOfWeek = null)
+ {
+ if ($dayOfWeek === null) {
+ $dayOfWeek = $this->dayOfWeek;
+ }
+
+ return $this->startOfDay()->modify('next '.static::$days[$dayOfWeek]);
+ }
+
+ /**
+ * Go forward or backward to the next week- or weekend-day.
+ *
+ * @param bool $weekday
+ * @param bool $forward
+ *
+ * @return $this
+ */
+ private function nextOrPreviousDay($weekday = true, $forward = true)
+ {
+ $step = $forward ? 1 : -1;
+
+ do {
+ $this->addDay($step);
+ } while ($weekday ? $this->isWeekend() : $this->isWeekday());
+
+ return $this;
+ }
+
+ /**
+ * Go forward to the next weekday.
+ *
+ * @return $this
+ */
+ public function nextWeekday()
+ {
+ return $this->nextOrPreviousDay();
+ }
+
+ /**
+ * Go backward to the previous weekday.
+ *
+ * @return $this
+ */
+ public function previousWeekday()
+ {
+ return $this->nextOrPreviousDay(true, false);
+ }
+
+ /**
+ * Go forward to the next weekend day.
+ *
+ * @return $this
+ */
+ public function nextWeekendDay()
+ {
+ return $this->nextOrPreviousDay(false);
+ }
+
+ /**
+ * Go backward to the previous weekend day.
+ *
+ * @return $this
+ */
+ public function previousWeekendDay()
+ {
+ return $this->nextOrPreviousDay(false, false);
+ }
+
+ /**
+ * Modify to the previous occurrence of a given day of the week.
+ * If no dayOfWeek is provided, modify to the previous occurrence
+ * of the current day of the week. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek
+ *
+ * @return static
+ */
+ public function previous($dayOfWeek = null)
+ {
+ if ($dayOfWeek === null) {
+ $dayOfWeek = $this->dayOfWeek;
+ }
+
+ return $this->startOfDay()->modify('last '.static::$days[$dayOfWeek]);
+ }
+
+ /**
+ * Modify to the first occurrence of a given day of the week
+ * in the current month. If no dayOfWeek is provided, modify to the
+ * first day of the current month. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek
+ *
+ * @return static
+ */
+ public function firstOfMonth($dayOfWeek = null)
+ {
+ $this->startOfDay();
+
+ if ($dayOfWeek === null) {
+ return $this->day(1);
+ }
+
+ return $this->modify('first '.static::$days[$dayOfWeek].' of '.$this->format('F').' '.$this->year);
+ }
+
+ /**
+ * Modify to the last occurrence of a given day of the week
+ * in the current month. If no dayOfWeek is provided, modify to the
+ * last day of the current month. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek
+ *
+ * @return static
+ */
+ public function lastOfMonth($dayOfWeek = null)
+ {
+ $this->startOfDay();
+
+ if ($dayOfWeek === null) {
+ return $this->day($this->daysInMonth);
+ }
+
+ return $this->modify('last '.static::$days[$dayOfWeek].' of '.$this->format('F').' '.$this->year);
+ }
+
+ /**
+ * Modify to the given occurrence of a given day of the week
+ * in the current month. If the calculated occurrence is outside the scope
+ * of the current month, then return false and no modifications are made.
+ * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int $nth
+ * @param int $dayOfWeek
+ *
+ * @return mixed
+ */
+ public function nthOfMonth($nth, $dayOfWeek)
+ {
+ $date = $this->copy()->firstOfMonth();
+ $check = $date->format('Y-m');
+ $date->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+
+ return $date->format('Y-m') === $check ? $this->modify($date) : false;
+ }
+
+ /**
+ * Modify to the first occurrence of a given day of the week
+ * in the current quarter. If no dayOfWeek is provided, modify to the
+ * first day of the current quarter. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function firstOfQuarter($dayOfWeek = null)
+ {
+ return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER - 2, 1)->firstOfMonth($dayOfWeek);
+ }
+
+ /**
+ * Modify to the last occurrence of a given day of the week
+ * in the current quarter. If no dayOfWeek is provided, modify to the
+ * last day of the current quarter. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function lastOfQuarter($dayOfWeek = null)
+ {
+ return $this->setDate($this->year, $this->quarter * static::MONTHS_PER_QUARTER, 1)->lastOfMonth($dayOfWeek);
+ }
+
+ /**
+ * Modify to the given occurrence of a given day of the week
+ * in the current quarter. If the calculated occurrence is outside the scope
+ * of the current quarter, then return false and no modifications are made.
+ * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int $nth
+ * @param int $dayOfWeek
+ *
+ * @return mixed
+ */
+ public function nthOfQuarter($nth, $dayOfWeek)
+ {
+ $date = $this->copy()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
+ $lastMonth = $date->month;
+ $year = $date->year;
+ $date->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+
+ return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify($date);
+ }
+
+ /**
+ * Modify to the first occurrence of a given day of the week
+ * in the current year. If no dayOfWeek is provided, modify to the
+ * first day of the current year. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function firstOfYear($dayOfWeek = null)
+ {
+ return $this->month(1)->firstOfMonth($dayOfWeek);
+ }
+
+ /**
+ * Modify to the last occurrence of a given day of the week
+ * in the current year. If no dayOfWeek is provided, modify to the
+ * last day of the current year. Use the supplied constants
+ * to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int|null $dayOfWeek day of the week default null
+ *
+ * @return static
+ */
+ public function lastOfYear($dayOfWeek = null)
+ {
+ return $this->month(static::MONTHS_PER_YEAR)->lastOfMonth($dayOfWeek);
+ }
+
+ /**
+ * Modify to the given occurrence of a given day of the week
+ * in the current year. If the calculated occurrence is outside the scope
+ * of the current year, then return false and no modifications are made.
+ * Use the supplied constants to indicate the desired dayOfWeek, ex. static::MONDAY.
+ *
+ * @param int $nth
+ * @param int $dayOfWeek
+ *
+ * @return mixed
+ */
+ public function nthOfYear($nth, $dayOfWeek)
+ {
+ $date = $this->copy()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+
+ return $this->year === $date->year ? $this->modify($date) : false;
+ }
+
+ /**
+ * Modify the current instance to the average of a given instance (default now) and the current instance.
+ *
+ * @param \Carbon\Carbon|\DateTimeInterface|string|null $date
+ *
+ * @return static
+ */
+ public function average($date = null)
+ {
+ $date = $this->resolveCarbon($date);
+ $increment = $this->diffInRealSeconds($date, false) / 2;
+ $intIncrement = floor($increment);
+ $microIncrement = (int) (($date->micro - $this->micro) / 2 + 1000000 * ($increment - $intIncrement));
+ $micro = (int) ($this->micro + $microIncrement);
+ while ($micro >= 1000000) {
+ $micro -= 1000000;
+ $intIncrement++;
+ }
+ $this->addSeconds($intIncrement);
+
+ if (version_compare(PHP_VERSION, '7.1.8-dev', '>=')) {
+ $this->setTime($this->hour, $this->minute, $this->second, $micro);
+ }
+
+ return $this;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////////// SERIALIZATION /////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Return a serialized string of the instance.
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ return serialize($this);
+ }
+
+ /**
+ * Create an instance from a serialized string.
+ *
+ * @param string $value
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return static
+ */
+ public static function fromSerialized($value)
+ {
+ $instance = @unserialize($value);
+
+ if (!$instance instanceof static) {
+ throw new InvalidArgumentException('Invalid serialized value.');
+ }
+
+ return $instance;
+ }
+
+ /**
+ * The __set_state handler.
+ *
+ * @param array $array
+ *
+ * @return static
+ */
+ public static function __set_state($array)
+ {
+ return static::instance(parent::__set_state($array));
+ }
+
+ /**
+ * Prepare the object for JSON serialization.
+ *
+ * @return array|string
+ */
+ public function jsonSerialize()
+ {
+ if (static::$serializer) {
+ return call_user_func(static::$serializer, $this);
+ }
+
+ $carbon = $this;
+
+ return call_user_func(function () use ($carbon) {
+ return get_object_vars($carbon);
+ });
+ }
+
+ /**
+ * JSON serialize all Carbon instances using the given callback.
+ *
+ * @param callable $callback
+ *
+ * @return void
+ */
+ public static function serializeUsing($callback)
+ {
+ static::$serializer = $callback;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////////////// MACRO /////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Register a custom macro.
+ *
+ * @param string $name
+ * @param object|callable $macro
+ *
+ * @return void
+ */
+ public static function macro($name, $macro)
+ {
+ static::$localMacros[$name] = $macro;
+ }
+
+ /**
+ * Remove all macros.
+ */
+ public static function resetMacros()
+ {
+ static::$localMacros = array();
+ }
+
+ /**
+ * Mix another object into the class.
+ *
+ * @param object $mixin
+ *
+ * @return void
+ */
+ public static function mixin($mixin)
+ {
+ $reflection = new \ReflectionClass($mixin);
+ $methods = $reflection->getMethods(
+ \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED
+ );
+
+ foreach ($methods as $method) {
+ $method->setAccessible(true);
+
+ static::macro($method->name, $method->invoke($mixin));
+ }
+ }
+
+ /**
+ * Checks if macro is registered.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public static function hasMacro($name)
+ {
+ return isset(static::$localMacros[$name]);
+ }
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @throws \BadMethodCallException
+ *
+ * @return mixed
+ */
+ public static function __callStatic($method, $parameters)
+ {
+ if (!static::hasMacro($method)) {
+ throw new \BadMethodCallException("Method $method does not exist.");
+ }
+
+ if (static::$localMacros[$method] instanceof Closure && method_exists('Closure', 'bind')) {
+ return call_user_func_array(Closure::bind(static::$localMacros[$method], null, get_called_class()), $parameters);
+ }
+
+ return call_user_func_array(static::$localMacros[$method], $parameters);
+ }
+
+ /**
+ * Dynamically handle calls to the class.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @throws \BadMethodCallException|\ReflectionException
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ if (!static::hasMacro($method)) {
+ throw new \BadMethodCallException("Method $method does not exist.");
+ }
+
+ $macro = static::$localMacros[$method];
+
+ $reflexion = new \ReflectionFunction($macro);
+ $reflectionParameters = $reflexion->getParameters();
+ $expectedCount = count($reflectionParameters);
+ $actualCount = count($parameters);
+ if ($expectedCount > $actualCount && $reflectionParameters[$expectedCount - 1]->name === 'self') {
+ for ($i = $actualCount; $i < $expectedCount - 1; $i++) {
+ $parameters[] = $reflectionParameters[$i]->getDefaultValue();
+ }
+ $parameters[] = $this;
+ }
+
+ if ($macro instanceof Closure && method_exists($macro, 'bindTo')) {
+ return call_user_func_array($macro->bindTo($this, get_class($this)), $parameters);
+ }
+
+ return call_user_func_array($macro, $parameters);
+ }
+
+ /**
+ * Show truthy properties on var_dump().
+ *
+ * @return array
+ */
+ public function __debugInfo()
+ {
+ return array_filter(get_object_vars($this), function ($var) {
+ return $var;
+ });
+ }
+
+ /**
+ * Cast the current instance into the given class.
+ *
+ * @param string $className The $className::instance() method will be called to cast the current object.
+ *
+ * @return object
+ */
+ public function cast($className)
+ {
+ if (!method_exists($className, 'instance')) {
+ throw new \InvalidArgumentException("$className has not the instance() method needed to cast the date.");
+ }
+
+ return $className::instance($this);
+ }
+}
diff --git a/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php b/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php
new file mode 100644
index 000000000..e8c60325b
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php
@@ -0,0 +1,1163 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Carbon;
+
+use Closure;
+use DateInterval;
+use InvalidArgumentException;
+use ReflectionClass;
+use ReflectionFunction;
+use ReflectionMethod;
+use Symfony\Component\Translation\TranslatorInterface;
+
+/**
+ * A simple API extension for DateInterval.
+ * The implementation provides helpers to handle weeks but only days are saved.
+ * Weeks are calculated based on the total days of the current instance.
+ *
+ * @property int $years Total years of the current interval.
+ * @property int $months Total months of the current interval.
+ * @property int $weeks Total weeks of the current interval calculated from the days.
+ * @property int $dayz Total days of the current interval (weeks * 7 + days).
+ * @property int $hours Total hours of the current interval.
+ * @property int $minutes Total minutes of the current interval.
+ * @property int $seconds Total seconds of the current interval.
+ * @property-read int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7).
+ * @property-read int $daysExcludeWeeks alias of dayzExcludeWeeks
+ * @property-read float $totalYears Number of years equivalent to the interval.
+ * @property-read float $totalMonths Number of months equivalent to the interval.
+ * @property-read float $totalWeeks Number of weeks equivalent to the interval.
+ * @property-read float $totalDays Number of days equivalent to the interval.
+ * @property-read float $totalDayz Alias for totalDays.
+ * @property-read float $totalHours Number of hours equivalent to the interval.
+ * @property-read float $totalMinutes Number of minutes equivalent to the interval.
+ * @property-read float $totalSeconds Number of seconds equivalent to the interval.
+ *
+ * @method static CarbonInterval years($years = 1) Create instance specifying a number of years.
+ * @method static CarbonInterval year($years = 1) Alias for years()
+ * @method static CarbonInterval months($months = 1) Create instance specifying a number of months.
+ * @method static CarbonInterval month($months = 1) Alias for months()
+ * @method static CarbonInterval weeks($weeks = 1) Create instance specifying a number of weeks.
+ * @method static CarbonInterval week($weeks = 1) Alias for weeks()
+ * @method static CarbonInterval days($days = 1) Create instance specifying a number of days.
+ * @method static CarbonInterval dayz($days = 1) Alias for days()
+ * @method static CarbonInterval day($days = 1) Alias for days()
+ * @method static CarbonInterval hours($hours = 1) Create instance specifying a number of hours.
+ * @method static CarbonInterval hour($hours = 1) Alias for hours()
+ * @method static CarbonInterval minutes($minutes = 1) Create instance specifying a number of minutes.
+ * @method static CarbonInterval minute($minutes = 1) Alias for minutes()
+ * @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds.
+ * @method static CarbonInterval second($seconds = 1) Alias for seconds()
+ * @method CarbonInterval years($years = 1) Set the years portion of the current interval.
+ * @method CarbonInterval year($years = 1) Alias for years().
+ * @method CarbonInterval months($months = 1) Set the months portion of the current interval.
+ * @method CarbonInterval month($months = 1) Alias for months().
+ * @method CarbonInterval weeks($weeks = 1) Set the weeks portion of the current interval. Will overwrite dayz value.
+ * @method CarbonInterval week($weeks = 1) Alias for weeks().
+ * @method CarbonInterval days($days = 1) Set the days portion of the current interval.
+ * @method CarbonInterval dayz($days = 1) Alias for days().
+ * @method CarbonInterval day($days = 1) Alias for days().
+ * @method CarbonInterval hours($hours = 1) Set the hours portion of the current interval.
+ * @method CarbonInterval hour($hours = 1) Alias for hours().
+ * @method CarbonInterval minutes($minutes = 1) Set the minutes portion of the current interval.
+ * @method CarbonInterval minute($minutes = 1) Alias for minutes().
+ * @method CarbonInterval seconds($seconds = 1) Set the seconds portion of the current interval.
+ * @method CarbonInterval second($seconds = 1) Alias for seconds().
+ */
+class CarbonInterval extends DateInterval
+{
+ /**
+ * Interval spec period designators
+ */
+ const PERIOD_PREFIX = 'P';
+ const PERIOD_YEARS = 'Y';
+ const PERIOD_MONTHS = 'M';
+ const PERIOD_DAYS = 'D';
+ const PERIOD_TIME_PREFIX = 'T';
+ const PERIOD_HOURS = 'H';
+ const PERIOD_MINUTES = 'M';
+ const PERIOD_SECONDS = 'S';
+
+ /**
+ * A translator to ... er ... translate stuff
+ *
+ * @var \Symfony\Component\Translation\TranslatorInterface
+ */
+ protected static $translator;
+
+ /**
+ * @var array|null
+ */
+ protected static $cascadeFactors;
+
+ /**
+ * @var array|null
+ */
+ private static $flipCascadeFactors;
+
+ /**
+ * The registered macros.
+ *
+ * @var array
+ */
+ protected static $macros = array();
+
+ /**
+ * Before PHP 5.4.20/5.5.4 instead of FALSE days will be set to -99999 when the interval instance
+ * was created by DateTime::diff().
+ */
+ const PHP_DAYS_FALSE = -99999;
+
+ /**
+ * Mapping of units and factors for cascading.
+ *
+ * Should only be modified by changing the factors or referenced constants.
+ *
+ * @return array
+ */
+ public static function getCascadeFactors()
+ {
+ return static::$cascadeFactors ?: array(
+ 'minutes' => array(Carbon::SECONDS_PER_MINUTE, 'seconds'),
+ 'hours' => array(Carbon::MINUTES_PER_HOUR, 'minutes'),
+ 'dayz' => array(Carbon::HOURS_PER_DAY, 'hours'),
+ 'months' => array(Carbon::DAYS_PER_WEEK * Carbon::WEEKS_PER_MONTH, 'dayz'),
+ 'years' => array(Carbon::MONTHS_PER_YEAR, 'months'),
+ );
+ }
+
+ private static function standardizeUnit($unit)
+ {
+ $unit = rtrim($unit, 'sz').'s';
+
+ return $unit === 'days' ? 'dayz' : $unit;
+ }
+
+ private static function getFlipCascadeFactors()
+ {
+ if (!self::$flipCascadeFactors) {
+ self::$flipCascadeFactors = array();
+ foreach (static::getCascadeFactors() as $to => $tuple) {
+ list($factor, $from) = $tuple;
+
+ self::$flipCascadeFactors[self::standardizeUnit($from)] = array(self::standardizeUnit($to), $factor);
+ }
+ }
+
+ return self::$flipCascadeFactors;
+ }
+
+ /**
+ * @param array $cascadeFactors
+ */
+ public static function setCascadeFactors(array $cascadeFactors)
+ {
+ self::$flipCascadeFactors = null;
+ static::$cascadeFactors = $cascadeFactors;
+ }
+
+ /**
+ * Determine if the interval was created via DateTime:diff() or not.
+ *
+ * @param DateInterval $interval
+ *
+ * @return bool
+ */
+ private static function wasCreatedFromDiff(DateInterval $interval)
+ {
+ return $interval->days !== false && $interval->days !== static::PHP_DAYS_FALSE;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //////////////////////////// CONSTRUCTORS /////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Create a new CarbonInterval instance.
+ *
+ * @param int $years
+ * @param int $months
+ * @param int $weeks
+ * @param int $days
+ * @param int $hours
+ * @param int $minutes
+ * @param int $seconds
+ */
+ public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null)
+ {
+ $spec = $years;
+
+ if (!is_string($spec) || floatval($years) || preg_match('/^[0-9.]/', $years)) {
+ $spec = static::PERIOD_PREFIX;
+
+ $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
+ $spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
+
+ $specDays = 0;
+ $specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0;
+ $specDays += $days > 0 ? $days : 0;
+
+ $spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
+
+ if ($hours > 0 || $minutes > 0 || $seconds > 0) {
+ $spec .= static::PERIOD_TIME_PREFIX;
+ $spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
+ $spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
+ $spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
+ }
+
+ if ($spec === static::PERIOD_PREFIX) {
+ // Allow the zero interval.
+ $spec .= '0'.static::PERIOD_YEARS;
+ }
+ }
+
+ parent::__construct($spec);
+ }
+
+ /**
+ * Returns the factor for a given source-to-target couple.
+ *
+ * @param string $source
+ * @param string $target
+ *
+ * @return int|null
+ */
+ public static function getFactor($source, $target)
+ {
+ $source = self::standardizeUnit($source);
+ $target = self::standardizeUnit($target);
+ $factors = static::getFlipCascadeFactors();
+ if (isset($factors[$source])) {
+ list($to, $factor) = $factors[$source];
+ if ($to === $target) {
+ return $factor;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns current config for days per week.
+ *
+ * @return int
+ */
+ public static function getDaysPerWeek()
+ {
+ return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK;
+ }
+
+ /**
+ * Returns current config for hours per day.
+ *
+ * @return int
+ */
+ public static function getHoursPerDay()
+ {
+ return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY;
+ }
+
+ /**
+ * Returns current config for minutes per hour.
+ *
+ * @return int
+ */
+ public static function getMinutesPerHours()
+ {
+ return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR;
+ }
+
+ /**
+ * Returns current config for seconds per minute.
+ *
+ * @return int
+ */
+ public static function getSecondsPerMinutes()
+ {
+ return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE;
+ }
+
+ /**
+ * Create a new CarbonInterval instance from specific values.
+ * This is an alias for the constructor that allows better fluent
+ * syntax as it allows you to do CarbonInterval::create(1)->fn() rather than
+ * (new CarbonInterval(1))->fn().
+ *
+ * @param int $years
+ * @param int $months
+ * @param int $weeks
+ * @param int $days
+ * @param int $hours
+ * @param int $minutes
+ * @param int $seconds
+ *
+ * @return static
+ */
+ public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null)
+ {
+ return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds);
+ }
+
+ /**
+ * Get a copy of the instance.
+ *
+ * @return static
+ */
+ public function copy()
+ {
+ $date = new static($this->spec());
+ $date->invert = $this->invert;
+
+ return $date;
+ }
+
+ /**
+ * Provide static helpers to create instances. Allows CarbonInterval::years(3).
+ *
+ * Note: This is done using the magic method to allow static and instance methods to
+ * have the same names.
+ *
+ * @param string $name
+ * @param array $args
+ *
+ * @return static
+ */
+ public static function __callStatic($name, $args)
+ {
+ $arg = count($args) === 0 ? 1 : $args[0];
+
+ switch ($name) {
+ case 'years':
+ case 'year':
+ return new static($arg);
+
+ case 'months':
+ case 'month':
+ return new static(null, $arg);
+
+ case 'weeks':
+ case 'week':
+ return new static(null, null, $arg);
+
+ case 'days':
+ case 'dayz':
+ case 'day':
+ return new static(null, null, null, $arg);
+
+ case 'hours':
+ case 'hour':
+ return new static(null, null, null, null, $arg);
+
+ case 'minutes':
+ case 'minute':
+ return new static(null, null, null, null, null, $arg);
+
+ case 'seconds':
+ case 'second':
+ return new static(null, null, null, null, null, null, $arg);
+ }
+
+ if (static::hasMacro($name)) {
+ return call_user_func_array(
+ array(new static(0), $name), $args
+ );
+ }
+ }
+
+ /**
+ * Creates a CarbonInterval from string.
+ *
+ * Format:
+ *
+ * Suffix | Unit | Example | DateInterval expression
+ * -------|---------|---------|------------------------
+ * y | years | 1y | P1Y
+ * mo | months | 3mo | P3M
+ * w | weeks | 2w | P2W
+ * d | days | 28d | P28D
+ * h | hours | 4h | PT4H
+ * m | minutes | 12m | PT12M
+ * s | seconds | 59s | PT59S
+ *
+ * e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
+ *
+ * Special cases:
+ * - An empty string will return a zero interval
+ * - Fractions are allowed for weeks, days, hours and minutes and will be converted
+ * and rounded to the next smaller value (caution: 0.5w = 4d)
+ *
+ * @param string $intervalDefinition
+ *
+ * @return static
+ */
+ public static function fromString($intervalDefinition)
+ {
+ if (empty($intervalDefinition)) {
+ return new static(0);
+ }
+
+ $years = 0;
+ $months = 0;
+ $weeks = 0;
+ $days = 0;
+ $hours = 0;
+ $minutes = 0;
+ $seconds = 0;
+
+ $pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
+ preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
+ while ($match = array_shift($parts)) {
+ list($part, $value, $unit) = $match;
+ $intValue = intval($value);
+ $fraction = floatval($value) - $intValue;
+ switch (strtolower($unit)) {
+ case 'year':
+ case 'years':
+ case 'y':
+ $years += $intValue;
+ break;
+
+ case 'month':
+ case 'months':
+ case 'mo':
+ $months += $intValue;
+ break;
+
+ case 'week':
+ case 'weeks':
+ case 'w':
+ $weeks += $intValue;
+ if ($fraction) {
+ $parts[] = array(null, $fraction * static::getDaysPerWeek(), 'd');
+ }
+ break;
+
+ case 'day':
+ case 'days':
+ case 'd':
+ $days += $intValue;
+ if ($fraction) {
+ $parts[] = array(null, $fraction * static::getHoursPerDay(), 'h');
+ }
+ break;
+
+ case 'hour':
+ case 'hours':
+ case 'h':
+ $hours += $intValue;
+ if ($fraction) {
+ $parts[] = array(null, $fraction * static::getMinutesPerHours(), 'm');
+ }
+ break;
+
+ case 'minute':
+ case 'minutes':
+ case 'm':
+ $minutes += $intValue;
+ if ($fraction) {
+ $seconds += round($fraction * static::getSecondsPerMinutes());
+ }
+ break;
+
+ case 'second':
+ case 'seconds':
+ case 's':
+ $seconds += $intValue;
+ break;
+
+ default:
+ throw new InvalidArgumentException(
+ sprintf('Invalid part %s in definition %s', $part, $intervalDefinition)
+ );
+ }
+ }
+
+ return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds);
+ }
+
+ /**
+ * Create a CarbonInterval instance from a DateInterval one. Can not instance
+ * DateInterval objects created from DateTime::diff() as you can't externally
+ * set the $days field.
+ *
+ * Pass false as second argument to get a microseconds-precise interval. Else
+ * microseconds in the original interval will not be kept.
+ *
+ * @param DateInterval $di
+ * @param bool $trimMicroseconds (true by default)
+ *
+ * @return static
+ */
+ public static function instance(DateInterval $di, $trimMicroseconds = true)
+ {
+ $microseconds = $trimMicroseconds || version_compare(PHP_VERSION, '7.1.0-dev', '<') ? 0 : $di->f;
+ $instance = new static(static::getDateIntervalSpec($di));
+ if ($microseconds) {
+ $instance->f = $microseconds;
+ }
+ $instance->invert = $di->invert;
+ foreach (array('y', 'm', 'd', 'h', 'i', 's') as $unit) {
+ if ($di->$unit < 0) {
+ $instance->$unit *= -1;
+ }
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Make a CarbonInterval instance from given variable if possible.
+ *
+ * Always return a new instance. Parse only strings and only these likely to be intervals (skip dates
+ * and recurrences). Throw an exception for invalid format, but otherwise return null.
+ *
+ * @param mixed $var
+ *
+ * @return static|null
+ */
+ public static function make($var)
+ {
+ if ($var instanceof DateInterval) {
+ return static::instance($var);
+ }
+
+ if (is_string($var)) {
+ $var = trim($var);
+
+ if (substr($var, 0, 1) === 'P') {
+ return new static($var);
+ }
+
+ if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $var)) {
+ return static::fromString($var);
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ /////////////////////// LOCALIZATION //////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Initialize the translator instance if necessary.
+ *
+ * @return \Symfony\Component\Translation\TranslatorInterface
+ */
+ protected static function translator()
+ {
+ if (static::$translator === null) {
+ static::$translator = Translator::get();
+ }
+
+ return static::$translator;
+ }
+
+ /**
+ * Get the translator instance in use.
+ *
+ * @return \Symfony\Component\Translation\TranslatorInterface
+ */
+ public static function getTranslator()
+ {
+ return static::translator();
+ }
+
+ /**
+ * Set the translator instance to use.
+ *
+ * @param TranslatorInterface $translator
+ */
+ public static function setTranslator(TranslatorInterface $translator)
+ {
+ static::$translator = $translator;
+ }
+
+ /**
+ * Get the current translator locale.
+ *
+ * @return string
+ */
+ public static function getLocale()
+ {
+ return static::translator()->getLocale();
+ }
+
+ /**
+ * Set the current translator locale.
+ *
+ * @param string $locale
+ */
+ public static function setLocale($locale)
+ {
+ return static::translator()->setLocale($locale) !== false;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ ///////////////////////// GETTERS AND SETTERS /////////////////////
+ ///////////////////////////////////////////////////////////////////
+
+ /**
+ * Get a part of the CarbonInterval object.
+ *
+ * @param string $name
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return int|float
+ */
+ public function __get($name)
+ {
+ if (substr($name, 0, 5) === 'total') {
+ return $this->total(substr($name, 5));
+ }
+
+ switch ($name) {
+ case 'years':
+ return $this->y;
+
+ case 'months':
+ return $this->m;
+
+ case 'dayz':
+ return $this->d;
+
+ case 'hours':
+ return $this->h;
+
+ case 'minutes':
+ return $this->i;
+
+ case 'seconds':
+ return $this->s;
+
+ case 'weeks':
+ return (int) floor($this->d / static::getDaysPerWeek());
+
+ case 'daysExcludeWeeks':
+ case 'dayzExcludeWeeks':
+ return $this->d % static::getDaysPerWeek();
+
+ default:
+ throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
+ }
+ }
+
+ /**
+ * Set a part of the CarbonInterval object.
+ *
+ * @param string $name
+ * @param int $val
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function __set($name, $val)
+ {
+ switch ($name) {
+ case 'years':
+ $this->y = $val;
+ break;
+
+ case 'months':
+ $this->m = $val;
+ break;
+
+ case 'weeks':
+ $this->d = $val * static::getDaysPerWeek();
+ break;
+
+ case 'dayz':
+ $this->d = $val;
+ break;
+
+ case 'hours':
+ $this->h = $val;
+ break;
+
+ case 'minutes':
+ $this->i = $val;
+ break;
+
+ case 'seconds':
+ $this->s = $val;
+ break;
+ }
+ }
+
+ /**
+ * Allow setting of weeks and days to be cumulative.
+ *
+ * @param int $weeks Number of weeks to set
+ * @param int $days Number of days to set
+ *
+ * @return static
+ */
+ public function weeksAndDays($weeks, $days)
+ {
+ $this->dayz = ($weeks * static::getDaysPerWeek()) + $days;
+
+ return $this;
+ }
+
+ /**
+ * Register a custom macro.
+ *
+ * @param string $name
+ * @param object|callable $macro
+ *
+ * @return void
+ */
+ public static function macro($name, $macro)
+ {
+ static::$macros[$name] = $macro;
+ }
+
+ /**
+ * Remove all macros.
+ */
+ public static function resetMacros()
+ {
+ static::$macros = array();
+ }
+
+ /**
+ * Register macros from a mixin object.
+ *
+ * @param object $mixin
+ *
+ * @throws \ReflectionException
+ *
+ * @return void
+ */
+ public static function mixin($mixin)
+ {
+ $reflection = new ReflectionClass($mixin);
+
+ $methods = $reflection->getMethods(
+ ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
+ );
+
+ foreach ($methods as $method) {
+ $method->setAccessible(true);
+
+ static::macro($method->name, $method->invoke($mixin));
+ }
+ }
+
+ /**
+ * Check if macro is registered.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public static function hasMacro($name)
+ {
+ return isset(static::$macros[$name]);
+ }
+
+ /**
+ * Call given macro.
+ *
+ * @param string $name
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ protected function callMacro($name, $parameters)
+ {
+ $macro = static::$macros[$name];
+
+ $reflection = new ReflectionFunction($macro);
+
+ $reflectionParameters = $reflection->getParameters();
+
+ $expectedCount = count($reflectionParameters);
+ $actualCount = count($parameters);
+
+ if ($expectedCount > $actualCount && $reflectionParameters[$expectedCount - 1]->name === 'self') {
+ for ($i = $actualCount; $i < $expectedCount - 1; $i++) {
+ $parameters[] = $reflectionParameters[$i]->getDefaultValue();
+ }
+
+ $parameters[] = $this;
+ }
+
+ if ($macro instanceof Closure && method_exists($macro, 'bindTo')) {
+ $macro = $macro->bindTo($this, get_class($this));
+ }
+
+ return call_user_func_array($macro, $parameters);
+ }
+
+ /**
+ * Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day().
+ *
+ * Note: This is done using the magic method to allow static and instance methods to
+ * have the same names.
+ *
+ * @param string $name
+ * @param array $args
+ *
+ * @return static
+ */
+ public function __call($name, $args)
+ {
+ if (static::hasMacro($name)) {
+ return $this->callMacro($name, $args);
+ }
+
+ $arg = count($args) === 0 ? 1 : $args[0];
+
+ switch ($name) {
+ case 'years':
+ case 'year':
+ $this->years = $arg;
+ break;
+
+ case 'months':
+ case 'month':
+ $this->months = $arg;
+ break;
+
+ case 'weeks':
+ case 'week':
+ $this->dayz = $arg * static::getDaysPerWeek();
+ break;
+
+ case 'days':
+ case 'dayz':
+ case 'day':
+ $this->dayz = $arg;
+ break;
+
+ case 'hours':
+ case 'hour':
+ $this->hours = $arg;
+ break;
+
+ case 'minutes':
+ case 'minute':
+ $this->minutes = $arg;
+ break;
+
+ case 'seconds':
+ case 'second':
+ $this->seconds = $arg;
+ break;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get the current interval in a human readable format in the current locale.
+ *
+ * @param bool $short (false by default), returns short units if true
+ *
+ * @return string
+ */
+ public function forHumans($short = false)
+ {
+ $periods = array(
+ 'year' => array('y', $this->years),
+ 'month' => array('m', $this->months),
+ 'week' => array('w', $this->weeks),
+ 'day' => array('d', $this->daysExcludeWeeks),
+ 'hour' => array('h', $this->hours),
+ 'minute' => array('min', $this->minutes),
+ 'second' => array('s', $this->seconds),
+ );
+
+ $parts = array();
+ foreach ($periods as $unit => $options) {
+ list($shortUnit, $count) = $options;
+ if ($count > 0) {
+ $parts[] = static::translator()->transChoice($short ? $shortUnit : $unit, $count, array(':count' => $count));
+ }
+ }
+
+ return implode(' ', $parts);
+ }
+
+ /**
+ * Format the instance as a string using the forHumans() function.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->forHumans();
+ }
+
+ /**
+ * Convert the interval to a CarbonPeriod.
+ *
+ * @return CarbonPeriod
+ */
+ public function toPeriod()
+ {
+ return CarbonPeriod::createFromArray(
+ array_merge(array($this), func_get_args())
+ );
+ }
+
+ /**
+ * Invert the interval.
+ *
+ * @return $this
+ */
+ public function invert()
+ {
+ $this->invert = $this->invert ? 0 : 1;
+
+ return $this;
+ }
+
+ /**
+ * Add the passed interval to the current instance.
+ *
+ * @param DateInterval $interval
+ *
+ * @return static
+ */
+ public function add(DateInterval $interval)
+ {
+ $sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1;
+
+ if (static::wasCreatedFromDiff($interval)) {
+ $this->dayz += $interval->days * $sign;
+ } else {
+ $this->years += $interval->y * $sign;
+ $this->months += $interval->m * $sign;
+ $this->dayz += $interval->d * $sign;
+ $this->hours += $interval->h * $sign;
+ $this->minutes += $interval->i * $sign;
+ $this->seconds += $interval->s * $sign;
+ }
+
+ if (($this->years || $this->months || $this->dayz || $this->hours || $this->minutes || $this->seconds) &&
+ $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0
+ ) {
+ $this->years *= -1;
+ $this->months *= -1;
+ $this->dayz *= -1;
+ $this->hours *= -1;
+ $this->minutes *= -1;
+ $this->seconds *= -1;
+ $this->invert();
+ }
+
+ return $this;
+ }
+
+ /**
+ * Multiply current instance given number of times
+ *
+ * @param float $factor
+ *
+ * @return $this
+ */
+ public function times($factor)
+ {
+ if ($factor < 0) {
+ $this->invert = $this->invert ? 0 : 1;
+ $factor = -$factor;
+ }
+
+ $this->years = (int) round($this->years * $factor);
+ $this->months = (int) round($this->months * $factor);
+ $this->dayz = (int) round($this->dayz * $factor);
+ $this->hours = (int) round($this->hours * $factor);
+ $this->minutes = (int) round($this->minutes * $factor);
+ $this->seconds = (int) round($this->seconds * $factor);
+
+ return $this;
+ }
+
+ /**
+ * Get the interval_spec string of a date interval.
+ *
+ * @param DateInterval $interval
+ *
+ * @return string
+ */
+ public static function getDateIntervalSpec(DateInterval $interval)
+ {
+ $date = array_filter(array(
+ static::PERIOD_YEARS => abs($interval->y),
+ static::PERIOD_MONTHS => abs($interval->m),
+ static::PERIOD_DAYS => abs($interval->d),
+ ));
+
+ $time = array_filter(array(
+ static::PERIOD_HOURS => abs($interval->h),
+ static::PERIOD_MINUTES => abs($interval->i),
+ static::PERIOD_SECONDS => abs($interval->s),
+ ));
+
+ $specString = static::PERIOD_PREFIX;
+
+ foreach ($date as $key => $value) {
+ $specString .= $value.$key;
+ }
+
+ if (count($time) > 0) {
+ $specString .= static::PERIOD_TIME_PREFIX;
+ foreach ($time as $key => $value) {
+ $specString .= $value.$key;
+ }
+ }
+
+ return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
+ }
+
+ /**
+ * Get the interval_spec string.
+ *
+ * @return string
+ */
+ public function spec()
+ {
+ return static::getDateIntervalSpec($this);
+ }
+
+ /**
+ * Comparing 2 date intervals.
+ *
+ * @param DateInterval $a
+ * @param DateInterval $b
+ *
+ * @return int
+ */
+ public static function compareDateIntervals(DateInterval $a, DateInterval $b)
+ {
+ $current = Carbon::now();
+ $passed = $current->copy()->add($b);
+ $current->add($a);
+
+ if ($current < $passed) {
+ return -1;
+ }
+ if ($current > $passed) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Comparing with passed interval.
+ *
+ * @param DateInterval $interval
+ *
+ * @return int
+ */
+ public function compare(DateInterval $interval)
+ {
+ return static::compareDateIntervals($this, $interval);
+ }
+
+ /**
+ * Convert overflowed values into bigger units.
+ *
+ * @return $this
+ */
+ public function cascade()
+ {
+ foreach (static::getFlipCascadeFactors() as $source => $cascade) {
+ list($target, $factor) = $cascade;
+
+ if ($source === 'dayz' && $target === 'weeks') {
+ continue;
+ }
+
+ $value = $this->$source;
+ $this->$source = $modulo = $value % $factor;
+ $this->$target += ($value - $modulo) / $factor;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get amount of given unit equivalent to the interval.
+ *
+ * @param string $unit
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return float
+ */
+ public function total($unit)
+ {
+ $realUnit = $unit = strtolower($unit);
+
+ if (in_array($unit, array('days', 'weeks'))) {
+ $realUnit = 'dayz';
+ } elseif (!in_array($unit, array('seconds', 'minutes', 'hours', 'dayz', 'months', 'years'))) {
+ throw new InvalidArgumentException("Unknown unit '$unit'.");
+ }
+
+ $result = 0;
+ $cumulativeFactor = 0;
+ $unitFound = false;
+
+ foreach (static::getFlipCascadeFactors() as $source => $cascade) {
+ list($target, $factor) = $cascade;
+
+ if ($source === $realUnit) {
+ $unitFound = true;
+ $result += $this->$source;
+ $cumulativeFactor = 1;
+ }
+
+ if ($factor === false) {
+ if ($unitFound) {
+ break;
+ }
+
+ $result = 0;
+ $cumulativeFactor = 0;
+
+ continue;
+ }
+
+ if ($target === $realUnit) {
+ $unitFound = true;
+ }
+
+ if ($cumulativeFactor) {
+ $cumulativeFactor *= $factor;
+ $result += $this->$target * $cumulativeFactor;
+
+ continue;
+ }
+
+ $result = ($result + $this->$source) / $factor;
+ }
+
+ if (isset($target) && !$cumulativeFactor) {
+ $result += $this->$target;
+ }
+
+ if (!$unitFound) {
+ throw new \InvalidArgumentException("Unit $unit have no configuration to get total from other units.");
+ }
+
+ if ($unit === 'weeks') {
+ return $result / static::getDaysPerWeek();
+ }
+
+ return $result;
+ }
+}
diff --git a/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php b/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php
new file mode 100644
index 000000000..808e9d6ac
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php
@@ -0,0 +1,1453 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Carbon;
+
+use BadMethodCallException;
+use Closure;
+use Countable;
+use DateInterval;
+use DateTime;
+use DateTimeInterface;
+use InvalidArgumentException;
+use Iterator;
+use ReflectionClass;
+use ReflectionFunction;
+use ReflectionMethod;
+use RuntimeException;
+
+/**
+ * Substitution of DatePeriod with some modifications and many more features.
+ * Fully compatible with PHP 5.3+!
+ *
+ * @method static CarbonPeriod start($date, $inclusive = null) Create instance specifying start date.
+ * @method static CarbonPeriod since($date, $inclusive = null) Alias for start().
+ * @method static CarbonPeriod sinceNow($inclusive = null) Create instance with start date set to now.
+ * @method static CarbonPeriod end($date = null, $inclusive = null) Create instance specifying end date.
+ * @method static CarbonPeriod until($date = null, $inclusive = null) Alias for end().
+ * @method static CarbonPeriod untilNow($inclusive = null) Create instance with end date set to now.
+ * @method static CarbonPeriod dates($start, $end = null) Create instance with start and end date.
+ * @method static CarbonPeriod between($start, $end = null) Create instance with start and end date.
+ * @method static CarbonPeriod recurrences($recurrences = null) Create instance with maximum number of recurrences.
+ * @method static CarbonPeriod times($recurrences = null) Alias for recurrences().
+ * @method static CarbonPeriod options($options = null) Create instance with options.
+ * @method static CarbonPeriod toggle($options, $state = null) Create instance with options toggled on or off.
+ * @method static CarbonPeriod filter($callback, $name = null) Create instance with filter added to the stack.
+ * @method static CarbonPeriod push($callback, $name = null) Alias for filter().
+ * @method static CarbonPeriod prepend($callback, $name = null) Create instance with filter prepened to the stack.
+ * @method static CarbonPeriod filters(array $filters) Create instance with filters stack.
+ * @method static CarbonPeriod interval($interval) Create instance with given date interval.
+ * @method static CarbonPeriod each($interval) Create instance with given date interval.
+ * @method static CarbonPeriod every($interval) Create instance with given date interval.
+ * @method static CarbonPeriod step($interval) Create instance with given date interval.
+ * @method static CarbonPeriod stepBy($interval) Create instance with given date interval.
+ * @method static CarbonPeriod invert() Create instance with inverted date interval.
+ * @method static CarbonPeriod years($years = 1) Create instance specifying a number of years for date interval.
+ * @method static CarbonPeriod year($years = 1) Alias for years().
+ * @method static CarbonPeriod months($months = 1) Create instance specifying a number of months for date interval.
+ * @method static CarbonPeriod month($months = 1) Alias for months().
+ * @method static CarbonPeriod weeks($weeks = 1) Create instance specifying a number of weeks for date interval.
+ * @method static CarbonPeriod week($weeks = 1) Alias for weeks().
+ * @method static CarbonPeriod days($days = 1) Create instance specifying a number of days for date interval.
+ * @method static CarbonPeriod dayz($days = 1) Alias for days().
+ * @method static CarbonPeriod day($days = 1) Alias for days().
+ * @method static CarbonPeriod hours($hours = 1) Create instance specifying a number of hours for date interval.
+ * @method static CarbonPeriod hour($hours = 1) Alias for hours().
+ * @method static CarbonPeriod minutes($minutes = 1) Create instance specifying a number of minutes for date interval.
+ * @method static CarbonPeriod minute($minutes = 1) Alias for minutes().
+ * @method static CarbonPeriod seconds($seconds = 1) Create instance specifying a number of seconds for date interval.
+ * @method static CarbonPeriod second($seconds = 1) Alias for seconds().
+ * @method CarbonPeriod start($date, $inclusive = null) Change the period start date.
+ * @method CarbonPeriod since($date, $inclusive = null) Alias for start().
+ * @method CarbonPeriod sinceNow($inclusive = null) Change the period start date to now.
+ * @method CarbonPeriod end($date = null, $inclusive = null) Change the period end date.
+ * @method CarbonPeriod until($date = null, $inclusive = null) Alias for end().
+ * @method CarbonPeriod untilNow($inclusive = null) Change the period end date to now.
+ * @method CarbonPeriod dates($start, $end = null) Change the period start and end date.
+ * @method CarbonPeriod recurrences($recurrences = null) Change the maximum number of recurrences.
+ * @method CarbonPeriod times($recurrences = null) Alias for recurrences().
+ * @method CarbonPeriod options($options = null) Change the period options.
+ * @method CarbonPeriod toggle($options, $state = null) Toggle given options on or off.
+ * @method CarbonPeriod filter($callback, $name = null) Add a filter to the stack.
+ * @method CarbonPeriod push($callback, $name = null) Alias for filter().
+ * @method CarbonPeriod prepend($callback, $name = null) Prepend a filter to the stack.
+ * @method CarbonPeriod filters(array $filters = array()) Set filters stack.
+ * @method CarbonPeriod interval($interval) Change the period date interval.
+ * @method CarbonPeriod invert() Invert the period date interval.
+ * @method CarbonPeriod years($years = 1) Set the years portion of the date interval.
+ * @method CarbonPeriod year($years = 1) Alias for years().
+ * @method CarbonPeriod months($months = 1) Set the months portion of the date interval.
+ * @method CarbonPeriod month($months = 1) Alias for months().
+ * @method CarbonPeriod weeks($weeks = 1) Set the weeks portion of the date interval.
+ * @method CarbonPeriod week($weeks = 1) Alias for weeks().
+ * @method CarbonPeriod days($days = 1) Set the days portion of the date interval.
+ * @method CarbonPeriod dayz($days = 1) Alias for days().
+ * @method CarbonPeriod day($days = 1) Alias for days().
+ * @method CarbonPeriod hours($hours = 1) Set the hours portion of the date interval.
+ * @method CarbonPeriod hour($hours = 1) Alias for hours().
+ * @method CarbonPeriod minutes($minutes = 1) Set the minutes portion of the date interval.
+ * @method CarbonPeriod minute($minutes = 1) Alias for minutes().
+ * @method CarbonPeriod seconds($seconds = 1) Set the seconds portion of the date interval.
+ * @method CarbonPeriod second($seconds = 1) Alias for seconds().
+ */
+class CarbonPeriod implements Iterator, Countable
+{
+ /**
+ * Built-in filters.
+ *
+ * @var string
+ */
+ const RECURRENCES_FILTER = 'Carbon\CarbonPeriod::filterRecurrences';
+ const END_DATE_FILTER = 'Carbon\CarbonPeriod::filterEndDate';
+
+ /**
+ * Special value which can be returned by filters to end iteration. Also a filter.
+ *
+ * @var string
+ */
+ const END_ITERATION = 'Carbon\CarbonPeriod::endIteration';
+
+ /**
+ * Available options.
+ *
+ * @var int
+ */
+ const EXCLUDE_START_DATE = 1;
+ const EXCLUDE_END_DATE = 2;
+
+ /**
+ * Number of maximum attempts before giving up on finding next valid date.
+ *
+ * @var int
+ */
+ const NEXT_MAX_ATTEMPTS = 1000;
+
+ /**
+ * The registered macros.
+ *
+ * @var array
+ */
+ protected static $macros = array();
+
+ /**
+ * Underlying date interval instance. Always present, one day by default.
+ *
+ * @var CarbonInterval
+ */
+ protected $dateInterval;
+
+ /**
+ * Whether current date interval was set by default.
+ *
+ * @var bool
+ */
+ protected $isDefaultInterval;
+
+ /**
+ * The filters stack.
+ *
+ * @var array
+ */
+ protected $filters = array();
+
+ /**
+ * Period start date. Applied on rewind. Always present, now by default.
+ *
+ * @var Carbon
+ */
+ protected $startDate;
+
+ /**
+ * Period end date. For inverted interval should be before the start date. Applied via a filter.
+ *
+ * @var Carbon|null
+ */
+ protected $endDate;
+
+ /**
+ * Limit for number of recurrences. Applied via a filter.
+ *
+ * @var int|null
+ */
+ protected $recurrences;
+
+ /**
+ * Iteration options.
+ *
+ * @var int
+ */
+ protected $options;
+
+ /**
+ * Index of current date. Always sequential, even if some dates are skipped by filters.
+ * Equal to null only before the first iteration.
+ *
+ * @var int
+ */
+ protected $key;
+
+ /**
+ * Current date. May temporarily hold unaccepted value when looking for a next valid date.
+ * Equal to null only before the first iteration.
+ *
+ * @var Carbon
+ */
+ protected $current;
+
+ /**
+ * Timezone of current date. Taken from the start date.
+ *
+ * @var \DateTimeZone|null
+ */
+ protected $timezone;
+
+ /**
+ * The cached validation result for current date.
+ *
+ * @var bool|string|null
+ */
+ protected $validationResult;
+
+ /**
+ * Create a new instance.
+ *
+ * @return static
+ */
+ public static function create()
+ {
+ return static::createFromArray(func_get_args());
+ }
+
+ /**
+ * Create a new instance from an array of parameters.
+ *
+ * @param array $params
+ *
+ * @return static
+ */
+ public static function createFromArray(array $params)
+ {
+ // PHP 5.3 equivalent of new static(...$params).
+ $reflection = new ReflectionClass(get_class());
+ /** @var static $instance */
+ $instance = $reflection->newInstanceArgs($params);
+
+ return $instance;
+ }
+
+ /**
+ * Create CarbonPeriod from ISO 8601 string.
+ *
+ * @param string $iso
+ * @param int|null $options
+ *
+ * @return static
+ */
+ public static function createFromIso($iso, $options = null)
+ {
+ $params = static::parseIso8601($iso);
+
+ $instance = static::createFromArray($params);
+
+ if ($options !== null) {
+ $instance->setOptions($options);
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Return whether given interval contains non zero value of any time unit.
+ *
+ * @param \DateInterval $interval
+ *
+ * @return bool
+ */
+ protected static function intervalHasTime(DateInterval $interval)
+ {
+ // The array_key_exists and get_object_vars are used as a workaround to check microsecond support.
+ // Both isset and property_exists will fail on PHP 7.0.14 - 7.0.21 due to the following bug:
+ // https://bugs.php.net/bug.php?id=74852
+ return $interval->h || $interval->i || $interval->s || array_key_exists('f', get_object_vars($interval)) && $interval->f;
+ }
+
+ /**
+ * Return whether given callable is a string pointing to one of Carbon's is* methods
+ * and should be automatically converted to a filter callback.
+ *
+ * @param callable $callable
+ *
+ * @return bool
+ */
+ protected static function isCarbonPredicateMethod($callable)
+ {
+ return is_string($callable) && substr($callable, 0, 2) === 'is' && (method_exists('Carbon\Carbon', $callable) || Carbon::hasMacro($callable));
+ }
+
+ /**
+ * Return whether given variable is an ISO 8601 specification.
+ *
+ * Note: Check is very basic, as actual validation will be done later when parsing.
+ * We just want to ensure that variable is not any other type of a valid parameter.
+ *
+ * @param mixed $var
+ *
+ * @return bool
+ */
+ protected static function isIso8601($var)
+ {
+ if (!is_string($var)) {
+ return false;
+ }
+
+ // Match slash but not within a timezone name.
+ $part = '[a-z]+(?:[_-][a-z]+)*';
+
+ preg_match("#\b$part/$part\b|(/)#i", $var, $match);
+
+ return isset($match[1]);
+ }
+
+ /**
+ * Parse given ISO 8601 string into an array of arguments.
+ *
+ * @param string $iso
+ *
+ * @return array
+ */
+ protected static function parseIso8601($iso)
+ {
+ $result = array();
+
+ $interval = null;
+ $start = null;
+ $end = null;
+
+ foreach (explode('/', $iso) as $key => $part) {
+ if ($key === 0 && preg_match('/^R([0-9]*)$/', $part, $match)) {
+ $parsed = strlen($match[1]) ? (int) $match[1] : null;
+ } elseif ($interval === null && $parsed = CarbonInterval::make($part)) {
+ $interval = $part;
+ } elseif ($start === null && $parsed = Carbon::make($part)) {
+ $start = $part;
+ } elseif ($end === null && $parsed = Carbon::make(static::addMissingParts($start, $part))) {
+ $end = $part;
+ } else {
+ throw new InvalidArgumentException("Invalid ISO 8601 specification: $iso.");
+ }
+
+ $result[] = $parsed;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Add missing parts of the target date from the soure date.
+ *
+ * @param string $source
+ * @param string $target
+ *
+ * @return string
+ */
+ protected static function addMissingParts($source, $target)
+ {
+ $pattern = '/'.preg_replace('/[0-9]+/', '[0-9]+', preg_quote($target, '/')).'$/';
+
+ $result = preg_replace($pattern, $target, $source, 1, $count);
+
+ return $count ? $result : $target;
+ }
+
+ /**
+ * Register a custom macro.
+ *
+ * @param string $name
+ * @param object|callable $macro
+ *
+ * @return void
+ */
+ public static function macro($name, $macro)
+ {
+ static::$macros[$name] = $macro;
+ }
+
+ /**
+ * Remove all macros.
+ */
+ public static function resetMacros()
+ {
+ static::$macros = array();
+ }
+
+ /**
+ * Register macros from a mixin object.
+ *
+ * @param object $mixin
+ *
+ * @throws \ReflectionException
+ *
+ * @return void
+ */
+ public static function mixin($mixin)
+ {
+ $reflection = new ReflectionClass($mixin);
+
+ $methods = $reflection->getMethods(
+ ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
+ );
+
+ foreach ($methods as $method) {
+ $method->setAccessible(true);
+
+ static::macro($method->name, $method->invoke($mixin));
+ }
+ }
+
+ /**
+ * Check if macro is registered.
+ *
+ * @param string $name
+ *
+ * @return bool
+ */
+ public static function hasMacro($name)
+ {
+ return isset(static::$macros[$name]);
+ }
+
+ /**
+ * Provide static proxy for instance aliases.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public static function __callStatic($method, $parameters)
+ {
+ return call_user_func_array(
+ array(new static, $method), $parameters
+ );
+ }
+
+ /**
+ * CarbonPeriod constructor.
+ *
+ * @throws InvalidArgumentException
+ */
+ public function __construct()
+ {
+ // Parse and assign arguments one by one. First argument may be an ISO 8601 spec,
+ // which will be first parsed into parts and then processed the same way.
+ $arguments = func_get_args();
+
+ if (count($arguments) && static::isIso8601($iso = $arguments[0])) {
+ array_splice($arguments, 0, 1, static::parseIso8601($iso));
+ }
+
+ foreach ($arguments as $argument) {
+ if ($this->dateInterval === null && $parsed = CarbonInterval::make($argument)) {
+ $this->setDateInterval($parsed);
+ } elseif ($this->startDate === null && $parsed = Carbon::make($argument)) {
+ $this->setStartDate($parsed);
+ } elseif ($this->endDate === null && $parsed = Carbon::make($argument)) {
+ $this->setEndDate($parsed);
+ } elseif ($this->recurrences === null && $this->endDate === null && is_numeric($argument)) {
+ $this->setRecurrences($argument);
+ } elseif ($this->options === null && (is_int($argument) || $argument === null)) {
+ $this->setOptions($argument);
+ } else {
+ throw new InvalidArgumentException('Invalid constructor parameters.');
+ }
+ }
+
+ if ($this->startDate === null) {
+ $this->setStartDate(Carbon::now());
+ }
+
+ if ($this->dateInterval === null) {
+ $this->setDateInterval(CarbonInterval::day());
+
+ $this->isDefaultInterval = true;
+ }
+
+ if ($this->options === null) {
+ $this->setOptions(0);
+ }
+ }
+
+ /**
+ * Change the period date interval.
+ *
+ * @param DateInterval|string $interval
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function setDateInterval($interval)
+ {
+ if (!$interval = CarbonInterval::make($interval)) {
+ throw new InvalidArgumentException('Invalid interval.');
+ }
+
+ if ($interval->spec() === 'PT0S') {
+ throw new InvalidArgumentException('Empty interval is not accepted.');
+ }
+
+ $this->dateInterval = $interval;
+
+ $this->isDefaultInterval = false;
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Invert the period date interval.
+ *
+ * @return $this
+ */
+ public function invertDateInterval()
+ {
+ $interval = $this->dateInterval->invert();
+
+ return $this->setDateInterval($interval);
+ }
+
+ /**
+ * Set start and end date.
+ *
+ * @param DateTime|DateTimeInterface|string $start
+ * @param DateTime|DateTimeInterface|string|null $end
+ *
+ * @return $this
+ */
+ public function setDates($start, $end)
+ {
+ $this->setStartDate($start);
+ $this->setEndDate($end);
+
+ return $this;
+ }
+
+ /**
+ * Change the period options.
+ *
+ * @param int|null $options
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function setOptions($options)
+ {
+ if (!is_int($options) && !is_null($options)) {
+ throw new InvalidArgumentException('Invalid options.');
+ }
+
+ $this->options = $options ?: 0;
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Get the period options.
+ *
+ * @return int
+ */
+ public function getOptions()
+ {
+ return $this->options;
+ }
+
+ /**
+ * Toggle given options on or off.
+ *
+ * @param int $options
+ * @param bool|null $state
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function toggleOptions($options, $state = null)
+ {
+ if ($state === null) {
+ $state = ($this->options & $options) !== $options;
+ }
+
+ return $this->setOptions($state ?
+ $this->options | $options :
+ $this->options & ~$options
+ );
+ }
+
+ /**
+ * Toggle EXCLUDE_START_DATE option.
+ *
+ * @param bool $state
+ *
+ * @return $this
+ */
+ public function excludeStartDate($state = true)
+ {
+ return $this->toggleOptions(static::EXCLUDE_START_DATE, $state);
+ }
+
+ /**
+ * Toggle EXCLUDE_END_DATE option.
+ *
+ * @param bool $state
+ *
+ * @return $this
+ */
+ public function excludeEndDate($state = true)
+ {
+ return $this->toggleOptions(static::EXCLUDE_END_DATE, $state);
+ }
+
+ /**
+ * Get the underlying date interval.
+ *
+ * @return CarbonInterval
+ */
+ public function getDateInterval()
+ {
+ return $this->dateInterval->copy();
+ }
+
+ /**
+ * Get start date of the period.
+ *
+ * @return Carbon
+ */
+ public function getStartDate()
+ {
+ return $this->startDate->copy();
+ }
+
+ /**
+ * Get end date of the period.
+ *
+ * @return Carbon|null
+ */
+ public function getEndDate()
+ {
+ if ($this->endDate) {
+ return $this->endDate->copy();
+ }
+ }
+
+ /**
+ * Get number of recurrences.
+ *
+ * @return int|null
+ */
+ public function getRecurrences()
+ {
+ return $this->recurrences;
+ }
+
+ /**
+ * Returns true if the start date should be excluded.
+ *
+ * @return bool
+ */
+ public function isStartExcluded()
+ {
+ return ($this->options & static::EXCLUDE_START_DATE) !== 0;
+ }
+
+ /**
+ * Returns true if the end date should be excluded.
+ *
+ * @return bool
+ */
+ public function isEndExcluded()
+ {
+ return ($this->options & static::EXCLUDE_END_DATE) !== 0;
+ }
+
+ /**
+ * Add a filter to the stack.
+ *
+ * @param callable $callback
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function addFilter($callback, $name = null)
+ {
+ $tuple = $this->createFilterTuple(func_get_args());
+
+ $this->filters[] = $tuple;
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Prepend a filter to the stack.
+ *
+ * @param callable $callback
+ * @param string $name
+ *
+ * @return $this
+ */
+ public function prependFilter($callback, $name = null)
+ {
+ $tuple = $this->createFilterTuple(func_get_args());
+
+ array_unshift($this->filters, $tuple);
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Create a filter tuple from raw parameters.
+ *
+ * Will create an automatic filter callback for one of Carbon's is* methods.
+ *
+ * @param array $parameters
+ *
+ * @return array
+ */
+ protected function createFilterTuple(array $parameters)
+ {
+ $method = array_shift($parameters);
+
+ if (!$this->isCarbonPredicateMethod($method)) {
+ return array($method, array_shift($parameters));
+ }
+
+ return array(function ($date) use ($method, $parameters) {
+ return call_user_func_array(array($date, $method), $parameters);
+ }, $method);
+ }
+
+ /**
+ * Remove a filter by instance or name.
+ *
+ * @param callable|string $filter
+ *
+ * @return $this
+ */
+ public function removeFilter($filter)
+ {
+ $key = is_callable($filter) ? 0 : 1;
+
+ $this->filters = array_values(array_filter(
+ $this->filters,
+ function ($tuple) use ($key, $filter) {
+ return $tuple[$key] !== $filter;
+ }
+ ));
+
+ $this->updateInternalState();
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Return whether given instance or name is in the filter stack.
+ *
+ * @param callable|string $filter
+ *
+ * @return bool
+ */
+ public function hasFilter($filter)
+ {
+ $key = is_callable($filter) ? 0 : 1;
+
+ foreach ($this->filters as $tuple) {
+ if ($tuple[$key] === $filter) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get filters stack.
+ *
+ * @return array
+ */
+ public function getFilters()
+ {
+ return $this->filters;
+ }
+
+ /**
+ * Set filters stack.
+ *
+ * @param array $filters
+ *
+ * @return $this
+ */
+ public function setFilters(array $filters)
+ {
+ $this->filters = $filters;
+
+ $this->updateInternalState();
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Reset filters stack.
+ *
+ * @return $this
+ */
+ public function resetFilters()
+ {
+ $this->filters = array();
+
+ if ($this->endDate !== null) {
+ $this->filters[] = array(static::END_DATE_FILTER, null);
+ }
+
+ if ($this->recurrences !== null) {
+ $this->filters[] = array(static::RECURRENCES_FILTER, null);
+ }
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Update properties after removing built-in filters.
+ *
+ * @return void
+ */
+ protected function updateInternalState()
+ {
+ if (!$this->hasFilter(static::END_DATE_FILTER)) {
+ $this->endDate = null;
+ }
+
+ if (!$this->hasFilter(static::RECURRENCES_FILTER)) {
+ $this->recurrences = null;
+ }
+ }
+
+ /**
+ * Add a recurrences filter (set maximum number of recurrences).
+ *
+ * @param int|null $recurrences
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function setRecurrences($recurrences)
+ {
+ if (!is_numeric($recurrences) && !is_null($recurrences) || $recurrences < 0) {
+ throw new InvalidArgumentException('Invalid number of recurrences.');
+ }
+
+ if ($recurrences === null) {
+ return $this->removeFilter(static::RECURRENCES_FILTER);
+ }
+
+ $this->recurrences = (int) $recurrences;
+
+ if (!$this->hasFilter(static::RECURRENCES_FILTER)) {
+ return $this->addFilter(static::RECURRENCES_FILTER);
+ }
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * Recurrences filter callback (limits number of recurrences).
+ *
+ * @param \Carbon\Carbon $current
+ * @param int $key
+ *
+ * @return bool|string
+ */
+ protected function filterRecurrences($current, $key)
+ {
+ if ($key < $this->recurrences) {
+ return true;
+ }
+
+ return static::END_ITERATION;
+ }
+
+ /**
+ * Change the period start date.
+ *
+ * @param DateTime|DateTimeInterface|string $date
+ * @param bool|null $inclusive
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function setStartDate($date, $inclusive = null)
+ {
+ if (!$date = Carbon::make($date)) {
+ throw new InvalidArgumentException('Invalid start date.');
+ }
+
+ $this->startDate = $date;
+
+ if ($inclusive !== null) {
+ $this->toggleOptions(static::EXCLUDE_START_DATE, !$inclusive);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Change the period end date.
+ *
+ * @param DateTime|DateTimeInterface|string|null $date
+ * @param bool|null $inclusive
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return $this
+ */
+ public function setEndDate($date, $inclusive = null)
+ {
+ if (!is_null($date) && !$date = Carbon::make($date)) {
+ throw new InvalidArgumentException('Invalid end date.');
+ }
+
+ if (!$date) {
+ return $this->removeFilter(static::END_DATE_FILTER);
+ }
+
+ $this->endDate = $date;
+
+ if ($inclusive !== null) {
+ $this->toggleOptions(static::EXCLUDE_END_DATE, !$inclusive);
+ }
+
+ if (!$this->hasFilter(static::END_DATE_FILTER)) {
+ return $this->addFilter(static::END_DATE_FILTER);
+ }
+
+ $this->handleChangedParameters();
+
+ return $this;
+ }
+
+ /**
+ * End date filter callback.
+ *
+ * @param \Carbon\Carbon $current
+ *
+ * @return bool|string
+ */
+ protected function filterEndDate($current)
+ {
+ if (!$this->isEndExcluded() && $current == $this->endDate) {
+ return true;
+ }
+
+ if ($this->dateInterval->invert ? $current > $this->endDate : $current < $this->endDate) {
+ return true;
+ }
+
+ return static::END_ITERATION;
+ }
+
+ /**
+ * End iteration filter callback.
+ *
+ * @return string
+ */
+ protected function endIteration()
+ {
+ return static::END_ITERATION;
+ }
+
+ /**
+ * Handle change of the parameters.
+ */
+ protected function handleChangedParameters()
+ {
+ $this->validationResult = null;
+ }
+
+ /**
+ * Validate current date and stop iteration when necessary.
+ *
+ * Returns true when current date is valid, false if it is not, or static::END_ITERATION
+ * when iteration should be stopped.
+ *
+ * @return bool|string
+ */
+ protected function validateCurrentDate()
+ {
+ if ($this->current === null) {
+ $this->rewind();
+ }
+
+ // Check after the first rewind to avoid repeating the initial validation.
+ if ($this->validationResult !== null) {
+ return $this->validationResult;
+ }
+
+ return $this->validationResult = $this->checkFilters();
+ }
+
+ /**
+ * Check whether current value and key pass all the filters.
+ *
+ * @return bool|string
+ */
+ protected function checkFilters()
+ {
+ $current = $this->prepareForReturn($this->current);
+
+ foreach ($this->filters as $tuple) {
+ $result = call_user_func(
+ $tuple[0], $current->copy(), $this->key, $this
+ );
+
+ if ($result === static::END_ITERATION) {
+ return static::END_ITERATION;
+ }
+
+ if (!$result) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Prepare given date to be returned to the external logic.
+ *
+ * @param Carbon $date
+ *
+ * @return Carbon
+ */
+ protected function prepareForReturn(Carbon $date)
+ {
+ $date = $date->copy();
+
+ if ($this->timezone) {
+ $date->setTimezone($this->timezone);
+ }
+
+ return $date;
+ }
+
+ /**
+ * Check if the current position is valid.
+ *
+ * @return bool
+ */
+ public function valid()
+ {
+ return $this->validateCurrentDate() === true;
+ }
+
+ /**
+ * Return the current key.
+ *
+ * @return int|null
+ */
+ public function key()
+ {
+ if ($this->valid()) {
+ return $this->key;
+ }
+ }
+
+ /**
+ * Return the current date.
+ *
+ * @return Carbon|null
+ */
+ public function current()
+ {
+ if ($this->valid()) {
+ return $this->prepareForReturn($this->current);
+ }
+ }
+
+ /**
+ * Move forward to the next date.
+ *
+ * @throws \RuntimeException
+ *
+ * @return void
+ */
+ public function next()
+ {
+ if ($this->current === null) {
+ $this->rewind();
+ }
+
+ if ($this->validationResult !== static::END_ITERATION) {
+ $this->key++;
+
+ $this->incrementCurrentDateUntilValid();
+ }
+ }
+
+ /**
+ * Rewind to the start date.
+ *
+ * Iterating over a date in the UTC timezone avoids bug during backward DST change.
+ *
+ * @see https://bugs.php.net/bug.php?id=72255
+ * @see https://bugs.php.net/bug.php?id=74274
+ * @see https://wiki.php.net/rfc/datetime_and_daylight_saving_time
+ *
+ * @throws \RuntimeException
+ *
+ * @return void
+ */
+ public function rewind()
+ {
+ $this->key = 0;
+ $this->current = $this->startDate->copy();
+ $this->timezone = static::intervalHasTime($this->dateInterval) ? $this->current->getTimezone() : null;
+
+ if ($this->timezone) {
+ $this->current->setTimezone('UTC');
+ }
+
+ $this->validationResult = null;
+
+ if ($this->isStartExcluded() || $this->validateCurrentDate() === false) {
+ $this->incrementCurrentDateUntilValid();
+ }
+ }
+
+ /**
+ * Skip iterations and returns iteration state (false if ended, true if still valid).
+ *
+ * @param int $count steps number to skip (1 by default)
+ *
+ * @return bool
+ */
+ public function skip($count = 1)
+ {
+ for ($i = $count; $this->valid() && $i > 0; $i--) {
+ $this->next();
+ }
+
+ return $this->valid();
+ }
+
+ /**
+ * Keep incrementing the current date until a valid date is found or the iteration is ended.
+ *
+ * @throws \RuntimeException
+ *
+ * @return void
+ */
+ protected function incrementCurrentDateUntilValid()
+ {
+ $attempts = 0;
+
+ do {
+ $this->current->add($this->dateInterval);
+
+ $this->validationResult = null;
+
+ if (++$attempts > static::NEXT_MAX_ATTEMPTS) {
+ throw new RuntimeException('Could not find next valid date.');
+ }
+ } while ($this->validateCurrentDate() === false);
+ }
+
+ /**
+ * Format the date period as ISO 8601.
+ *
+ * @return string
+ */
+ public function toIso8601String()
+ {
+ $parts = array();
+
+ if ($this->recurrences !== null) {
+ $parts[] = 'R'.$this->recurrences;
+ }
+
+ $parts[] = $this->startDate->toIso8601String();
+
+ $parts[] = $this->dateInterval->spec();
+
+ if ($this->endDate !== null) {
+ $parts[] = $this->endDate->toIso8601String();
+ }
+
+ return implode('/', $parts);
+ }
+
+ /**
+ * Convert the date period into a string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ $translator = Carbon::getTranslator();
+
+ $parts = array();
+
+ $format = !$this->startDate->isStartOfDay() || $this->endDate && !$this->endDate->isStartOfDay()
+ ? 'Y-m-d H:i:s'
+ : 'Y-m-d';
+
+ if ($this->recurrences !== null) {
+ $parts[] = $translator->transChoice('period_recurrences', $this->recurrences, array(':count' => $this->recurrences));
+ }
+
+ $parts[] = $translator->trans('period_interval', array(':interval' => $this->dateInterval->forHumans()));
+
+ $parts[] = $translator->trans('period_start_date', array(':date' => $this->startDate->format($format)));
+
+ if ($this->endDate !== null) {
+ $parts[] = $translator->trans('period_end_date', array(':date' => $this->endDate->format($format)));
+ }
+
+ $result = implode(' ', $parts);
+
+ return mb_strtoupper(mb_substr($result, 0, 1)).mb_substr($result, 1);
+ }
+
+ /**
+ * Format the date period as ISO 8601.
+ *
+ * @return string
+ */
+ public function spec()
+ {
+ return $this->toIso8601String();
+ }
+
+ /**
+ * Convert the date period into an array without changing current iteration state.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $state = array(
+ $this->key,
+ $this->current ? $this->current->copy() : null,
+ $this->validationResult,
+ );
+
+ $result = iterator_to_array($this);
+
+ list(
+ $this->key,
+ $this->current,
+ $this->validationResult
+ ) = $state;
+
+ return $result;
+ }
+
+ /**
+ * Count dates in the date period.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->toArray());
+ }
+
+ /**
+ * Return the first date in the date period.
+ *
+ * @return Carbon|null
+ */
+ public function first()
+ {
+ if ($array = $this->toArray()) {
+ return $array[0];
+ }
+ }
+
+ /**
+ * Return the last date in the date period.
+ *
+ * @return Carbon|null
+ */
+ public function last()
+ {
+ if ($array = $this->toArray()) {
+ return $array[count($array) - 1];
+ }
+ }
+
+ /**
+ * Call given macro.
+ *
+ * @param string $name
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ protected function callMacro($name, $parameters)
+ {
+ $macro = static::$macros[$name];
+
+ $reflection = new ReflectionFunction($macro);
+
+ $reflectionParameters = $reflection->getParameters();
+
+ $expectedCount = count($reflectionParameters);
+ $actualCount = count($parameters);
+
+ if ($expectedCount > $actualCount && $reflectionParameters[$expectedCount - 1]->name === 'self') {
+ for ($i = $actualCount; $i < $expectedCount - 1; $i++) {
+ $parameters[] = $reflectionParameters[$i]->getDefaultValue();
+ }
+
+ $parameters[] = $this;
+ }
+
+ if ($macro instanceof Closure && method_exists($macro, 'bindTo')) {
+ $macro = $macro->bindTo($this, get_class($this));
+ }
+
+ return call_user_func_array($macro, $parameters);
+ }
+
+ /**
+ * Convert the date period into a string.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ /**
+ * Add aliases for setters.
+ *
+ * CarbonPeriod::days(3)->hours(5)->invert()
+ * ->sinceNow()->until('2010-01-10')
+ * ->filter(...)
+ * ->count()
+ *
+ * Note: We use magic method to let static and instance aliases with the same names.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, $parameters)
+ {
+ if (static::hasMacro($method)) {
+ return $this->callMacro($method, $parameters);
+ }
+
+ $first = count($parameters) >= 1 ? $parameters[0] : null;
+ $second = count($parameters) >= 2 ? $parameters[1] : null;
+
+ switch ($method) {
+ case 'start':
+ case 'since':
+ return $this->setStartDate($first, $second);
+
+ case 'sinceNow':
+ return $this->setStartDate(new Carbon, $first);
+
+ case 'end':
+ case 'until':
+ return $this->setEndDate($first, $second);
+
+ case 'untilNow':
+ return $this->setEndDate(new Carbon, $first);
+
+ case 'dates':
+ case 'between':
+ return $this->setDates($first, $second);
+
+ case 'recurrences':
+ case 'times':
+ return $this->setRecurrences($first);
+
+ case 'options':
+ return $this->setOptions($first);
+
+ case 'toggle':
+ return $this->toggleOptions($first, $second);
+
+ case 'filter':
+ case 'push':
+ return $this->addFilter($first, $second);
+
+ case 'prepend':
+ return $this->prependFilter($first, $second);
+
+ case 'filters':
+ return $this->setFilters($first ?: array());
+
+ case 'interval':
+ case 'each':
+ case 'every':
+ case 'step':
+ case 'stepBy':
+ return $this->setDateInterval($first);
+
+ case 'invert':
+ return $this->invertDateInterval();
+
+ case 'years':
+ case 'year':
+ case 'months':
+ case 'month':
+ case 'weeks':
+ case 'week':
+ case 'days':
+ case 'dayz':
+ case 'day':
+ case 'hours':
+ case 'hour':
+ case 'minutes':
+ case 'minute':
+ case 'seconds':
+ case 'second':
+ return $this->setDateInterval(call_user_func(
+ // Override default P1D when instantiating via fluent setters.
+ array($this->isDefaultInterval ? new CarbonInterval('PT0S') : $this->dateInterval, $method),
+ count($parameters) === 0 ? 1 : $first
+ ));
+ }
+
+ throw new BadMethodCallException("Method $method does not exist.");
+ }
+}
diff --git a/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php b/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php
new file mode 100644
index 000000000..1b0d47377
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php
@@ -0,0 +1,67 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Carbon\Exceptions;
+
+use Exception;
+use InvalidArgumentException;
+
+class InvalidDateException extends InvalidArgumentException
+{
+ /**
+ * The invalid field.
+ *
+ * @var string
+ */
+ private $field;
+
+ /**
+ * The invalid value.
+ *
+ * @var mixed
+ */
+ private $value;
+
+ /**
+ * Constructor.
+ *
+ * @param string $field
+ * @param mixed $value
+ * @param int $code
+ * @param \Exception|null $previous
+ */
+ public function __construct($field, $value, $code = 0, Exception $previous = null)
+ {
+ $this->field = $field;
+ $this->value = $value;
+ parent::__construct($field.' : '.$value.' is not a valid value.', $code, $previous);
+ }
+
+ /**
+ * Get the invalid field.
+ *
+ * @return string
+ */
+ public function getField()
+ {
+ return $this->field;
+ }
+
+ /**
+ * Get the invalid value.
+ *
+ * @return mixed
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+}
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/af.php b/vendor/nesbot/carbon/src/Carbon/Lang/af.php
new file mode 100644
index 000000000..5cf6a8d94
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/af.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count jaar|:count jare',
+ 'y' => ':count jaar|:count jare',
+ 'month' => ':count maand|:count maande',
+ 'm' => ':count maand|:count maande',
+ 'week' => ':count week|:count weke',
+ 'w' => ':count week|:count weke',
+ 'day' => ':count dag|:count dae',
+ 'd' => ':count dag|:count dae',
+ 'hour' => ':count uur|:count ure',
+ 'h' => ':count uur|:count ure',
+ 'minute' => ':count minuut|:count minute',
+ 'min' => ':count minuut|:count minute',
+ 'second' => ':count sekond|:count sekondes',
+ 's' => ':count sekond|:count sekondes',
+ 'ago' => ':time terug',
+ 'from_now' => ':time van nou af',
+ 'after' => ':time na',
+ 'before' => ':time voor',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ar.php b/vendor/nesbot/carbon/src/Carbon/Lang/ar.php
new file mode 100644
index 000000000..de8f6b85b
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ar.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '{0}سنة|{1}سنة|{2}سنتين|[3,10]:count سنوات|[11,Inf]:count سنة',
+ 'y' => '{0}سنة|{1}سنة|{2}سنتين|[3,10]:count سنوات|[11,Inf]:count سنة',
+ 'month' => '{0}شهر|{1} شهر|{2}شهرين|[3,10]:count أشهر|[11,Inf]:count شهر',
+ 'm' => '{0}شهر|{1} شهر|{2}شهرين|[3,10]:count أشهر|[11,Inf]:count شهر',
+ 'week' => '{0}أسبوع|{1}أسبوع|{2}أسبوعين|[3,10]:count أسابيع|[11,Inf]:count أسبوع',
+ 'w' => '{0}أسبوع|{1}أسبوع|{2}أسبوعين|[3,10]:count أسابيع|[11,Inf]:count أسبوع',
+ 'day' => '{0}يوم|{1}يوم|{2}يومين|[3,10]:count أيام|[11,Inf] يوم',
+ 'd' => '{0}يوم|{1}يوم|{2}يومين|[3,10]:count أيام|[11,Inf] يوم',
+ 'hour' => '{0}ساعة|{1}ساعة|{2}ساعتين|[3,10]:count ساعات|[11,Inf]:count ساعة',
+ 'h' => '{0}ساعة|{1}ساعة|{2}ساعتين|[3,10]:count ساعات|[11,Inf]:count ساعة',
+ 'minute' => '{0}دقيقة|{1}دقيقة|{2}دقيقتين|[3,10]:count دقائق|[11,Inf]:count دقيقة',
+ 'min' => '{0}دقيقة|{1}دقيقة|{2}دقيقتين|[3,10]:count دقائق|[11,Inf]:count دقيقة',
+ 'second' => '{0}ثانية|{1}ثانية|{2}ثانيتين|[3,10]:count ثوان|[11,Inf]:count ثانية',
+ 's' => '{0}ثانية|{1}ثانية|{2}ثانيتين|[3,10]:count ثوان|[11,Inf]:count ثانية',
+ 'ago' => 'منذ :time',
+ 'from_now' => ':time من الآن',
+ 'after' => 'بعد :time',
+ 'before' => 'قبل :time',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php b/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php
new file mode 100644
index 000000000..846ae0247
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '[0,1] سَنَة|{2} سَنَتَيْن|[3,10]:count سَنَوَات|[11,Inf]:count سَنَة',
+ 'y' => '[0,1] سَنَة|{2} سَنَتَيْن|[3,10]:count سَنَوَات|[11,Inf]:count سَنَة',
+ 'month' => '[0,1] شَهْرَ|{2} شَهْرَيْن|[3,10]:count Ø£ÙŽØ´Ù’Ù‡ÙØ±|[11,Inf]:count شَهْرَ',
+ 'm' => '[0,1] شَهْرَ|{2} شَهْرَيْن|[3,10]:count Ø£ÙŽØ´Ù’Ù‡ÙØ±|[11,Inf]:count شَهْرَ',
+ 'week' => '[0,1] Ø£ÙØ³Ù’بÙوع|{2} Ø£ÙØ³Ù’بÙوعَيْن|[3,10]:count أَسَابÙيع|[11,Inf]:count Ø£ÙØ³Ù’بÙوع',
+ 'w' => '[0,1] Ø£ÙØ³Ù’بÙوع|{2} Ø£ÙØ³Ù’بÙوعَيْن|[3,10]:count أَسَابÙيع|[11,Inf]:count Ø£ÙØ³Ù’بÙوع',
+ 'day' => '[0,1] يَوْم|{2} يَوْمَيْن|[3,10]:count أَيَّام|[11,Inf] يَوْم',
+ 'd' => '[0,1] يَوْم|{2} يَوْمَيْن|[3,10]:count أَيَّام|[11,Inf] يَوْم',
+ 'hour' => '[0,1] سَاعَة|{2} سَاعَتَيْن|[3,10]:count سَاعَات|[11,Inf]:count سَاعَة',
+ 'h' => '[0,1] سَاعَة|{2} سَاعَتَيْن|[3,10]:count سَاعَات|[11,Inf]:count سَاعَة',
+ 'minute' => '[0,1] دَقÙيقَة|{2} دَقÙيقَتَيْن|[3,10]:count دَقَائÙÙ‚|[11,Inf]:count دَقÙيقَة',
+ 'min' => '[0,1] دَقÙيقَة|{2} دَقÙيقَتَيْن|[3,10]:count دَقَائÙÙ‚|[11,Inf]:count دَقÙيقَة',
+ 'second' => '[0,1] ثَانÙÙŠÙŽØ©|{2} ثَانÙيَتَيْن|[3,10]:count ثَوَان|[11,Inf]:count ثَانÙÙŠÙŽØ©',
+ 's' => '[0,1] ثَانÙÙŠÙŽØ©|{2} ثَانÙيَتَيْن|[3,10]:count ثَوَان|[11,Inf]:count ثَانÙÙŠÙŽØ©',
+ 'ago' => 'Ù…Ùنْذ٠:time',
+ 'from_now' => 'Ù…ÙÙ†ÙŽ الْآن :time',
+ 'after' => 'بَعْدَ :time',
+ 'before' => 'قَبْلَ :time',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/az.php b/vendor/nesbot/carbon/src/Carbon/Lang/az.php
new file mode 100644
index 000000000..25f5c4a4d
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/az.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count il',
+ 'y' => ':count il',
+ 'month' => ':count ay',
+ 'm' => ':count ay',
+ 'week' => ':count həftə',
+ 'w' => ':count həftə',
+ 'day' => ':count gün',
+ 'd' => ':count gün',
+ 'hour' => ':count saat',
+ 'h' => ':count saat',
+ 'minute' => ':count dəqiqə',
+ 'min' => ':count dəqiqə',
+ 'second' => ':count saniyÉ™',
+ 's' => ':count saniyÉ™',
+ 'ago' => ':time əvvəl',
+ 'from_now' => ':time sonra',
+ 'after' => ':time sonra',
+ 'before' => ':time əvvəl',
+ 'diff_now' => 'indi',
+ 'diff_yesterday' => 'dünən',
+ 'diff_tomorrow' => 'sabah',
+ 'diff_before_yesterday' => 'srağagün',
+ 'diff_after_tomorrow' => 'birisi gün',
+ 'period_recurrences' => ':count dəfədən bir',
+ 'period_interval' => 'hər :interval',
+ 'period_start_date' => ':date tarixindən başlayaraq',
+ 'period_end_date' => ':date tarixinədək',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/bg.php b/vendor/nesbot/carbon/src/Carbon/Lang/bg.php
new file mode 100644
index 000000000..d9e510be8
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/bg.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count година|:count години',
+ 'y' => ':count година|:count години',
+ 'month' => ':count меÑец|:count меÑеца',
+ 'm' => ':count меÑец|:count меÑеца',
+ 'week' => ':count Ñедмица|:count Ñедмици',
+ 'w' => ':count Ñедмица|:count Ñедмици',
+ 'day' => ':count ден|:count дни',
+ 'd' => ':count ден|:count дни',
+ 'hour' => ':count чаÑ|:count чаÑа',
+ 'h' => ':count чаÑ|:count чаÑа',
+ 'minute' => ':count минута|:count минути',
+ 'min' => ':count минута|:count минути',
+ 'second' => ':count Ñекунда|:count Ñекунди',
+ 's' => ':count Ñекунда|:count Ñекунди',
+ 'ago' => 'преди :time',
+ 'from_now' => ':time от Ñега',
+ 'after' => 'Ñлед :time',
+ 'before' => 'преди :time',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/bn.php b/vendor/nesbot/carbon/src/Carbon/Lang/bn.php
new file mode 100644
index 000000000..5817599c6
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/bn.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '১ বছর|:count বছর',
+ 'y' => '১ বছর|:count বছর',
+ 'month' => '১ মাস|:count মাস',
+ 'm' => '১ মাস|:count মাস',
+ 'week' => 'à§§ সপà§à¦¤à¦¾à¦¹|:count সপà§à¦¤à¦¾à¦¹',
+ 'w' => 'à§§ সপà§à¦¤à¦¾à¦¹|:count সপà§à¦¤à¦¾à¦¹',
+ 'day' => '১ দিন|:count দিন',
+ 'd' => '১ দিন|:count দিন',
+ 'hour' => 'à§§ ঘনà§à¦Ÿà¦¾|:count ঘনà§à¦Ÿà¦¾',
+ 'h' => 'à§§ ঘনà§à¦Ÿà¦¾|:count ঘনà§à¦Ÿà¦¾',
+ 'minute' => '১ মিনিট|:count মিনিট',
+ 'min' => '১ মিনিট|:count মিনিট',
+ 'second' => 'à§§ সেকেনà§à¦¡|:count সেকেনà§à¦¡',
+ 's' => 'à§§ সেকেনà§à¦¡|:count সেকেনà§à¦¡',
+ 'ago' => ':time পূরà§à¦¬à§‡',
+ 'from_now' => 'à¦à¦–ন থেকে :time',
+ 'after' => ':time পরে',
+ 'before' => ':time আগে',
+ 'diff_now' => 'à¦à¦–ন',
+ 'diff_yesterday' => 'গতকাল',
+ 'diff_tomorrow' => 'আগামীকাল',
+ 'period_recurrences' => ':count বার|:count বার',
+ 'period_interval' => 'পà§à¦°à¦¤à¦¿ :interval',
+ 'period_start_date' => ':date থেকে',
+ 'period_end_date' => ':date পরà§à¦¯à¦¨à§à¦¤',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php b/vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php
new file mode 100644
index 000000000..7a9b05aa4
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/bs_BA.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count godina|:count godine|:count godina',
+ 'y' => ':count godina|:count godine|:count godina',
+ 'month' => ':count mjesec|:count mjeseca|:count mjeseci',
+ 'm' => ':count mjesec|:count mjeseca|:count mjeseci',
+ 'week' => ':count nedjelja|:count nedjelje|:count nedjelja',
+ 'w' => ':count nedjelja|:count nedjelje|:count nedjelja',
+ 'day' => ':count dan|:count dana|:count dana',
+ 'd' => ':count dan|:count dana|:count dana',
+ 'hour' => ':count sat|:count sata|:count sati',
+ 'h' => ':count sat|:count sata|:count sati',
+ 'minute' => ':count minut|:count minuta|:count minuta',
+ 'min' => ':count minut|:count minuta|:count minuta',
+ 'second' => ':count sekund|:count sekunda|:count sekundi',
+ 's' => ':count sekund|:count sekunda|:count sekundi',
+ 'ago' => 'prije :time',
+ 'from_now' => 'za :time',
+ 'after' => 'nakon :time',
+ 'before' => ':time ranije',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ca.php b/vendor/nesbot/carbon/src/Carbon/Lang/ca.php
new file mode 100644
index 000000000..c854b5a91
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ca.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count any|:count anys',
+ 'y' => ':count any|:count anys',
+ 'month' => ':count mes|:count mesos',
+ 'm' => ':count mes|:count mesos',
+ 'week' => ':count setmana|:count setmanes',
+ 'w' => ':count setmana|:count setmanes',
+ 'day' => ':count dia|:count dies',
+ 'd' => ':count dia|:count dies',
+ 'hour' => ':count hora|:count hores',
+ 'h' => ':count hora|:count hores',
+ 'minute' => ':count minut|:count minuts',
+ 'min' => ':count minut|:count minuts',
+ 'second' => ':count segon|:count segons',
+ 's' => ':count segon|:count segons',
+ 'ago' => 'fa :time',
+ 'from_now' => 'd\'aquà :time',
+ 'after' => ':time després',
+ 'before' => ':time abans',
+ 'diff_now' => 'ara mateix',
+ 'diff_yesterday' => 'ahir',
+ 'diff_tomorrow' => 'demà ',
+ 'diff_before_yesterday' => "abans d'ahir",
+ 'diff_after_tomorrow' => 'demà passat',
+ 'period_recurrences' => ':count cop|:count cops',
+ 'period_interval' => 'cada :interval',
+ 'period_start_date' => 'de :date',
+ 'period_end_date' => 'fins a :date',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/cs.php b/vendor/nesbot/carbon/src/Carbon/Lang/cs.php
new file mode 100644
index 000000000..a447ce298
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/cs.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count rok|:count roky|:count let',
+ 'y' => ':count rok|:count roky|:count let',
+ 'month' => ':count mÄ›sÃc|:count mÄ›sÃce|:count mÄ›sÃců',
+ 'm' => ':count mÄ›sÃc|:count mÄ›sÃce|:count mÄ›sÃců',
+ 'week' => ':count týden|:count týdny|:count týdnů',
+ 'w' => ':count týden|:count týdny|:count týdnů',
+ 'day' => ':count den|:count dny|:count dnÃ',
+ 'd' => ':count den|:count dny|:count dnÃ',
+ 'hour' => ':count hodinu|:count hodiny|:count hodin',
+ 'h' => ':count hodinu|:count hodiny|:count hodin',
+ 'minute' => ':count minutu|:count minuty|:count minut',
+ 'min' => ':count minutu|:count minuty|:count minut',
+ 'second' => ':count sekundu|:count sekundy|:count sekund',
+ 's' => ':count sekundu|:count sekundy|:count sekund',
+ 'ago' => ':time nazpět',
+ 'from_now' => 'za :time',
+ 'after' => ':time později',
+ 'before' => ':time pÅ™edtÃm',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/cy.php b/vendor/nesbot/carbon/src/Carbon/Lang/cy.php
new file mode 100644
index 000000000..c93750e25
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/cy.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array(
+ 'year' => '1 flwyddyn|:count blynedd',
+ 'y' => ':countbl',
+ 'month' => '1 mis|:count fis',
+ 'm' => ':countmi',
+ 'week' => ':count wythnos',
+ 'w' => ':countw',
+ 'day' => ':count diwrnod',
+ 'd' => ':countd',
+ 'hour' => ':count awr',
+ 'h' => ':counth',
+ 'minute' => ':count munud',
+ 'min' => ':countm',
+ 'second' => ':count eiliad',
+ 's' => ':counts',
+ 'ago' => ':time yn ôl',
+ 'from_now' => ':time o hyn ymlaen',
+ 'after' => ':time ar ôl',
+ 'before' => ':time o\'r blaen',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/da.php b/vendor/nesbot/carbon/src/Carbon/Lang/da.php
new file mode 100644
index 000000000..86507b0fe
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/da.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count år|:count år',
+ 'y' => ':count år|:count år',
+ 'month' => ':count måned|:count måneder',
+ 'm' => ':count måned|:count måneder',
+ 'week' => ':count uge|:count uger',
+ 'w' => ':count uge|:count uger',
+ 'day' => ':count dag|:count dage',
+ 'd' => ':count dag|:count dage',
+ 'hour' => ':count time|:count timer',
+ 'h' => ':count time|:count timer',
+ 'minute' => ':count minut|:count minutter',
+ 'min' => ':count minut|:count minutter',
+ 'second' => ':count sekund|:count sekunder',
+ 's' => ':count sekund|:count sekunder',
+ 'ago' => ':time siden',
+ 'from_now' => 'om :time',
+ 'after' => ':time efter',
+ 'before' => ':time før',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/de.php b/vendor/nesbot/carbon/src/Carbon/Lang/de.php
new file mode 100644
index 000000000..5ea2a03ad
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/de.php
@@ -0,0 +1,46 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count Jahr|:count Jahre',
+ 'y' => ':countJ|:countJ',
+ 'month' => ':count Monat|:count Monate',
+ 'm' => ':countMon|:countMon',
+ 'week' => ':count Woche|:count Wochen',
+ 'w' => ':countWo|:countWo',
+ 'day' => ':count Tag|:count Tage',
+ 'd' => ':countTg|:countTg',
+ 'hour' => ':count Stunde|:count Stunden',
+ 'h' => ':countStd|:countStd',
+ 'minute' => ':count Minute|:count Minuten',
+ 'min' => ':countMin|:countMin',
+ 'second' => ':count Sekunde|:count Sekunden',
+ 's' => ':countSek|:countSek',
+ 'ago' => 'vor :time',
+ 'from_now' => 'in :time',
+ 'after' => ':time später',
+ 'before' => ':time zuvor',
+
+ 'year_from_now' => ':count Jahr|:count Jahren',
+ 'month_from_now' => ':count Monat|:count Monaten',
+ 'week_from_now' => ':count Woche|:count Wochen',
+ 'day_from_now' => ':count Tag|:count Tagen',
+ 'year_ago' => ':count Jahr|:count Jahren',
+ 'month_ago' => ':count Monat|:count Monaten',
+ 'week_ago' => ':count Woche|:count Wochen',
+ 'day_ago' => ':count Tag|:count Tagen',
+
+ 'diff_now' => 'Gerade eben',
+ 'diff_yesterday' => 'Gestern',
+ 'diff_tomorrow' => 'Heute',
+ 'diff_before_yesterday' => 'Vorgestern',
+ 'diff_after_tomorrow' => 'Übermorgen',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php b/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php
new file mode 100644
index 000000000..e3c50b396
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '{0}Þ‡Þ¦Þ€Þ¦ÞƒÞ¬Þ‡Þ°|[1,Inf]:count Þ‡Þ¦Þ€Þ¦ÞƒÞª',
+ 'y' => '{0}Þ‡Þ¦Þ€Þ¦ÞƒÞ¬Þ‡Þ°|[1,Inf]:count Þ‡Þ¦Þ€Þ¦ÞƒÞª',
+ 'month' => '{0}Þ‰Þ¦Þ‡Þ°ÞÞ¦ÞƒÞ¬Þ‡Þ°|[1,Inf]:count Þ‰Þ¦ÞÞ°',
+ 'm' => '{0}Þ‰Þ¦Þ‡Þ°ÞÞ¦ÞƒÞ¬Þ‡Þ°|[1,Inf]:count Þ‰Þ¦ÞÞ°',
+ 'week' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
+ 'w' => '{0}ހަފްތާއެއް|[1,Inf]:count ހަފްތާ',
+ 'day' => '{0}Þ‹ÞªÞˆÞ¦ÞÞ°|[1,Inf]:count Þ‹ÞªÞˆÞ¦ÞÞ°',
+ 'd' => '{0}Þ‹ÞªÞˆÞ¦ÞÞ°|[1,Inf]:count Þ‹ÞªÞˆÞ¦ÞÞ°',
+ 'hour' => '{0}ÞŽÞ¦Þ‘Þ¨Þ‡Þ¨ÞƒÞ¬Þ‡Þ°|[1,Inf]:count ÞŽÞ¦Þ‘Þ¨',
+ 'h' => '{0}ÞŽÞ¦Þ‘Þ¨Þ‡Þ¨ÞƒÞ¬Þ‡Þ°|[1,Inf]:count ÞŽÞ¦Þ‘Þ¨',
+ 'minute' => '{0}Þ‰Þ¨Þ‚Þ¬Þ“Þ¬Þ‡Þ°|[1,Inf]:count Þ‰Þ¨Þ‚Þ¬Þ“Þ°',
+ 'min' => '{0}Þ‰Þ¨Þ‚Þ¬Þ“Þ¬Þ‡Þ°|[1,Inf]:count Þ‰Þ¨Þ‚Þ¬Þ“Þ°',
+ 'second' => '{0}Þިކުންތެއް|[1,Inf]:count Þިކުންތު',
+ 's' => '{0}Þިކުންތެއް|[1,Inf]:count Þިކުންތު',
+ 'ago' => ':time Þ†ÞªÞƒÞ¨Þ‚Þ°',
+ 'from_now' => ':time ÞŠÞ¦Þ€ÞªÞ‚Þ°',
+ 'after' => ':time ÞŠÞ¦Þ€ÞªÞ‚Þ°',
+ 'before' => ':time Þ†ÞªÞƒÞ¨',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/el.php b/vendor/nesbot/carbon/src/Carbon/Lang/el.php
new file mode 100644
index 000000000..16b3f4427
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/el.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count χÏόνος|:count χÏόνια',
+ 'y' => ':count χÏόνος|:count χÏόνια',
+ 'month' => ':count μήνας|:count μήνες',
+ 'm' => ':count μήνας|:count μήνες',
+ 'week' => ':count εβδομάδα|:count εβδομάδες',
+ 'w' => ':count εβδομάδα|:count εβδομάδες',
+ 'day' => ':count μÎÏα|:count μÎÏες',
+ 'd' => ':count μÎÏα|:count μÎÏες',
+ 'hour' => ':count ÏŽÏα|:count ÏŽÏες',
+ 'h' => ':count ÏŽÏα|:count ÏŽÏες',
+ 'minute' => ':count λεπτό|:count λεπτά',
+ 'min' => ':count λεπτό|:count λεπτά',
+ 'second' => ':count δευτεÏόλεπτο|:count δευτεÏόλεπτα',
+ 's' => ':count δευτεÏόλεπτο|:count δευτεÏόλεπτα',
+ 'ago' => 'Ï€Ïιν από :time',
+ 'from_now' => 'σε :time από τώÏα',
+ 'after' => ':time μετά',
+ 'before' => ':time Ï€Ïιν',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/en.php b/vendor/nesbot/carbon/src/Carbon/Lang/en.php
new file mode 100644
index 000000000..a15c131fb
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/en.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count year|:count years',
+ 'y' => ':countyr|:countyrs',
+ 'month' => ':count month|:count months',
+ 'm' => ':countmo|:countmos',
+ 'week' => ':count week|:count weeks',
+ 'w' => ':countw|:countw',
+ 'day' => ':count day|:count days',
+ 'd' => ':countd|:countd',
+ 'hour' => ':count hour|:count hours',
+ 'h' => ':counth|:counth',
+ 'minute' => ':count minute|:count minutes',
+ 'min' => ':countm|:countm',
+ 'second' => ':count second|:count seconds',
+ 's' => ':counts|:counts',
+ 'ago' => ':time ago',
+ 'from_now' => ':time from now',
+ 'after' => ':time after',
+ 'before' => ':time before',
+ 'diff_now' => 'just now',
+ 'diff_yesterday' => 'yesterday',
+ 'diff_tomorrow' => 'tomorrow',
+ 'diff_before_yesterday' => 'before yesterday',
+ 'diff_after_tomorrow' => 'after tomorrow',
+ 'period_recurrences' => 'once|:count times',
+ 'period_interval' => 'every :interval',
+ 'period_start_date' => 'from :date',
+ 'period_end_date' => 'to :date',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/eo.php b/vendor/nesbot/carbon/src/Carbon/Lang/eo.php
new file mode 100644
index 000000000..c5b90b3e7
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/eo.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count jaro|:count jaroj',
+ 'y' => ':count jaro|:count jaroj',
+ 'month' => ':count monato|:count monatoj',
+ 'm' => ':count monato|:count monatoj',
+ 'week' => ':count semajno|:count semajnoj',
+ 'w' => ':count semajno|:count semajnoj',
+ 'day' => ':count tago|:count tagoj',
+ 'd' => ':count tago|:count tagoj',
+ 'hour' => ':count horo|:count horoj',
+ 'h' => ':count horo|:count horoj',
+ 'minute' => ':count minuto|:count minutoj',
+ 'min' => ':count minuto|:count minutoj',
+ 'second' => ':count sekundo|:count sekundoj',
+ 's' => ':count sekundo|:count sekundoj',
+ 'ago' => 'antaÅ :time',
+ 'from_now' => 'je :time',
+ 'after' => ':time poste',
+ 'before' => ':time antaÅe',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/es.php b/vendor/nesbot/carbon/src/Carbon/Lang/es.php
new file mode 100644
index 000000000..567a280f3
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/es.php
@@ -0,0 +1,36 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count año|:count años',
+ 'y' => ':count año|:count años',
+ 'month' => ':count mes|:count meses',
+ 'm' => ':count mes|:count meses',
+ 'week' => ':count semana|:count semanas',
+ 'w' => ':count semana|:count semanas',
+ 'day' => ':count dÃa|:count dÃas',
+ 'd' => ':count dÃa|:count dÃas',
+ 'hour' => ':count hora|:count horas',
+ 'h' => ':count hora|:count horas',
+ 'minute' => ':count minuto|:count minutos',
+ 'min' => ':count minuto|:count minutos',
+ 'second' => ':count segundo|:count segundos',
+ 's' => ':count segundo|:count segundos',
+ 'ago' => 'hace :time',
+ 'from_now' => 'dentro de :time',
+ 'after' => ':time después',
+ 'before' => ':time antes',
+ 'diff_now' => 'ahora mismo',
+ 'diff_yesterday' => 'ayer',
+ 'diff_tomorrow' => 'mañana',
+ 'diff_before_yesterday' => 'antier',
+ 'diff_after_tomorrow' => 'pasado mañana',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/et.php b/vendor/nesbot/carbon/src/Carbon/Lang/et.php
new file mode 100644
index 000000000..2d9291e04
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/et.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count aasta|:count aastat',
+ 'y' => ':count aasta|:count aastat',
+ 'month' => ':count kuu|:count kuud',
+ 'm' => ':count kuu|:count kuud',
+ 'week' => ':count nädal|:count nädalat',
+ 'w' => ':count nädal|:count nädalat',
+ 'day' => ':count päev|:count päeva',
+ 'd' => ':count päev|:count päeva',
+ 'hour' => ':count tund|:count tundi',
+ 'h' => ':count tund|:count tundi',
+ 'minute' => ':count minut|:count minutit',
+ 'min' => ':count minut|:count minutit',
+ 'second' => ':count sekund|:count sekundit',
+ 's' => ':count sekund|:count sekundit',
+ 'ago' => ':time tagasi',
+ 'from_now' => ':time pärast',
+ 'after' => ':time pärast',
+ 'before' => ':time enne',
+ 'year_from_now' => ':count aasta',
+ 'month_from_now' => ':count kuu',
+ 'week_from_now' => ':count nädala',
+ 'day_from_now' => ':count päeva',
+ 'hour_from_now' => ':count tunni',
+ 'minute_from_now' => ':count minuti',
+ 'second_from_now' => ':count sekundi',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/eu.php b/vendor/nesbot/carbon/src/Carbon/Lang/eu.php
new file mode 100644
index 000000000..1cb6b7cd6
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/eu.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => 'Urte 1|:count urte',
+ 'y' => 'Urte 1|:count urte',
+ 'month' => 'Hile 1|:count hile',
+ 'm' => 'Hile 1|:count hile',
+ 'week' => 'Aste 1|:count aste',
+ 'w' => 'Aste 1|:count aste',
+ 'day' => 'Egun 1|:count egun',
+ 'd' => 'Egun 1|:count egun',
+ 'hour' => 'Ordu 1|:count ordu',
+ 'h' => 'Ordu 1|:count ordu',
+ 'minute' => 'Minutu 1|:count minutu',
+ 'min' => 'Minutu 1|:count minutu',
+ 'second' => 'Segundu 1|:count segundu',
+ 's' => 'Segundu 1|:count segundu',
+ 'ago' => 'Orain dela :time',
+ 'from_now' => ':time barru',
+ 'after' => ':time geroago',
+ 'before' => ':time lehenago',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/fa.php b/vendor/nesbot/carbon/src/Carbon/Lang/fa.php
new file mode 100644
index 000000000..31bec8869
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/fa.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count سال',
+ 'y' => ':count سال',
+ 'month' => ':count ماه',
+ 'm' => ':count ماه',
+ 'week' => ':count Ù‡ÙØªÙ‡',
+ 'w' => ':count Ù‡ÙØªÙ‡',
+ 'day' => ':count روز',
+ 'd' => ':count روز',
+ 'hour' => ':count ساعت',
+ 'h' => ':count ساعت',
+ 'minute' => ':count دقیقه',
+ 'min' => ':count دقیقه',
+ 'second' => ':count ثانیه',
+ 's' => ':count ثانیه',
+ 'ago' => ':time پیش',
+ 'from_now' => ':time بعد',
+ 'after' => ':time پس از',
+ 'before' => ':time پیش از',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/fi.php b/vendor/nesbot/carbon/src/Carbon/Lang/fi.php
new file mode 100644
index 000000000..481880444
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/fi.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count vuosi|:count vuotta',
+ 'y' => ':count vuosi|:count vuotta',
+ 'month' => ':count kuukausi|:count kuukautta',
+ 'm' => ':count kuukausi|:count kuukautta',
+ 'week' => ':count viikko|:count viikkoa',
+ 'w' => ':count viikko|:count viikkoa',
+ 'day' => ':count päivä|:count päivää',
+ 'd' => ':count päivä|:count päivää',
+ 'hour' => ':count tunti|:count tuntia',
+ 'h' => ':count tunti|:count tuntia',
+ 'minute' => ':count minuutti|:count minuuttia',
+ 'min' => ':count minuutti|:count minuuttia',
+ 'second' => ':count sekunti|:count sekuntia',
+ 's' => ':count sekunti|:count sekuntia',
+ 'ago' => ':time sitten',
+ 'from_now' => ':time tästä hetkestä',
+ 'after' => ':time sen jälkeen',
+ 'before' => ':time ennen',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/fo.php b/vendor/nesbot/carbon/src/Carbon/Lang/fo.php
new file mode 100644
index 000000000..d91104b78
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/fo.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count ár|:count ár',
+ 'y' => ':count ár|:count ár',
+ 'month' => ':count mánaður|:count mánaðir',
+ 'm' => ':count mánaður|:count mánaðir',
+ 'week' => ':count vika|:count vikur',
+ 'w' => ':count vika|:count vikur',
+ 'day' => ':count dag|:count dagar',
+ 'd' => ':count dag|:count dagar',
+ 'hour' => ':count tÃmi|:count tÃmar',
+ 'h' => ':count tÃmi|:count tÃmar',
+ 'minute' => ':count minutt|:count minuttir',
+ 'min' => ':count minutt|:count minuttir',
+ 'second' => ':count sekund|:count sekundir',
+ 's' => ':count sekund|:count sekundir',
+ 'ago' => ':time sÃðan',
+ 'from_now' => 'um :time',
+ 'after' => ':time aftaná',
+ 'before' => ':time áðrenn',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/fr.php b/vendor/nesbot/carbon/src/Carbon/Lang/fr.php
new file mode 100644
index 000000000..0b20cdd29
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/fr.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count an|:count ans',
+ 'y' => ':count an|:count ans',
+ 'month' => ':count mois',
+ 'm' => ':count mois',
+ 'week' => ':count semaine|:count semaines',
+ 'w' => ':count sem.',
+ 'day' => ':count jour|:count jours',
+ 'd' => ':count j.',
+ 'hour' => ':count heure|:count heures',
+ 'h' => ':count h.',
+ 'minute' => ':count minute|:count minutes',
+ 'min' => ':count min.',
+ 'second' => ':count seconde|:count secondes',
+ 's' => ':count sec.',
+ 'ago' => 'il y a :time',
+ 'from_now' => 'dans :time',
+ 'after' => ':time après',
+ 'before' => ':time avant',
+ 'diff_now' => "Ã l'instant",
+ 'diff_yesterday' => 'hier',
+ 'diff_tomorrow' => 'demain',
+ 'diff_before_yesterday' => 'avant-hier',
+ 'diff_after_tomorrow' => 'après-demain',
+ 'period_recurrences' => ':count fois',
+ 'period_interval' => 'tous les :interval',
+ 'period_start_date' => 'de :date',
+ 'period_end_date' => 'Ã :date',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/gl.php b/vendor/nesbot/carbon/src/Carbon/Lang/gl.php
new file mode 100644
index 000000000..cd22a31e7
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/gl.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count ano|:count anos',
+ 'month' => ':count mes|:count meses',
+ 'week' => ':count semana|:count semanas',
+ 'day' => ':count dÃa|:count dÃas',
+ 'hour' => ':count hora|:count horas',
+ 'minute' => ':count minuto|:count minutos',
+ 'second' => ':count segundo|:count segundos',
+ 'ago' => 'fai :time',
+ 'from_now' => 'dentro de :time',
+ 'after' => ':time despois',
+ 'before' => ':time antes',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/gu.php b/vendor/nesbot/carbon/src/Carbon/Lang/gu.php
new file mode 100644
index 000000000..7759dfcb5
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/gu.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count વરà«àª·|:count વરà«àª·à«‹',
+ 'y' => ':countવરà«àª·|:countવરà«àª·à«‹',
+ 'month' => ':count મહિનો|:count મહિના',
+ 'm' => ':countમહિનો|:countમહિના',
+ 'week' => ':count અઠવાડિયà«àª‚|:count અઠવાડિયા',
+ 'w' => ':countઅઠ.|:countઅઠ.',
+ 'day' => ':count દિવસ|:count દિવસો',
+ 'd' => ':countદિ.|:countદિ.',
+ 'hour' => ':count કલાક|:count કલાકો',
+ 'h' => ':countક.|:countક.',
+ 'minute' => ':count મિનિટ|:count મિનિટ',
+ 'min' => ':countમિ.|:countમિ.',
+ 'second' => ':count સેકેનà«àª¡|:count સેકેનà«àª¡',
+ 's' => ':countસે.|:countસે.',
+ 'ago' => ':time પહેલા',
+ 'from_now' => ':time અતà«àª¯àª¾àª°àª¥à«€',
+ 'after' => ':time પછી',
+ 'before' => ':time પહેલા',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/he.php b/vendor/nesbot/carbon/src/Carbon/Lang/he.php
new file mode 100644
index 000000000..2d4f4f880
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/he.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '×©× ×”|{2}×©× ×ª×™×™×|:count ×©× ×™×',
+ 'y' => '×©× ×”|{2}×©× ×ª×™×™×|:count ×©× ×™×',
+ 'month' => 'חודש|{2}חודשיי×|:count חודשי×',
+ 'm' => 'חודש|{2}חודשיי×|:count חודשי×',
+ 'week' => 'שבוע|{2}שבועיי×|:count שבועות',
+ 'w' => 'שבוע|{2}שבועיי×|:count שבועות',
+ 'day' => 'יו×|{2}יומיי×|:count ימי×',
+ 'd' => 'יו×|{2}יומיי×|:count ימי×',
+ 'hour' => 'שעה|{2}שעתיי×|:count שעות',
+ 'h' => 'שעה|{2}שעתיי×|:count שעות',
+ 'minute' => 'דקה|{2}דקותיי×|:count דקות',
+ 'min' => 'דקה|{2}דקותיי×|:count דקות',
+ 'second' => '×©× ×™×”|:count ×©× ×™×•×ª',
+ 's' => '×©× ×™×”|:count ×©× ×™×•×ª',
+ 'ago' => '×œ×¤× ×™ :time',
+ 'from_now' => 'בעוד :time',
+ 'after' => '×חרי :time',
+ 'before' => '×œ×¤× ×™ :time',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/hi.php b/vendor/nesbot/carbon/src/Carbon/Lang/hi.php
new file mode 100644
index 000000000..6c670ee8c
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/hi.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '1 वरà¥à¤·|:count वरà¥à¤·à¥‹à¤‚',
+ 'y' => '1 वरà¥à¤·|:count वरà¥à¤·à¥‹à¤‚',
+ 'month' => '1 माह|:count महीने',
+ 'm' => '1 माह|:count महीने',
+ 'week' => '1 सपà¥à¤¤à¤¾à¤¹|:count सपà¥à¤¤à¤¾à¤¹',
+ 'w' => '1 सपà¥à¤¤à¤¾à¤¹|:count सपà¥à¤¤à¤¾à¤¹',
+ 'day' => '1 दिन|:count दिनों',
+ 'd' => '1 दिन|:count दिनों',
+ 'hour' => '1 घंटा|:count घंटे',
+ 'h' => '1 घंटा|:count घंटे',
+ 'minute' => '1 मिनट|:count मिनटों',
+ 'min' => '1 मिनट|:count मिनटों',
+ 'second' => '1 सेकंड|:count सेकंड',
+ 's' => '1 सेकंड|:count सेकंड',
+ 'ago' => ':time पूरà¥à¤µ',
+ 'from_now' => ':time से',
+ 'after' => ':time के बाद',
+ 'before' => ':time के पहले',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/hr.php b/vendor/nesbot/carbon/src/Carbon/Lang/hr.php
new file mode 100644
index 000000000..1a339de7b
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/hr.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count godinu|:count godine|:count godina',
+ 'y' => ':count godinu|:count godine|:count godina',
+ 'month' => ':count mjesec|:count mjeseca|:count mjeseci',
+ 'm' => ':count mjesec|:count mjeseca|:count mjeseci',
+ 'week' => ':count tjedan|:count tjedna|:count tjedana',
+ 'w' => ':count tjedan|:count tjedna|:count tjedana',
+ 'day' => ':count dan|:count dana|:count dana',
+ 'd' => ':count dan|:count dana|:count dana',
+ 'hour' => ':count sat|:count sata|:count sati',
+ 'h' => ':count sat|:count sata|:count sati',
+ 'minute' => ':count minutu|:count minute |:count minuta',
+ 'min' => ':count minutu|:count minute |:count minuta',
+ 'second' => ':count sekundu|:count sekunde|:count sekundi',
+ 's' => ':count sekundu|:count sekunde|:count sekundi',
+ 'ago' => 'prije :time',
+ 'from_now' => 'za :time',
+ 'after' => 'za :time',
+ 'before' => 'prije :time',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/hu.php b/vendor/nesbot/carbon/src/Carbon/Lang/hu.php
new file mode 100644
index 000000000..45daf41a1
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/hu.php
@@ -0,0 +1,52 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count év',
+ 'y' => ':count év',
+ 'month' => ':count hónap',
+ 'm' => ':count hónap',
+ 'week' => ':count hét',
+ 'w' => ':count hét',
+ 'day' => ':count nap',
+ 'd' => ':count nap',
+ 'hour' => ':count óra',
+ 'h' => ':count óra',
+ 'minute' => ':count perc',
+ 'min' => ':count perc',
+ 'second' => ':count másodperc',
+ 's' => ':count másodperc',
+ 'ago' => ':time',
+ 'from_now' => ':time múlva',
+ 'after' => ':time később',
+ 'before' => ':time korábban',
+ 'year_ago' => ':count éve',
+ 'month_ago' => ':count hónapja',
+ 'week_ago' => ':count hete',
+ 'day_ago' => ':count napja',
+ 'hour_ago' => ':count órája',
+ 'minute_ago' => ':count perce',
+ 'second_ago' => ':count másodperce',
+ 'year_after' => ':count évvel',
+ 'month_after' => ':count hónappal',
+ 'week_after' => ':count héttel',
+ 'day_after' => ':count nappal',
+ 'hour_after' => ':count órával',
+ 'minute_after' => ':count perccel',
+ 'second_after' => ':count másodperccel',
+ 'year_before' => ':count évvel',
+ 'month_before' => ':count hónappal',
+ 'week_before' => ':count héttel',
+ 'day_before' => ':count nappal',
+ 'hour_before' => ':count órával',
+ 'minute_before' => ':count perccel',
+ 'second_before' => ':count másodperccel',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/hy.php b/vendor/nesbot/carbon/src/Carbon/Lang/hy.php
new file mode 100644
index 000000000..d2665f27a
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/hy.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count Õ¿Õ¡Ö€Õ«',
+ 'y' => ':countÕ¿',
+ 'month' => ':count Õ¡Õ´Õ«Õ½',
+ 'm' => ':countÕ¡Õ´',
+ 'week' => ':count Õ·Õ¡Õ¢Õ¡Õ©',
+ 'w' => ':countÕ·',
+ 'day' => ':count Ö…Ö€',
+ 'd' => ':countÖ…Ö€',
+ 'hour' => ':count ÕªÕ¡Õ´',
+ 'h' => ':countÕª',
+ 'minute' => ':count Ö€Õ¸ÕºÕ¥',
+ 'min' => ':countÖ€',
+ 'second' => ':count Õ¾Õ¡Ö€Õ¯ÕµÕ¡Õ¶',
+ 's' => ':countÕ¾Ö€Õ¯',
+ 'ago' => ':time Õ¡Õ¼Õ¡Õ»',
+ 'from_now' => ':time Õ¶Õ¥Ö€Õ¯Õ¡ ÕºÕ¡Õ°Õ«Ö',
+ 'after' => ':time Õ°Õ¥Õ¿Õ¸',
+ 'before' => ':time Õ¡Õ¼Õ¡Õ»',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/id.php b/vendor/nesbot/carbon/src/Carbon/Lang/id.php
new file mode 100644
index 000000000..7f7114fad
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/id.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count tahun',
+ 'y' => ':count tahun',
+ 'month' => ':count bulan',
+ 'm' => ':count bulan',
+ 'week' => ':count minggu',
+ 'w' => ':count minggu',
+ 'day' => ':count hari',
+ 'd' => ':count hari',
+ 'hour' => ':count jam',
+ 'h' => ':count jam',
+ 'minute' => ':count menit',
+ 'min' => ':count menit',
+ 'second' => ':count detik',
+ 's' => ':count detik',
+ 'ago' => ':time yang lalu',
+ 'from_now' => ':time dari sekarang',
+ 'after' => ':time setelah',
+ 'before' => ':time sebelum',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/is.php b/vendor/nesbot/carbon/src/Carbon/Lang/is.php
new file mode 100644
index 000000000..94c76a7f2
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/is.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '1 ár|:count ár',
+ 'y' => '1 ár|:count ár',
+ 'month' => '1 mánuður|:count mánuðir',
+ 'm' => '1 mánuður|:count mánuðir',
+ 'week' => '1 vika|:count vikur',
+ 'w' => '1 vika|:count vikur',
+ 'day' => '1 dagur|:count dagar',
+ 'd' => '1 dagur|:count dagar',
+ 'hour' => '1 klukkutÃmi|:count klukkutÃmar',
+ 'h' => '1 klukkutÃmi|:count klukkutÃmar',
+ 'minute' => '1 mÃnúta|:count mÃnútur',
+ 'min' => '1 mÃnúta|:count mÃnútur',
+ 'second' => '1 sekúnda|:count sekúndur',
+ 's' => '1 sekúnda|:count sekúndur',
+ 'ago' => ':time sÃðan',
+ 'from_now' => ':time sÃðan',
+ 'after' => ':time eftir',
+ 'before' => ':time fyrir',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/it.php b/vendor/nesbot/carbon/src/Carbon/Lang/it.php
new file mode 100644
index 000000000..70bc6d7b3
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/it.php
@@ -0,0 +1,36 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count anno|:count anni',
+ 'y' => ':count anno|:count anni',
+ 'month' => ':count mese|:count mesi',
+ 'm' => ':count mese|:count mesi',
+ 'week' => ':count settimana|:count settimane',
+ 'w' => ':count settimana|:count settimane',
+ 'day' => ':count giorno|:count giorni',
+ 'd' => ':count giorno|:count giorni',
+ 'hour' => ':count ora|:count ore',
+ 'h' => ':count ora|:count ore',
+ 'minute' => ':count minuto|:count minuti',
+ 'min' => ':count minuto|:count minuti',
+ 'second' => ':count secondo|:count secondi',
+ 's' => ':count secondo|:count secondi',
+ 'ago' => ':time fa',
+ 'from_now' => 'tra :time',
+ 'after' => ':time dopo',
+ 'before' => ':time prima',
+ 'diff_now' => 'proprio ora',
+ 'diff_yesterday' => 'ieri',
+ 'diff_tomorrow' => 'domani',
+ 'diff_before_yesterday' => "l'altro ieri",
+ 'diff_after_tomorrow' => 'dopodomani',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ja.php b/vendor/nesbot/carbon/src/Carbon/Lang/ja.php
new file mode 100644
index 000000000..71195475d
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ja.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':countå¹´',
+ 'y' => ':countå¹´',
+ 'month' => ':countヶ月',
+ 'm' => ':countヶ月',
+ 'week' => ':count週間',
+ 'w' => ':count週間',
+ 'day' => ':countæ—¥',
+ 'd' => ':countæ—¥',
+ 'hour' => ':count時間',
+ 'h' => ':count時間',
+ 'minute' => ':count分',
+ 'min' => ':count分',
+ 'second' => ':countç§’',
+ 's' => ':countç§’',
+ 'ago' => ':timeå‰',
+ 'from_now' => '今ã‹ã‚‰:time',
+ 'after' => ':time後',
+ 'before' => ':timeå‰',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ka.php b/vendor/nesbot/carbon/src/Carbon/Lang/ka.php
new file mode 100644
index 000000000..a8dde7ebc
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ka.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count წლის',
+ 'y' => ':count წლის',
+ 'month' => ':count თვის',
+ 'm' => ':count თვის',
+ 'week' => ':count კვირის',
+ 'w' => ':count კვირის',
+ 'day' => ':count დღის',
+ 'd' => ':count დღის',
+ 'hour' => ':count სáƒáƒáƒ—ის',
+ 'h' => ':count სáƒáƒáƒ—ის',
+ 'minute' => ':count წუთის',
+ 'min' => ':count წუთის',
+ 'second' => ':count წáƒáƒ›áƒ˜áƒ¡',
+ 's' => ':count წáƒáƒ›áƒ˜áƒ¡',
+ 'ago' => ':time უკáƒáƒœ',
+ 'from_now' => ':time შემდეგ',
+ 'after' => ':time შემდეგ',
+ 'before' => ':time უკáƒáƒœ',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/kk.php b/vendor/nesbot/carbon/src/Carbon/Lang/kk.php
new file mode 100644
index 000000000..8d113afed
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/kk.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+return array(
+ 'year' => ':count жыл',
+ 'y' => ':count жыл',
+ 'month' => ':count ай',
+ 'm' => ':count ай',
+ 'week' => ':count апта',
+ 'w' => ':count апта',
+ 'day' => ':count күн',
+ 'd' => ':count күн',
+ 'hour' => ':count Ñағат',
+ 'h' => ':count Ñағат',
+ 'minute' => ':count минут',
+ 'min' => ':count минут',
+ 'second' => ':count Ñекунд',
+ 's' => ':count Ñекунд',
+ 'ago' => ':time бұрын',
+ 'from_now' => ':time кейін',
+ 'after' => ':time кейін',
+ 'before' => ':time бұрын',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/km.php b/vendor/nesbot/carbon/src/Carbon/Lang/km.php
new file mode 100644
index 000000000..a104e06eb
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/km.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count ឆ្នាំ',
+ 'y' => ':count ឆ្នាំ',
+ 'month' => ':count ážáŸ‚',
+ 'm' => ':count ážáŸ‚',
+ 'week' => ':count សប្ដាហáŸ',
+ 'w' => ':count សប្ដាហáŸ',
+ 'day' => ':count ážáŸ’ងៃ',
+ 'd' => ':count ážáŸ’ងៃ',
+ 'hour' => ':count ម៉ោង',
+ 'h' => ':count ម៉ោង',
+ 'minute' => ':count នាទី',
+ 'min' => ':count នាទី',
+ 'second' => ':count វិនាទី',
+ 's' => ':count វិនាទី',
+ 'ago' => ':timeមុន',
+ 'from_now' => ':timeពី​ឥឡូវ',
+ 'after' => 'នៅ​ក្រោយ :time',
+ 'before' => 'នៅ​មុន :time',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ko.php b/vendor/nesbot/carbon/src/Carbon/Lang/ko.php
new file mode 100644
index 000000000..020916442
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ko.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count ë…„',
+ 'y' => ':count ë…„',
+ 'month' => ':count 개월',
+ 'm' => ':count 개월',
+ 'week' => ':count 주ì¼',
+ 'w' => ':count 주ì¼',
+ 'day' => ':count ì¼',
+ 'd' => ':count ì¼',
+ 'hour' => ':count 시간',
+ 'h' => ':count 시간',
+ 'minute' => ':count ë¶„',
+ 'min' => ':count ë¶„',
+ 'second' => ':count ì´ˆ',
+ 's' => ':count ì´ˆ',
+ 'ago' => ':time ì „',
+ 'from_now' => ':time 후',
+ 'after' => ':time ì´í›„',
+ 'before' => ':time ì´ì „',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/lt.php b/vendor/nesbot/carbon/src/Carbon/Lang/lt.php
new file mode 100644
index 000000000..3f2fd1ec9
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/lt.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count metus|:count metus|:count metų',
+ 'y' => ':count metus|:count metus|:count metų',
+ 'month' => ':count mėnesį|:count mėnesius|:count mėnesių',
+ 'm' => ':count mėnesį|:count mėnesius|:count mėnesių',
+ 'week' => ':count savaitÄ™|:count savaites|:count savaiÄių',
+ 'w' => ':count savaitÄ™|:count savaites|:count savaiÄių',
+ 'day' => ':count dieną|:count dienas|:count dienų',
+ 'd' => ':count dieną|:count dienas|:count dienų',
+ 'hour' => ':count valandą|:count valandas|:count valandų',
+ 'h' => ':count valandą|:count valandas|:count valandų',
+ 'minute' => ':count minutÄ™|:count minutes|:count minuÄių',
+ 'min' => ':count minutÄ™|:count minutes|:count minuÄių',
+ 'second' => ':count sekundę|:count sekundes|:count sekundžių',
+ 's' => ':count sekundę|:count sekundes|:count sekundžių',
+ 'second_from_now' => ':count sekundės|:count sekundžių|:count sekundžių',
+ 'minute_from_now' => ':count minutÄ—s|:count minuÄių|:count minuÄių',
+ 'hour_from_now' => ':count valandos|:count valandų|:count valandų',
+ 'day_from_now' => ':count dienos|:count dienų|:count dienų',
+ 'week_from_now' => ':count savaitÄ—s|:count savaiÄių|:count savaiÄių',
+ 'month_from_now' => ':count mėnesio|:count mėnesių|:count mėnesių',
+ 'year_from_now' => ':count metų',
+ 'ago' => 'prieš :time',
+ 'from_now' => 'už :time',
+ 'after' => 'po :time',
+ 'before' => ':time nuo dabar',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/lv.php b/vendor/nesbot/carbon/src/Carbon/Lang/lv.php
new file mode 100644
index 000000000..363193db9
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/lv.php
@@ -0,0 +1,47 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '0 gadiem|:count gada|:count gadiem',
+ 'y' => '0 gadiem|:count gada|:count gadiem',
+ 'month' => '0 mēnešiem|:count mēneša|:count mēnešiem',
+ 'm' => '0 mēnešiem|:count mēneša|:count mēnešiem',
+ 'week' => '0 nedēļÄm|:count nedēļas|:count nedēļÄm',
+ 'w' => '0 nedēļÄm|:count nedēļas|:count nedēļÄm',
+ 'day' => '0 dienÄm|:count dienas|:count dienÄm',
+ 'd' => '0 dienÄm|:count dienas|:count dienÄm',
+ 'hour' => '0 stundÄm|:count stundas|:count stundÄm',
+ 'h' => '0 stundÄm|:count stundas|:count stundÄm',
+ 'minute' => '0 minūtēm|:count minūtes|:count minūtēm',
+ 'min' => '0 minūtēm|:count minūtes|:count minūtēm',
+ 'second' => '0 sekundēm|:count sekundes|:count sekundēm',
+ 's' => '0 sekundēm|:count sekundes|:count sekundēm',
+ 'ago' => 'pirms :time',
+ 'from_now' => 'pēc :time',
+ 'after' => ':time vÄ“lÄk',
+ 'before' => ':time pirms',
+
+ 'year_after' => '0 gadus|:count gadu|:count gadus',
+ 'month_after' => '0 mēnešus|:count mēnesi|:count mēnešus',
+ 'week_after' => '0 nedēļas|:count nedēļu|:count nedēļas',
+ 'day_after' => '0 dienas|:count dienu|:count dienas',
+ 'hour_after' => '0 stundas|:count stundu|:count stundas',
+ 'minute_after' => '0 minūtes|:count minūti|:count minūtes',
+ 'second_after' => '0 sekundes|:count sekundi|:count sekundes',
+
+ 'year_before' => '0 gadus|:count gadu|:count gadus',
+ 'month_before' => '0 mēnešus|:count mēnesi|:count mēnešus',
+ 'week_before' => '0 nedēļas|:count nedēļu|:count nedēļas',
+ 'day_before' => '0 dienas|:count dienu|:count dienas',
+ 'hour_before' => '0 stundas|:count stundu|:count stundas',
+ 'minute_before' => '0 minūtes|:count minūti|:count minūtes',
+ 'second_before' => '0 sekundes|:count sekundi|:count sekundes',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/mk.php b/vendor/nesbot/carbon/src/Carbon/Lang/mk.php
new file mode 100644
index 000000000..c5ec12df7
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/mk.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count година|:count години',
+ 'month' => ':count меÑец|:count меÑеци',
+ 'week' => ':count Ñедмица|:count Ñедмици',
+ 'day' => ':count ден|:count дена',
+ 'hour' => ':count чаÑ|:count чаÑа',
+ 'minute' => ':count минута|:count минути',
+ 'second' => ':count Ñекунда|:count Ñекунди',
+ 'ago' => 'пред :time',
+ 'from_now' => ':time од Ñега',
+ 'after' => 'по :time',
+ 'before' => 'пред :time',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/mn.php b/vendor/nesbot/carbon/src/Carbon/Lang/mn.php
new file mode 100644
index 000000000..b26dce557
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/mn.php
@@ -0,0 +1,62 @@
+
+ *
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ * @translator Batmandakh Erdenebileg
+ */
+
+return array(
+ 'year' => ':count жил',
+ 'y' => ':count жил',
+ 'month' => ':count Ñар',
+ 'm' => ':count Ñар',
+ 'week' => ':count долоо хоног',
+ 'w' => ':count долоо хоног',
+ 'day' => ':count өдөр',
+ 'd' => ':count өдөр',
+ 'hour' => ':count цаг',
+ 'h' => ':countц',
+ 'minute' => ':count минут',
+ 'min' => ':countм',
+ 'second' => ':count Ñекунд',
+ 's' => ':countÑ',
+
+ 'ago' => ':timeн өмнө',
+ 'year_ago' => ':count жилий',
+ 'month_ago' => ':count Ñары',
+ 'day_ago' => ':count хоногий',
+ 'hour_ago' => ':count цагий',
+ 'minute_ago' => ':count минуты',
+ 'second_ago' => ':count Ñекунды',
+
+ 'from_now' => 'Ð¾Ð´Ð¾Ð¾Ð³Ð¾Ð¾Ñ :time',
+ 'year_from_now' => ':count жилийн дараа',
+ 'month_from_now' => ':count Ñарын дараа',
+ 'day_from_now' => ':count хоногийн дараа',
+ 'hour_from_now' => ':count цагийн дараа',
+ 'minute_from_now' => ':count минутын дараа',
+ 'second_from_now' => ':count Ñекундын дараа',
+
+ // Does it required to make translation for before, after as follows? hmm, I think we've made it with ago and from now keywords already. Anyway, I've included it just in case of undesired action...
+ 'after' => ':timeн дараа',
+ 'year_after' => ':count жилий',
+ 'month_after' => ':count Ñары',
+ 'day_after' => ':count хоногий',
+ 'hour_after' => ':count цагий',
+ 'minute_after' => ':count минуты',
+ 'second_after' => ':count Ñекунды',
+ 'before' => ':timeн өмнө',
+ 'year_before' => ':count жилий',
+ 'month_before' => ':count Ñары',
+ 'day_before' => ':count хоногий',
+ 'hour_before' => ':count цагий',
+ 'minute_before' => ':count минуты',
+ 'second_before' => ':count Ñекунды',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ms.php b/vendor/nesbot/carbon/src/Carbon/Lang/ms.php
new file mode 100644
index 000000000..ef574228a
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ms.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count tahun',
+ 'y' => ':count tahun',
+ 'month' => ':count bulan',
+ 'm' => ':count bulan',
+ 'week' => ':count minggu',
+ 'w' => ':count minggu',
+ 'day' => ':count hari',
+ 'd' => ':count hari',
+ 'hour' => ':count jam',
+ 'h' => ':count jam',
+ 'minute' => ':count minit',
+ 'min' => ':count minit',
+ 'second' => ':count saat',
+ 's' => ':count saat',
+ 'ago' => ':time yang lalu',
+ 'from_now' => ':time dari sekarang',
+ 'after' => ':time selepas',
+ 'before' => ':time sebelum',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/my.php b/vendor/nesbot/carbon/src/Carbon/Lang/my.php
new file mode 100644
index 000000000..e8e491ecf
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/my.php
@@ -0,0 +1,37 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count နှစ်|:count နှစ်',
+ 'y' => ':count နှစ်|:count နှစ်',
+ 'month' => ':count လ|:count လ',
+ 'm' => ':count လ|:count လ',
+ 'week' => ':count ပá€á€º|:count ပá€á€º',
+ 'w' => ':count ပá€á€º|:count ပá€á€º',
+ 'day' => ':count ရက်|:count ရက်',
+ 'd' => ':count ရက်|:count ရက်',
+ 'hour' => ':count နာရီ|:count နာရီ',
+ 'h' => ':count နာရီ|:count နာရီ',
+ 'minute' => ':count မá€á€”စ်|:count မá€á€”စ်',
+ 'min' => ':count မá€á€”စ်|:count မá€á€”စ်',
+ 'second' => ':count စက္ကန့်|:count စက္ကန့်',
+ 's' => ':count စက္ကန့်|:count စက္ကန့်',
+ 'ago' => 'လွန်á€á€²á€·á€žá€±á€¬ :time က',
+ 'from_now' => 'ယá€á€¯á€™á€¾á€…áနောက် :time အကြာ',
+ 'after' => ':time ကြာပြီးနောက်',
+ 'before' => ':time မá€á€á€¯á€„်á€á€„်',
+ 'diff_now' => 'အá€á€¯á€œá€±á€¸á€á€„်',
+ 'diff_yesterday' => 'မနေ့က',
+ 'diff_tomorrow' => 'မနက်ဖြန်',
+ 'diff_before_yesterday' => 'á€á€™á€¼á€”်နေ့က',
+ 'diff_after_tomorrow' => 'á€á€˜á€€á€ºá€á€«',
+ 'period_recurrences' => ':count ကြá€á€™á€º',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ne.php b/vendor/nesbot/carbon/src/Carbon/Lang/ne.php
new file mode 100644
index 000000000..0b528dfa4
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ne.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count वरà¥à¤·',
+ 'y' => ':count वरà¥à¤·',
+ 'month' => ':count महिना',
+ 'm' => ':count महिना',
+ 'week' => ':count हपà¥à¤¤à¤¾',
+ 'w' => ':count हपà¥à¤¤à¤¾',
+ 'day' => ':count दिन',
+ 'd' => ':count दिन',
+ 'hour' => ':count घणà¥à¤Ÿà¤¾',
+ 'h' => ':count घणà¥à¤Ÿà¤¾',
+ 'minute' => ':count मिनेट',
+ 'min' => ':count मिनेट',
+ 'second' => ':count सेकेणà¥à¤¡',
+ 's' => ':count सेकेणà¥à¤¡',
+ 'ago' => ':time पहिले',
+ 'from_now' => ':time देखि',
+ 'after' => ':time पछि',
+ 'before' => ':time अघि',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/nl.php b/vendor/nesbot/carbon/src/Carbon/Lang/nl.php
new file mode 100644
index 000000000..ec5a88edf
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/nl.php
@@ -0,0 +1,36 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count jaar',
+ 'y' => ':count jaar',
+ 'month' => ':count maand|:count maanden',
+ 'm' => ':count maand|:count maanden',
+ 'week' => ':count week|:count weken',
+ 'w' => ':count week|:count weken',
+ 'day' => ':count dag|:count dagen',
+ 'd' => ':count dag|:count dagen',
+ 'hour' => ':count uur',
+ 'h' => ':count uur',
+ 'minute' => ':count minuut|:count minuten',
+ 'min' => ':count minuut|:count minuten',
+ 'second' => ':count seconde|:count seconden',
+ 's' => ':count seconde|:count seconden',
+ 'ago' => ':time geleden',
+ 'from_now' => 'over :time',
+ 'after' => ':time later',
+ 'before' => ':time eerder',
+ 'diff_now' => 'nu',
+ 'diff_yesterday' => 'gisteren',
+ 'diff_tomorrow' => 'morgen',
+ 'diff_after_tomorrow' => 'overmorgen',
+ 'diff_before_yesterday' => 'eergisteren',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/no.php b/vendor/nesbot/carbon/src/Carbon/Lang/no.php
new file mode 100644
index 000000000..a6ece06a0
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/no.php
@@ -0,0 +1,36 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count år|:count år',
+ 'y' => ':count år|:count år',
+ 'month' => ':count måned|:count måneder',
+ 'm' => ':count måned|:count måneder',
+ 'week' => ':count uke|:count uker',
+ 'w' => ':count uke|:count uker',
+ 'day' => ':count dag|:count dager',
+ 'd' => ':count dag|:count dager',
+ 'hour' => ':count time|:count timer',
+ 'h' => ':count time|:count timer',
+ 'minute' => ':count minutt|:count minutter',
+ 'min' => ':count minutt|:count minutter',
+ 'second' => ':count sekund|:count sekunder',
+ 's' => ':count sekund|:count sekunder',
+ 'ago' => ':time siden',
+ 'from_now' => 'om :time',
+ 'after' => ':time etter',
+ 'before' => ':time før',
+ 'diff_now' => 'akkurat nå',
+ 'diff_yesterday' => 'i går',
+ 'diff_tomorrow' => 'i morgen',
+ 'diff_before_yesterday' => 'i forgårs',
+ 'diff_after_tomorrow' => 'i overmorgen',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/oc.php b/vendor/nesbot/carbon/src/Carbon/Lang/oc.php
new file mode 100644
index 000000000..e89e94c3b
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/oc.php
@@ -0,0 +1,44 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
+ return $number == 1 ? 0 : 1;
+}, 'oc');
+
+return array(
+ 'year' => ':count an|:count ans',
+ 'y' => ':count an|:count ans',
+ 'month' => ':count mes|:count meses',
+ 'm' => ':count mes|:count meses',
+ 'week' => ':count setmana|:count setmanas',
+ 'w' => ':count setmana|:count setmanas',
+ 'day' => ':count jorn|:count jorns',
+ 'd' => ':count jorn|:count jorns',
+ 'hour' => ':count ora|:count oras',
+ 'h' => ':count ora|:count oras',
+ 'minute' => ':count minuta|:count minutas',
+ 'min' => ':count minuta|:count minutas',
+ 'second' => ':count segonda|:count segondas',
+ 's' => ':count segonda|:count segondas',
+ 'ago' => 'fa :time',
+ 'from_now' => 'dins :time',
+ 'after' => ':time aprèp',
+ 'before' => ':time abans',
+ 'diff_now' => 'ara meteis',
+ 'diff_yesterday' => 'ièr',
+ 'diff_tomorrow' => 'deman',
+ 'diff_before_yesterday' => 'ièr delà ',
+ 'diff_after_tomorrow' => 'deman passat',
+ 'period_recurrences' => ':count còp|:count còps',
+ 'period_interval' => 'cada :interval',
+ 'period_start_date' => 'de :date',
+ 'period_end_date' => 'fins a :date',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/pl.php b/vendor/nesbot/carbon/src/Carbon/Lang/pl.php
new file mode 100644
index 000000000..2308af2d0
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/pl.php
@@ -0,0 +1,36 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count rok|:count lata|:count lat',
+ 'y' => ':countr|:countl',
+ 'month' => ':count miesiąc|:count miesiące|:count miesięcy',
+ 'm' => ':countmies',
+ 'week' => ':count tydzień|:count tygodnie|:count tygodni',
+ 'w' => ':counttyg',
+ 'day' => ':count dzień|:count dni|:count dni',
+ 'd' => ':countd',
+ 'hour' => ':count godzina|:count godziny|:count godzin',
+ 'h' => ':countg',
+ 'minute' => ':count minuta|:count minuty|:count minut',
+ 'min' => ':countm',
+ 'second' => ':count sekunda|:count sekundy|:count sekund',
+ 's' => ':counts',
+ 'ago' => ':time temu',
+ 'from_now' => ':time od teraz',
+ 'after' => ':time po',
+ 'before' => ':time przed',
+ 'diff_now' => 'przed chwilÄ…',
+ 'diff_yesterday' => 'wczoraj',
+ 'diff_tomorrow' => 'jutro',
+ 'diff_before_yesterday' => 'przedwczoraj',
+ 'diff_after_tomorrow' => 'pojutrze',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ps.php b/vendor/nesbot/carbon/src/Carbon/Lang/ps.php
new file mode 100644
index 000000000..15c3296e2
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ps.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count کال|:count کاله',
+ 'y' => ':countکال|:countکاله',
+ 'month' => ':count مياشت|:count مياشتي',
+ 'm' => ':countمياشت|:countمياشتي',
+ 'week' => ':count اونÛ|:count اونÛ',
+ 'w' => ':countاونÛ|:countاونÛ',
+ 'day' => ':count ورÚ|:count ورÚÙŠ',
+ 'd' => ':countورÚ|:countورÚÙŠ',
+ 'hour' => ':count ساعت|:count ساعته',
+ 'h' => ':countساعت|:countساعته',
+ 'minute' => ':count دقيقه|:count دقيقÛ',
+ 'min' => ':countدقيقه|:countدقيقÛ',
+ 'second' => ':count ثانيه|:count ثانيÛ',
+ 's' => ':countثانيه|:countثانيÛ',
+ 'ago' => ':time دمخه',
+ 'from_now' => ':time له اوس څخه',
+ 'after' => ':time وروسته',
+ 'before' => ':time دمخه',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/pt.php b/vendor/nesbot/carbon/src/Carbon/Lang/pt.php
new file mode 100644
index 000000000..392b12159
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/pt.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count ano|:count anos',
+ 'y' => ':count ano|:count anos',
+ 'month' => ':count mês|:count meses',
+ 'm' => ':count mês|:count meses',
+ 'week' => ':count semana|:count semanas',
+ 'w' => ':count semana|:count semanas',
+ 'day' => ':count dia|:count dias',
+ 'd' => ':count dia|:count dias',
+ 'hour' => ':count hora|:count horas',
+ 'h' => ':count hora|:count horas',
+ 'minute' => ':count minuto|:count minutos',
+ 'min' => ':count minuto|:count minutos',
+ 'second' => ':count segundo|:count segundos',
+ 's' => ':count segundo|:count segundos',
+ 'ago' => ':time atrás',
+ 'from_now' => 'em :time',
+ 'after' => ':time depois',
+ 'before' => ':time antes',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php b/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php
new file mode 100644
index 000000000..1f84eac5f
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count ano|:count anos',
+ 'y' => ':counta|:counta',
+ 'month' => ':count mês|:count meses',
+ 'm' => ':countm|:countm',
+ 'week' => ':count semana|:count semanas',
+ 'w' => ':countsem|:countsem',
+ 'day' => ':count dia|:count dias',
+ 'd' => ':countd|:countd',
+ 'hour' => ':count hora|:count horas',
+ 'h' => ':counth|:counth',
+ 'minute' => ':count minuto|:count minutos',
+ 'min' => ':countmin|:countmin',
+ 'second' => ':count segundo|:count segundos',
+ 's' => ':counts|:counts',
+ 'ago' => 'há :time',
+ 'from_now' => 'em :time',
+ 'after' => 'após :time',
+ 'before' => ':time atrás',
+ 'diff_now' => 'agora',
+ 'diff_yesterday' => 'ontem',
+ 'diff_tomorrow' => 'amanhã',
+ 'diff_before_yesterday' => 'anteontem',
+ 'diff_after_tomorrow' => 'depois de amanhã',
+ 'period_recurrences' => 'uma|:count vez',
+ 'period_interval' => 'toda :interval',
+ 'period_start_date' => 'de :date',
+ 'period_end_date' => 'até :date',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ro.php b/vendor/nesbot/carbon/src/Carbon/Lang/ro.php
new file mode 100644
index 000000000..cc1672406
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ro.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => 'un an|:count ani|:count ani',
+ 'y' => 'un an|:count ani|:count ani',
+ 'month' => 'o lună|:count luni|:count luni',
+ 'm' => 'o lună|:count luni|:count luni',
+ 'week' => 'o săptămână|:count săptămâni|:count săptămâni',
+ 'w' => 'o săptămână|:count săptămâni|:count săptămâni',
+ 'day' => 'o zi|:count zile|:count zile',
+ 'd' => 'o zi|:count zile|:count zile',
+ 'hour' => 'o oră|:count ore|:count ore',
+ 'h' => 'o oră|:count ore|:count ore',
+ 'minute' => 'un minut|:count minute|:count minute',
+ 'min' => 'un minut|:count minute|:count minute',
+ 'second' => 'o secundă|:count secunde|:count secunde',
+ 's' => 'o secundă|:count secunde|:count secunde',
+ 'ago' => 'acum :time',
+ 'from_now' => ':time de acum',
+ 'after' => 'peste :time',
+ 'before' => 'acum :time',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ru.php b/vendor/nesbot/carbon/src/Carbon/Lang/ru.php
new file mode 100644
index 000000000..6a83fb131
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ru.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count год|:count года|:count лет',
+ 'y' => ':count г|:count г|:count л',
+ 'month' => ':count меÑÑц|:count меÑÑца|:count меÑÑцев',
+ 'm' => ':count м|:count м|:count м',
+ 'week' => ':count неделю|:count недели|:count недель',
+ 'w' => ':count н|:count н|:count н',
+ 'day' => ':count день|:count днÑ|:count дней',
+ 'd' => ':count д|:count д|:count д',
+ 'hour' => ':count чаÑ|:count чаÑа|:count чаÑов',
+ 'h' => ':count ч|:count ч|:count ч',
+ 'minute' => ':count минуту|:count минуты|:count минут',
+ 'min' => ':count мин|:count мин|:count мин',
+ 'second' => ':count Ñекунду|:count Ñекунды|:count Ñекунд',
+ 's' => ':count Ñ|:count Ñ|:count Ñ',
+ 'ago' => ':time назад',
+ 'from_now' => 'через :time',
+ 'after' => ':time поÑле',
+ 'before' => ':time до',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sh.php b/vendor/nesbot/carbon/src/Carbon/Lang/sh.php
new file mode 100644
index 000000000..57f287a7c
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sh.php
@@ -0,0 +1,35 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+\Symfony\Component\Translation\PluralizationRules::set(function ($number) {
+ return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+}, 'sh');
+
+return array(
+ 'year' => ':count godina|:count godine|:count godina',
+ 'y' => ':count godina|:count godine|:count godina',
+ 'month' => ':count mesec|:count meseca|:count meseci',
+ 'm' => ':count mesec|:count meseca|:count meseci',
+ 'week' => ':count nedelja|:count nedelje|:count nedelja',
+ 'w' => ':count nedelja|:count nedelje|:count nedelja',
+ 'day' => ':count dan|:count dana|:count dana',
+ 'd' => ':count dan|:count dana|:count dana',
+ 'hour' => ':count Äas|:count Äasa|:count Äasova',
+ 'h' => ':count Äas|:count Äasa|:count Äasova',
+ 'minute' => ':count minut|:count minuta|:count minuta',
+ 'min' => ':count minut|:count minuta|:count minuta',
+ 'second' => ':count sekund|:count sekunda|:count sekundi',
+ 's' => ':count sekund|:count sekunda|:count sekundi',
+ 'ago' => 'pre :time',
+ 'from_now' => 'za :time',
+ 'after' => 'nakon :time',
+ 'before' => ':time raniјe',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sk.php b/vendor/nesbot/carbon/src/Carbon/Lang/sk.php
new file mode 100644
index 000000000..61013448d
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sk.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => 'rok|:count roky|:count rokov',
+ 'y' => 'rok|:count roky|:count rokov',
+ 'month' => 'mesiac|:count mesiace|:count mesiacov',
+ 'm' => 'mesiac|:count mesiace|:count mesiacov',
+ 'week' => 'týždeň|:count týždne|:count týždňov',
+ 'w' => 'týždeň|:count týždne|:count týždňov',
+ 'day' => 'deň|:count dni|:count dnÃ',
+ 'd' => 'deň|:count dni|:count dnÃ',
+ 'hour' => 'hodinu|:count hodiny|:count hodÃn',
+ 'h' => 'hodinu|:count hodiny|:count hodÃn',
+ 'minute' => 'minútu|:count minúty|:count minút',
+ 'min' => 'minútu|:count minúty|:count minút',
+ 'second' => 'sekundu|:count sekundy|:count sekúnd',
+ 's' => 'sekundu|:count sekundy|:count sekúnd',
+ 'ago' => 'pred :time',
+ 'from_now' => 'za :time',
+ 'after' => 'o :time neskôr',
+ 'before' => ':time predtým',
+ 'year_ago' => 'rokom|:count rokmi|:count rokmi',
+ 'month_ago' => 'mesiacom|:count mesiacmi|:count mesiacmi',
+ 'week_ago' => 'týždňom|:count týždňami|:count týždňami',
+ 'day_ago' => 'dňom|:count dňami|:count dňami',
+ 'hour_ago' => 'hodinou|:count hodinami|:count hodinami',
+ 'minute_ago' => 'minútou|:count minútami|:count minútami',
+ 'second_ago' => 'sekundou|:count sekundami|:count sekundami',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sl.php b/vendor/nesbot/carbon/src/Carbon/Lang/sl.php
new file mode 100644
index 000000000..06686d135
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sl.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count leto|:count leti|:count leta|:count let',
+ 'y' => ':count leto|:count leti|:count leta|:count let',
+ 'month' => ':count mesec|:count meseca|:count mesece|:count mesecev',
+ 'm' => ':count mesec|:count meseca|:count mesece|:count mesecev',
+ 'week' => ':count teden|:count tedna|:count tedne|:count tednov',
+ 'w' => ':count teden|:count tedna|:count tedne|:count tednov',
+ 'day' => ':count dan|:count dni|:count dni|:count dni',
+ 'd' => ':count dan|:count dni|:count dni|:count dni',
+ 'hour' => ':count uro|:count uri|:count ure|:count ur',
+ 'h' => ':count uro|:count uri|:count ure|:count ur',
+ 'minute' => ':count minuto|:count minuti|:count minute|:count minut',
+ 'min' => ':count minuto|:count minuti|:count minute|:count minut',
+ 'second' => ':count sekundo|:count sekundi|:count sekunde|:count sekund',
+ 's' => ':count sekundo|:count sekundi|:count sekunde|:count sekund',
+ 'year_ago' => ':count letom|:count leti|:count leti|:count leti',
+ 'month_ago' => ':count mesecem|:count meseci|:count meseci|:count meseci',
+ 'week_ago' => ':count tednom|:count tednoma|:count tedni|:count tedni',
+ 'day_ago' => ':count dnem|:count dnevoma|:count dnevi|:count dnevi',
+ 'hour_ago' => ':count uro|:count urama|:count urami|:count urami',
+ 'minute_ago' => ':count minuto|:count minutama|:count minutami|:count minutami',
+ 'second_ago' => ':count sekundo|:count sekundama|:count sekundami|:count sekundami',
+ 'ago' => 'pred :time',
+ 'from_now' => 'Äez :time',
+ 'after' => 'Äez :time',
+ 'before' => 'pred :time',
+ 'diff_now' => 'ravnokar',
+ 'diff_yesterday' => 'vÄeraj',
+ 'diff_tomorrow' => 'jutri',
+ 'diff_before_yesterday' => 'predvÄerajÅ¡njim',
+ 'diff_after_tomorrow' => 'pojutrišnjem',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sq.php b/vendor/nesbot/carbon/src/Carbon/Lang/sq.php
new file mode 100644
index 000000000..6e138a041
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sq.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count vit|:count vjet',
+ 'y' => ':count vit|:count vjet',
+ 'month' => ':count muaj|:count muaj',
+ 'm' => ':count muaj|:count muaj',
+ 'week' => ':count javë|:count javë',
+ 'w' => ':count javë|:count javë',
+ 'day' => ':count ditë|:count ditë',
+ 'd' => ':count ditë|:count ditë',
+ 'hour' => ':count orë|:count orë',
+ 'h' => ':count orë|:count orë',
+ 'minute' => ':count minutë|:count minuta',
+ 'min' => ':count minutë|:count minuta',
+ 'second' => ':count sekondë|:count sekonda',
+ 's' => ':count sekondë|:count sekonda',
+ 'ago' => ':time më parë',
+ 'from_now' => ':time nga tani',
+ 'after' => ':time pas',
+ 'before' => ':time para',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sr.php b/vendor/nesbot/carbon/src/Carbon/Lang/sr.php
new file mode 100644
index 000000000..5a1064212
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sr.php
@@ -0,0 +1,37 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count godina|:count godine|:count godina',
+ 'y' => ':count godina|:count godine|:count godina',
+ 'month' => ':count mesec|:count meseca|:count meseci',
+ 'm' => ':count mesec|:count meseca|:count meseci',
+ 'week' => ':count nedelja|:count nedelje|:count nedelja',
+ 'w' => ':count nedelja|:count nedelje|:count nedelja',
+ 'day' => ':count dan|:count dana|:count dana',
+ 'd' => ':count dan|:count dana|:count dana',
+ 'hour' => ':count sat|:count sata|:count sati',
+ 'h' => ':count sat|:count sata|:count sati',
+ 'minute' => ':count minut|:count minuta |:count minuta',
+ 'min' => ':count minut|:count minuta |:count minuta',
+ 'second' => ':count sekund|:count sekunde|:count sekunde',
+ 's' => ':count sekund|:count sekunde|:count sekunde',
+ 'ago' => 'pre :time',
+ 'from_now' => ':time od sada',
+ 'after' => 'nakon :time',
+ 'before' => 'pre :time',
+
+ 'year_from_now' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina',
+ 'year_ago' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina',
+
+ 'week_from_now' => '{1} :count nedelju|{2,3,4} :count nedelje|[5,Inf[ :count nedelja',
+ 'week_ago' => '{1} :count nedelju|{2,3,4} :count nedelje|[5,Inf[ :count nedelja',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php b/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php
new file mode 100644
index 000000000..2db83edd9
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[ :count година',
+ 'y' => ':count г.',
+ 'month' => '{1} :count меÑец|{2,3,4}:count меÑеца|[5,Inf[ :count меÑеци',
+ 'm' => ':count м.',
+ 'week' => '{1} :count недеља|{2,3,4}:count недеље|[5,Inf[ :count недеља',
+ 'w' => ':count нед.',
+ 'day' => '{1,21,31} :count дан|[2,Inf[ :count дана',
+ 'd' => ':count д.',
+ 'hour' => '{1,21} :count Ñат|{2,3,4,22,23,24}:count Ñата|[5,Inf[ :count Ñати',
+ 'h' => ':count ч.',
+ 'minute' => '{1,21,31,41,51} :count минут|[2,Inf[ :count минута',
+ 'min' => ':count мин.',
+ 'second' => '{1,21,31,41,51} :count Ñекунд|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count Ñекунде|[5,Inf[:count Ñекунди',
+ 's' => ':count Ñек.',
+ 'ago' => 'пре :time',
+ 'from_now' => 'за :time',
+ 'after' => ':time након',
+ 'before' => ':time пре',
+
+ 'year_from_now' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година',
+ 'year_ago' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година',
+
+ 'week_from_now' => '{1} :count недељу|{2,3,4} :count недеље|[5,Inf[ :count недеља',
+ 'week_ago' => '{1} :count недељу|{2,3,4} :count недеље|[5,Inf[ :count недеља',
+
+ 'diff_now' => 'управо Ñада',
+ 'diff_yesterday' => 'јуче',
+ 'diff_tomorrow' => 'Ñутра',
+ 'diff_before_yesterday' => 'прекјуче',
+ 'diff_after_tomorrow' => 'прекоÑутра',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php b/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php
new file mode 100644
index 000000000..18214c44c
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count године|[0,Inf[ :count година',
+ 'y' => ':count г.',
+ 'month' => '{1} :count мјеÑец|{2,3,4}:count мјеÑеца|[5,Inf[ :count мјеÑеци',
+ 'm' => ':count мј.',
+ 'week' => '{1} :count недјеља|{2,3,4}:count недјеље|[5,Inf[ :count недјеља',
+ 'w' => ':count нед.',
+ 'day' => '{1,21,31} :count дан|[2,Inf[ :count дана',
+ 'd' => ':count д.',
+ 'hour' => '{1,21} :count Ñат|{2,3,4,22,23,24}:count Ñата|[5,Inf[ :count Ñати',
+ 'h' => ':count ч.',
+ 'minute' => '{1,21,31,41,51} :count минут|[2,Inf[ :count минута',
+ 'min' => ':count мин.',
+ 'second' => '{1,21,31,41,51} :count Ñекунд|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count Ñекунде|[5,Inf[:count Ñекунди',
+ 's' => ':count Ñек.',
+ 'ago' => 'прије :time',
+ 'from_now' => 'за :time',
+ 'after' => ':time након',
+ 'before' => ':time прије',
+
+ 'year_from_now' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година',
+ 'year_ago' => '{1,21,31,41,51} :count годину|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count године|[5,Inf[ :count година',
+
+ 'week_from_now' => '{1} :count недјељу|{2,3,4} :count недјеље|[5,Inf[ :count недјеља',
+ 'week_ago' => '{1} :count недјељу|{2,3,4} :count недјеље|[5,Inf[ :count недјеља',
+
+ 'diff_now' => 'управо Ñада',
+ 'diff_yesterday' => 'јуче',
+ 'diff_tomorrow' => 'Ñутра',
+ 'diff_before_yesterday' => 'прекјуче',
+ 'diff_after_tomorrow' => 'прекоÑјутра',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php b/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php
new file mode 100644
index 000000000..2d2e28814
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php
@@ -0,0 +1,43 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => '{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count godine|[0,Inf[ :count godina',
+ 'y' => ':count g.',
+ 'month' => '{1} :count mjesec|{2,3,4}:count mjeseca|[5,Inf[ :count mjeseci',
+ 'm' => ':count mj.',
+ 'week' => '{1} :count nedjelja|{2,3,4}:count nedjelje|[5,Inf[ :count nedjelja',
+ 'w' => ':count ned.',
+ 'day' => '{1,21,31} :count dan|[2,Inf[ :count dana',
+ 'd' => ':count d.',
+ 'hour' => '{1,21} :count sat|{2,3,4,22,23,24}:count sata|[5,Inf[ :count sati',
+ 'h' => ':count Ä.',
+ 'minute' => '{1,21,31,41,51} :count minut|[2,Inf[ :count minuta',
+ 'min' => ':count min.',
+ 'second' => '{1,21,31,41,51} :count sekund|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54}:count sekunde|[5,Inf[:count sekundi',
+ 's' => ':count sek.',
+ 'ago' => 'prije :time',
+ 'from_now' => 'za :time',
+ 'after' => ':time nakon',
+ 'before' => ':time prije',
+
+ 'year_from_now' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina',
+ 'year_ago' => '{1,21,31,41,51} :count godinu|{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54} :count godine|[5,Inf[ :count godina',
+
+ 'week_from_now' => '{1} :count nedjelju|{2,3,4} :count nedjelje|[5,Inf[ :count nedjelja',
+ 'week_ago' => '{1} :count nedjelju|{2,3,4} :count nedjelje|[5,Inf[ :count nedjelja',
+
+ 'diff_now' => 'upravo sada',
+ 'diff_yesterday' => 'juÄe',
+ 'diff_tomorrow' => 'sutra',
+ 'diff_before_yesterday' => 'prekjuÄe',
+ 'diff_after_tomorrow' => 'preksutra',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php b/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php
new file mode 100644
index 000000000..7ebf6f041
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php
@@ -0,0 +1,12 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return require __DIR__.'/sr_Latn_ME.php';
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sv.php b/vendor/nesbot/carbon/src/Carbon/Lang/sv.php
new file mode 100644
index 000000000..89a03b432
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sv.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count år|:count år',
+ 'y' => ':count år|:count år',
+ 'month' => ':count månad|:count månader',
+ 'm' => ':count månad|:count månader',
+ 'week' => ':count vecka|:count veckor',
+ 'w' => ':count vecka|:count veckor',
+ 'day' => ':count dag|:count dagar',
+ 'd' => ':count dag|:count dagar',
+ 'hour' => ':count timme|:count timmar',
+ 'h' => ':count timme|:count timmar',
+ 'minute' => ':count minut|:count minuter',
+ 'min' => ':count minut|:count minuter',
+ 'second' => ':count sekund|:count sekunder',
+ 's' => ':count sekund|:count sekunder',
+ 'ago' => ':time sedan',
+ 'from_now' => 'om :time',
+ 'after' => ':time efter',
+ 'before' => ':time före',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/sw.php b/vendor/nesbot/carbon/src/Carbon/Lang/sw.php
new file mode 100644
index 000000000..52f03429e
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/sw.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => 'mwaka 1|miaka :count',
+ 'y' => 'mwaka 1|miaka :count',
+ 'month' => 'mwezi 1|miezi :count',
+ 'm' => 'mwezi 1|miezi :count',
+ 'week' => 'wiki 1|wiki :count',
+ 'w' => 'wiki 1|wiki :count',
+ 'day' => 'siku 1|siku :count',
+ 'd' => 'siku 1|siku :count',
+ 'hour' => 'saa 1|masaa :count',
+ 'h' => 'saa 1|masaa :count',
+ 'minute' => 'dakika 1|dakika :count',
+ 'min' => 'dakika 1|dakika :count',
+ 'second' => 'sekunde 1|sekunde :count',
+ 's' => 'sekunde 1|sekunde :count',
+ 'ago' => ':time ziliyopita',
+ 'from_now' => ':time kwanzia sasa',
+ 'after' => ':time baada',
+ 'before' => ':time kabla',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/th.php b/vendor/nesbot/carbon/src/Carbon/Lang/th.php
new file mode 100644
index 000000000..88bb4ac40
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/th.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count ปี',
+ 'y' => ':count ปี',
+ 'month' => ':count เดืà¸à¸™',
+ 'm' => ':count เดืà¸à¸™',
+ 'week' => ':count สัปดาห์',
+ 'w' => ':count สัปดาห์',
+ 'day' => ':count วัน',
+ 'd' => ':count วัน',
+ 'hour' => ':count ชั่วโมง',
+ 'h' => ':count ชั่วโมง',
+ 'minute' => ':count นาที',
+ 'min' => ':count นาที',
+ 'second' => ':count วินาที',
+ 's' => ':count วินาที',
+ 'ago' => ':timeที่à¹à¸¥à¹‰à¸§',
+ 'from_now' => ':timeต่à¸à¸ˆà¸²à¸à¸™à¸µà¹‰',
+ 'after' => ':timeหลังจาà¸à¸™à¸µà¹‰',
+ 'before' => ':timeà¸à¹ˆà¸à¸™',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/tr.php b/vendor/nesbot/carbon/src/Carbon/Lang/tr.php
new file mode 100644
index 000000000..6a9dfed87
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/tr.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count yıl',
+ 'y' => ':count yıl',
+ 'month' => ':count ay',
+ 'm' => ':count ay',
+ 'week' => ':count hafta',
+ 'w' => ':count hafta',
+ 'day' => ':count gün',
+ 'd' => ':count gün',
+ 'hour' => ':count saat',
+ 'h' => ':count saat',
+ 'minute' => ':count dakika',
+ 'min' => ':count dakika',
+ 'second' => ':count saniye',
+ 's' => ':count saniye',
+ 'ago' => ':time önce',
+ 'from_now' => ':time sonra',
+ 'after' => ':time sonra',
+ 'before' => ':time önce',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/uk.php b/vendor/nesbot/carbon/src/Carbon/Lang/uk.php
new file mode 100644
index 000000000..8d08eaa4e
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/uk.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count рік|:count роки|:count років',
+ 'y' => ':count рік|:count роки|:count років',
+ 'month' => ':count міÑÑць|:count міÑÑці|:count міÑÑців',
+ 'm' => ':count міÑÑць|:count міÑÑці|:count міÑÑців',
+ 'week' => ':count тиждень|:count тижні|:count тижнів',
+ 'w' => ':count тиждень|:count тижні|:count тижнів',
+ 'day' => ':count день|:count дні|:count днів',
+ 'd' => ':count день|:count дні|:count днів',
+ 'hour' => ':count година|:count години|:count годин',
+ 'h' => ':count година|:count години|:count годин',
+ 'minute' => ':count хвилину|:count хвилини|:count хвилин',
+ 'min' => ':count хвилину|:count хвилини|:count хвилин',
+ 'second' => ':count Ñекунду|:count Ñекунди|:count Ñекунд',
+ 's' => ':count Ñекунду|:count Ñекунди|:count Ñекунд',
+ 'ago' => ':time тому',
+ 'from_now' => 'через :time',
+ 'after' => ':time піÑлÑ',
+ 'before' => ':time до',
+ 'diff_now' => 'щойно',
+ 'diff_yesterday' => 'вчора',
+ 'diff_tomorrow' => 'завтра',
+ 'diff_before_yesterday' => 'позавчора',
+ 'diff_after_tomorrow' => 'піÑлÑзавтра',
+ 'period_recurrences' => 'один раз|:count рази|:count разів',
+ 'period_interval' => 'кожні :interval',
+ 'period_start_date' => 'з :date',
+ 'period_end_date' => 'до :date',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/ur.php b/vendor/nesbot/carbon/src/Carbon/Lang/ur.php
new file mode 100644
index 000000000..3c5f7ed91
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/ur.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count سال',
+ 'month' => ':count ماه',
+ 'week' => ':count ÛÙØªÛ’',
+ 'day' => ':count روز',
+ 'hour' => ':count گھنٹے',
+ 'minute' => ':count منٹ',
+ 'second' => ':count سیکنڈ',
+ 'ago' => ':time Ù¾ÛÙ„Û’',
+ 'from_now' => ':time بعد',
+ 'after' => ':time بعد',
+ 'before' => ':time Ù¾ÛÙ„Û’',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/uz.php b/vendor/nesbot/carbon/src/Carbon/Lang/uz.php
new file mode 100644
index 000000000..1cb6f713e
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/uz.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count yil',
+ 'y' => ':count yil',
+ 'month' => ':count oy',
+ 'm' => ':count oy',
+ 'week' => ':count hafta',
+ 'w' => ':count hafta',
+ 'day' => ':count kun',
+ 'd' => ':count kun',
+ 'hour' => ':count soat',
+ 'h' => ':count soat',
+ 'minute' => ':count daqiqa',
+ 'min' => ':count daq',
+ 'second' => ':count soniya',
+ 's' => ':count s',
+ 'ago' => ':time avval',
+ 'from_now' => ':time dan keyin',
+ 'after' => ':time keyin',
+ 'before' => ':time oldin',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/vi.php b/vendor/nesbot/carbon/src/Carbon/Lang/vi.php
new file mode 100644
index 000000000..3f9838d66
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/vi.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':count năm',
+ 'y' => ':count năm',
+ 'month' => ':count tháng',
+ 'm' => ':count tháng',
+ 'week' => ':count tuần',
+ 'w' => ':count tuần',
+ 'day' => ':count ngà y',
+ 'd' => ':count ngà y',
+ 'hour' => ':count giá»',
+ 'h' => ':count giá»',
+ 'minute' => ':count phút',
+ 'min' => ':count phút',
+ 'second' => ':count giây',
+ 's' => ':count giây',
+ 'ago' => ':time trước',
+ 'from_now' => ':time từ bây giá»',
+ 'after' => ':time sau',
+ 'before' => ':time trước',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/zh.php b/vendor/nesbot/carbon/src/Carbon/Lang/zh.php
new file mode 100644
index 000000000..9e1f6cad5
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/zh.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':countå¹´',
+ 'y' => ':countå¹´',
+ 'month' => ':count个月',
+ 'm' => ':count个月',
+ 'week' => ':count周',
+ 'w' => ':count周',
+ 'day' => ':count天',
+ 'd' => ':count天',
+ 'hour' => ':countå°æ—¶',
+ 'h' => ':countå°æ—¶',
+ 'minute' => ':count分钟',
+ 'min' => ':count分钟',
+ 'second' => ':countç§’',
+ 's' => ':countç§’',
+ 'ago' => ':timeå‰',
+ 'from_now' => 'è·çŽ°åœ¨:time',
+ 'after' => ':timeåŽ',
+ 'before' => ':timeå‰',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php b/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php
new file mode 100644
index 000000000..c848723bc
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return array(
+ 'year' => ':countå¹´',
+ 'y' => ':countå¹´',
+ 'month' => ':count月',
+ 'm' => ':count月',
+ 'week' => ':count週',
+ 'w' => ':count週',
+ 'day' => ':count天',
+ 'd' => ':count天',
+ 'hour' => ':countå°æ™‚',
+ 'h' => ':countå°æ™‚',
+ 'minute' => ':count分é˜',
+ 'min' => ':count分é˜',
+ 'second' => ':countç§’',
+ 's' => ':countç§’',
+ 'ago' => ':timeå‰',
+ 'from_now' => 'è·ç¾åœ¨:time',
+ 'after' => ':time後',
+ 'before' => ':timeå‰',
+);
diff --git a/vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php b/vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php
new file mode 100644
index 000000000..4d83b0c65
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Laravel/ServiceProvider.php
@@ -0,0 +1,37 @@
+app['events'];
+ if ($events instanceof EventDispatcher || $events instanceof Dispatcher) {
+ $events->listen(class_exists('Illuminate\Foundation\Events\LocaleUpdated') ? 'Illuminate\Foundation\Events\LocaleUpdated' : 'locale.changed', function () use ($service) {
+ $service->updateLocale();
+ });
+ $service->updateLocale();
+ }
+ }
+
+ public function updateLocale()
+ {
+ $translator = $this->app['translator'];
+ if ($translator instanceof Translator || $translator instanceof IlluminateTranslator) {
+ Carbon::setLocale($translator->getLocale());
+ }
+ }
+
+ public function register()
+ {
+ // Needed for Laravel < 5.3 compatibility
+ }
+}
diff --git a/vendor/nesbot/carbon/src/Carbon/Translator.php b/vendor/nesbot/carbon/src/Carbon/Translator.php
new file mode 100644
index 000000000..12115b008
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Translator.php
@@ -0,0 +1,143 @@
+addLoader('array', new Translation\Loader\ArrayLoader());
+ parent::__construct($locale, $formatter, $cacheDir, $debug);
+ }
+
+ /**
+ * Reset messages of a locale (all locale if no locale passed).
+ * Remove custom messages and reload initial messages from matching
+ * file in Lang directory.
+ *
+ * @param string|null $locale
+ *
+ * @return bool
+ */
+ public function resetMessages($locale = null)
+ {
+ if ($locale === null) {
+ static::$messages = array();
+
+ return true;
+ }
+
+ if (file_exists($filename = __DIR__.'/Lang/'.$locale.'.php')) {
+ static::$messages[$locale] = require $filename;
+ $this->addResource('array', static::$messages[$locale], $locale);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Init messages language from matching file in Lang directory.
+ *
+ * @param string $locale
+ *
+ * @return bool
+ */
+ protected function loadMessagesFromFile($locale)
+ {
+ if (isset(static::$messages[$locale])) {
+ return true;
+ }
+
+ return $this->resetMessages($locale);
+ }
+
+ /**
+ * Set messages of a locale and take file first if present.
+ *
+ * @param string $locale
+ * @param array $messages
+ *
+ * @return $this
+ */
+ public function setMessages($locale, $messages)
+ {
+ $this->loadMessagesFromFile($locale);
+ $this->addResource('array', $messages, $locale);
+ static::$messages[$locale] = array_merge(
+ isset(static::$messages[$locale]) ? static::$messages[$locale] : array(),
+ $messages
+ );
+
+ return $this;
+ }
+
+ /**
+ * Get messages of a locale, if none given, return all the
+ * languages.
+ *
+ * @param string|null $locale
+ *
+ * @return array
+ */
+ public function getMessages($locale = null)
+ {
+ return $locale === null ? static::$messages : static::$messages[$locale];
+ }
+
+ /**
+ * Set the current translator locale and indicate if the source locale file exists
+ *
+ * @param string $locale locale ex. en
+ *
+ * @return bool
+ */
+ public function setLocale($locale)
+ {
+ $locale = preg_replace_callback('/[-_]([a-z]{2,})/', function ($matches) {
+ // _2-letters is a region, _3+-letters is a variant
+ return '_'.call_user_func(strlen($matches[1]) > 2 ? 'ucfirst' : 'strtoupper', $matches[1]);
+ }, strtolower($locale));
+
+ if ($this->loadMessagesFromFile($locale)) {
+ parent::setLocale($locale);
+
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/nesbot/carbon/src/Carbon/Upgrade.php b/vendor/nesbot/carbon/src/Carbon/Upgrade.php
new file mode 100644
index 000000000..26449ff74
--- /dev/null
+++ b/vendor/nesbot/carbon/src/Carbon/Upgrade.php
@@ -0,0 +1,150 @@
+ '5.8.0',
+ 'laravel/cashier' => '9.0.1',
+ 'illuminate/support' => '5.8.0',
+ 'laravel/dusk' => '5.0.0',
+ );
+
+ protected static $otherLibraries = array(
+ 'spatie/laravel-analytics' => '3.6.4',
+ 'jenssegers/date' => '3.5.0',
+ );
+
+ /**
+ * @param \UpdateHelper\UpdateHelper $helper
+ */
+ public function check(UpdateHelper $helper)
+ {
+ $helper->write(array(
+ 'Carbon 1 is deprecated, see how to migrate to Carbon 2.',
+ 'https://carbon.nesbot.com/docs/#api-carbon-2',
+ ));
+
+ if (static::SUGGEST_ON_UPDATE || static::ASK_ON_UPDATE || $helper->getIo()->isVerbose()) {
+ $laravelUpdate = array();
+
+ foreach (static::$laravelLibraries as $name => $version) {
+ if ($helper->hasAsDependency($name) && $helper->isDependencyLesserThan($name, $version)) {
+ $laravelUpdate[$name] = $version;
+ }
+ }
+
+ if (count($laravelUpdate)) {
+ $output = array(
+ ' Please consider upgrading your Laravel dependencies to be compatible with Carbon 2:',
+ );
+
+ foreach ($laravelUpdate as $name => $version) {
+ $output[] = " - $name at least to version $version";
+ }
+
+ $output[] = '';
+ $output[] = " If you can't update Laravel, check https://carbon.nesbot.com/ to see how to";
+ $output[] = ' install Carbon 2 using alias version and our adapter kylekatarnls/laravel-carbon-2';
+ $output[] = '';
+
+ $helper->write($output);
+ }
+
+ foreach (static::$otherLibraries as $name => $version) {
+ if ($helper->hasAsDependency($name) && $helper->isDependencyLesserThan($name, $version)) {
+ $helper->write(" Please consider upgrading $name at least to $version to be compatible with Carbon 2.\n");
+ }
+ }
+
+ if (static::ASK_ON_UPDATE) {
+ static::askForUpgrade($helper);
+
+ return;
+ }
+ }
+
+ $path = implode(DIRECTORY_SEPARATOR, array('.', 'vendor', 'bin', 'upgrade-carbon'));
+
+ if (!file_exists($path)) {
+ $path = realpath(__DIR__.'/../../bin/upgrade-carbon');
+ }
+
+ $helper->write(
+ ' You can run '.escapeshellarg($path).
+ ' to get help in updating carbon and other frameworks and libraries that depend on it.'
+ );
+ }
+
+ private static function getUpgradeQuestion($upgrades)
+ {
+ $message = "Do you want us to try the following upgrade:\n";
+
+ foreach ($upgrades as $name => $version) {
+ $message .= " - $name: $version\n";
+ }
+
+ return $message.'[Y/N] ';
+ }
+
+ public static function askForUpgrade(UpdateHelper $helper, $upgradeIfNotInteractive = false)
+ {
+ $upgrades = array(
+ 'nesbot/carbon' => '^2.0.0',
+ );
+
+ foreach (array(static::$laravelLibraries, static::$otherLibraries) as $libraries) {
+ foreach ($libraries as $name => $version) {
+ if ($helper->hasAsDependency($name) && $helper->isDependencyLesserThan($name, $version)) {
+ $upgrades[$name] = "^$version";
+ }
+ }
+ }
+
+ $shouldUpgrade = $helper->isInteractive()
+ ? $helper->getIo()->askConfirmation(static::getUpgradeQuestion($upgrades))
+ : $upgradeIfNotInteractive;
+
+ if ($shouldUpgrade) {
+ $helper->setDependencyVersions($upgrades)->update();
+ }
+ }
+
+ public static function upgrade(ScriptEvent $event = null)
+ {
+ if (!$event) {
+ $composer = new Composer();
+ $baseDir = __DIR__.'/../..';
+
+ if (file_exists("$baseDir/autoload.php")) {
+ $baseDir .= '/..';
+ }
+
+ $composer->setConfig(new Config(true, $baseDir));
+ $event = new ScriptEvent(
+ 'upgrade-carbon',
+ $composer,
+ new ConsoleIO(new StringInput(''), new ConsoleOutput(), new HelperSet(array(
+ new QuestionHelper(),
+ )))
+ );
+ }
+
+ static::askForUpgrade(new UpdateHelper($event), true);
+ }
+}
diff --git a/vendor/nesbot/carbon/src/JsonSerializable.php b/vendor/nesbot/carbon/src/JsonSerializable.php
new file mode 100644
index 000000000..d34060b44
--- /dev/null
+++ b/vendor/nesbot/carbon/src/JsonSerializable.php
@@ -0,0 +1,18 @@
+json_encode,
+ * which is a value of any type other than a resource.
+ *
+ * @since 5.4.0
+ */
+ public function jsonSerialize();
+ }
+}
diff --git a/vendor/nikic/php-parser/.gitignore b/vendor/nikic/php-parser/.gitignore
new file mode 100644
index 000000000..8c7db2a6e
--- /dev/null
+++ b/vendor/nikic/php-parser/.gitignore
@@ -0,0 +1,4 @@
+vendor/
+composer.lock
+grammar/kmyacc.exe
+grammar/y.output
diff --git a/vendor/nikic/php-parser/.travis.yml b/vendor/nikic/php-parser/.travis.yml
new file mode 100644
index 000000000..9cd00253e
--- /dev/null
+++ b/vendor/nikic/php-parser/.travis.yml
@@ -0,0 +1,31 @@
+language: php
+dist: trusty
+sudo: false
+
+cache:
+ directories:
+ - $HOME/.composer/cache
+
+php:
+ - 5.5
+ - 5.6
+ - 7.0
+ - nightly
+ - hhvm
+
+install:
+ - if [ $TRAVIS_PHP_VERSION = '5.6' ]; then composer require satooshi/php-coveralls '~1.0'; fi
+ - composer install --prefer-dist
+
+matrix:
+ allow_failures:
+ - php: nightly
+ fast_finish: true
+
+script:
+ - if [ $TRAVIS_PHP_VERSION = '5.6' ]; then vendor/bin/phpunit --coverage-clover build/logs/clover.xml; else vendor/bin/phpunit; fi
+ - if [ $TRAVIS_PHP_VERSION = '7.0' ]; then test_old/run-php-src.sh; fi
+
+after_success:
+ if [ $TRAVIS_PHP_VERSION = '5.6' ]; then php vendor/bin/coveralls; fi
+
diff --git a/vendor/nikic/php-parser/CHANGELOG.md b/vendor/nikic/php-parser/CHANGELOG.md
new file mode 100644
index 000000000..c2d953393
--- /dev/null
+++ b/vendor/nikic/php-parser/CHANGELOG.md
@@ -0,0 +1,422 @@
+Version 3.1.6-dev
+-----------------
+
+Nothing yet.
+
+Version 3.1.5 (2018-02-28)
+--------------------------
+
+### Fixed
+
+* Fixed duplicate comment assignment in switch statements. (#469)
+* Improve compatibility with PHP-Scoper. (#477)
+
+Version 3.1.4 (2018-01-25)
+--------------------------
+
+### Fixed
+
+* Fixed pretty printing of `-(-$x)` and `+(+$x)`. (#459)
+
+Version 3.1.3 (2017-12-26)
+--------------------------
+
+### Fixed
+
+* Improve compatibility with php-scoper, by supporting prefixed namespaces in
+ `NodeAbstract::getType()`.
+
+Version 3.1.2 (2017-11-04)
+--------------------------
+
+### Fixed
+
+* Comments on empty blocks are now preserved on a `Stmt\Nop` node. (#382)
+
+### Added
+
+* Added `kind` attribute for `Stmt\Namespace_` node, which is one of `KIND_SEMICOLON` or
+ `KIND_BRACED`. (#417)
+* Added `setDocComment()` method to namespace builder. (#437)
+
+Version 3.1.1 (2017-09-02)
+--------------------------
+
+### Fixed
+
+* Fixed syntax error on comment after brace-style namespace declaration. (#412)
+* Added support for TraitUse statements in trait builder. (#413)
+
+Version 3.1.0 (2017-07-28)
+--------------------------
+
+### Added
+
+* [PHP 7.2] Added support for trailing comma in group use statements.
+* [PHP 7.2] Added support for `object` type. This means `object` types will now be represented as a
+ builtin type (a simple `"object"` string), rather than a class `Name`.
+
+### Fixed
+
+* Floating-point numbers are now printed correctly if the LC_NUMERIC locale uses a comma as decimal
+ separator.
+
+### Changed
+
+* `Name::$parts` is no longer deprecated.
+
+Version 3.0.6 (2017-06-28)
+--------------------------
+
+### Fixed
+
+* Fixed the spelling of `Class_::VISIBILITY_MODIFIER_MASK`. The previous spelling of
+ `Class_::VISIBILITY_MODIFER_MASK` is preserved for backwards compatibility.
+* The pretty printing will now preserve comments inside array literals and function calls by
+ printing the array items / function arguments on separate lines. Array literals and functions that
+ do not contain comments are not affected.
+
+### Added
+
+* Added `Builder\Param::makeVariadic()`.
+
+### Deprecated
+
+* The `Node::setLine()` method has been deprecated.
+
+Version 3.0.5 (2017-03-05)
+--------------------------
+
+### Fixed
+
+* Name resolution of `NullableType`s is now performed earlier, so that a fully resolved signature is
+ available when a function is entered. (#360)
+* `Error` nodes are now considered empty, while previously they extended until the token where the
+ error occurred. This made some nodes larger than expected. (#359)
+* Fixed notices being thrown during error recovery in some situations. (#362)
+
+Version 3.0.4 (2017-02-10)
+--------------------------
+
+### Fixed
+
+* Fixed some extensibility issues in pretty printer (`pUseType()` is now public and `pPrec()` calls
+ into `p()`, instead of directly dispatching to the type-specific printing method).
+* Fixed notice in `bin/php-parse` script.
+
+### Added
+
+* Error recovery from missing semicolons is now supported in more cases.
+* Error recovery from trailing commas in positions where PHP does not support them is now supported.
+
+Version 3.0.3 (2017-02-03)
+--------------------------
+
+### Fixed
+
+* In `"$foo[0]"` the `0` is now parsed as an `LNumber` rather than `String`. (#325)
+* Ensure integers and floats are always pretty printed preserving semantics, even if the particular
+ value can only be manually constructed.
+* Throw a `LogicException` when trying to pretty-print an `Error` node. Previously this resulted in
+ an undefined method exception or fatal error.
+
+### Added
+
+* [PHP 7.1] Added support for negative interpolated offsets: `"$foo[-1]"`
+* Added `preserveOriginalNames` option to `NameResolver`. If this option is enabled, an
+ `originalName` attribute, containing the unresolved name, will be added to each resolved name.
+* Added `php-parse --with-positions` option, which dumps nodes with position information.
+
+### Deprecated
+
+* The XML serializer has been deprecated. In particular, the classes `Serializer\XML`,
+ `Unserializer\XML`, as well as the interfaces `Serializer` and `Unserializer` are deprecated.
+
+Version 3.0.2 (2016-12-06)
+--------------------------
+
+### Fixed
+
+* Fixed name resolution of nullable types. (#324)
+* Fixed pretty-printing of nullable types.
+
+Version 3.0.1 (2016-12-01)
+--------------------------
+
+### Fixed
+
+* Fixed handling of nested `list()`s: If the nested list was unkeyed, it was directly included in
+ the list items. If it was keyed, it was wrapped in `ArrayItem`. Now nested `List_` nodes are
+ always wrapped in `ArrayItem`s. (#321)
+
+Version 3.0.0 (2016-11-30)
+--------------------------
+
+### Added
+
+* Added support for dumping node positions in the NodeDumper through the `dumpPositions` option.
+* Added error recovery support for `$`, `new`, `Foo::`.
+
+Version 3.0.0-beta2 (2016-10-29)
+--------------------------------
+
+This release primarily improves our support for error recovery.
+
+### Added
+
+* Added `Node::setDocComment()` method.
+* Added `Error::getMessageWithColumnInfo()` method.
+* Added support for recovery from lexer errors.
+* Added support for recovering from "special" errors (i.e. non-syntax parse errors).
+* Added precise location information for lexer errors.
+* Added `ErrorHandler` interface, and `ErrorHandler\Throwing` and `ErrorHandler\Collecting` as
+ specific implementations. These provide a general mechanism for handling error recovery.
+* Added optional `ErrorHandler` argument to `Parser::parse()`, `Lexer::startLexing()` and
+ `NameResolver::__construct()`.
+* The `NameResolver` now adds a `namespacedName` attribute on name nodes that cannot be statically
+ resolved (unqualified unaliased function or constant names in namespaces).
+
+### Fixed
+
+* Fixed attribute assignment for `GroupUse` prefix and variables in interpolated strings.
+
+### Changed
+
+* The constants on `NameTraverserInterface` have been moved into the `NameTraverser` class.
+* Due to the error handling changes, the `Parser` interface and `Lexer` API have changed.
+* The emulative lexer now directly postprocesses tokens, instead of using `~__EMU__~` sequences.
+ This changes the protected API of the lexer.
+* The `Name::slice()` method now returns `null` for empty slices, previously `new Name([])` was
+ used. `Name::concat()` now also supports concatenation with `null`.
+
+### Removed
+
+* Removed `Name::append()` and `Name::prepend()`. These mutable methods have been superseded by
+ the immutable `Name::concat()`.
+* Removed `Error::getRawLine()` and `Error::setRawLine()`. These methods have been superseded by
+ `Error::getStartLine()` and `Error::setStartLine()`.
+* Removed support for node cloning in the `NodeTraverser`.
+* Removed `$separator` argument from `Name::toString()`.
+* Removed `throw_on_error` parser option and `Parser::getErrors()` method. Use the `ErrorHandler`
+ mechanism instead.
+
+Version 3.0.0-beta1 (2016-09-16)
+--------------------------------
+
+### Added
+
+* [7.1] Function/method and parameter builders now support PHP 7.1 type hints (void, iterable and
+ nullable types).
+* Nodes and Comments now implement `JsonSerializable`. The node kind is stored in a `nodeType`
+ property.
+* The `InlineHTML` node now has an `hasLeadingNewline` attribute, that specifies whether the
+ preceding closing tag contained a newline. The pretty printer honors this attribute.
+* Partial parsing of `$obj->` (with missing property name) is now supported in error recovery mode.
+* The error recovery mode is now exposed in the `php-parse` script through the `--with-recovery`
+ or `-r` flags.
+
+The following changes are also part of PHP-Parser 2.1.1:
+
+* The PHP 7 parser will now generate a parse error for `$var =& new Obj` assignments.
+* Comments on free-standing code blocks will now be retained as comments on the first statement in
+ the code block.
+
+Version 3.0.0-alpha1 (2016-07-25)
+---------------------------------
+
+### Added
+
+* [7.1] Added support for `void` and `iterable` types. These will now be represented as strings
+ (instead of `Name` instances) similar to other builtin types.
+* [7.1] Added support for class constant visibility. The `ClassConst` node now has a `flags` subnode
+ holding the visibility modifier, as well as `isPublic()`, `isProtected()` and `isPrivate()`
+ methods. The constructor changed to accept the additional subnode.
+* [7.1] Added support for nullable types. These are represented using a new `NullableType` node
+ with a single `type` subnode.
+* [7.1] Added support for short array destructuring syntax. This means that `Array` nodes may now
+ appear as the left-hand-side of assignments and foreach value targets. Additionally the array
+ items may now contain `null` values if elements are skipped.
+* [7.1] Added support for keys in list() destructuring. The `List` subnode `vars` has been renamed
+ to `items` and now contains `ArrayItem`s instead of plain variables.
+* [7.1] Added support for multi-catch. The `Catch` subnode `type` has been renamed to `types` and
+ is now an array of `Name`s.
+* `Name::slice()` now supports lengths and negative offsets. This brings it in line with
+ `array_slice()` functionality.
+
+### Changed
+
+Due to PHP 7.1 support additions described above, the node structure changed as follows:
+
+* `void` and `iterable` types are now stored as strings if the PHP 7 parser is used.
+* The `ClassConst` constructor changed to accept an additional `flags` subnode.
+* The `Array` subnode `items` may now contain `null` elements (destructuring).
+* The `List` subnode `vars` has been renamed to `items` and now contains `ArrayItem`s instead of
+ plain variables.
+* The `Catch` subnode `type` has been renamed to `types` and is now an array of `Name`s.
+
+Additionally the following changes were made:
+
+* The `type` subnode on `Class`, `ClassMethod` and `Property` has been renamed to `flags`. The
+ `type` subnode has retained for backwards compatibility and is populated to the same value as
+ `flags`. However, writes to `type` will not update `flags`.
+* The `TryCatch` subnode `finallyStmts` has been replaced with a `finally` subnode that holds an
+ explicit `Finally` node. This allows for more accurate attribute assignment.
+* The `Trait` constructor now has the same form as the `Class` and `Interface` constructors: It
+ takes an array of subnodes. Unlike classes/interfaces, traits can only have a `stmts` subnode.
+* The `NodeDumper` now prints class/method/property/constant modifiers, as well as the include and
+ use type in a textual representation, instead of only showing the number.
+* All methods on `PrettyPrinter\Standard` are now protected. Previoulsy most of them were public.
+
+### Removed
+
+* Removed support for running on PHP 5.4. It is however still possible to parse PHP 5.2-5.4 code
+ while running on a newer version.
+* The deprecated `Comment::setLine()` and `Comment::setText()` methods have been removed.
+* The deprecated `Name::set()`, `Name::setFirst()` and `Name::setLast()` methods have been removed.
+
+Version 2.1.1 (2016-09-16)
+--------------------------
+
+### Changed
+
+* The pretty printer will now escape all control characters in the range `\x00-\x1F` inside double
+ quoted strings. If no special escape sequence is available, an octal escape will be used.
+* The quality of the error recovery has been improved. In particular unterminated expressions should
+ be handled more gracefully.
+* The PHP 7 parser will now generate a parse error for `$var =& new Obj` assignments.
+* Comments on free-standing code blocks will no be retained as comments on the first statement in
+ the code block.
+
+Version 2.1.0 (2016-04-19)
+--------------------------
+
+### Fixed
+
+* Properly support `B""` strings (with uppercase `B`) in a number of places.
+* Fixed reformatting of indented parts in a certain non-standard comment style.
+
+### Added
+
+* Added `dumpComments` option to node dumper, to enable dumping of comments associated with nodes.
+* Added `Stmt\Nop` node, that is used to collect comments located at the end of a block or at the
+ end of a file (without a following node with which they could otherwise be associated).
+* Added `kind` attribute to `Expr\Exit` to distinguish between `exit` and `die`.
+* Added `kind` attribute to `Scalar\LNumber` to distinguish between decimal, binary, octal and
+ hexadecimal numbers.
+* Added `kind` attribtue to `Expr\Array` to distinguish between `array()` and `[]`.
+* Added `kind` attribute to `Scalar\String` and `Scalar\Encapsed` to distinguish between
+ single-quoted, double-quoted, heredoc and nowdoc string.
+* Added `docLabel` attribute to `Scalar\String` and `Scalar\Encapsed`, if it is a heredoc or
+ nowdoc string.
+* Added start file offset information to `Comment` nodes.
+* Added `setReturnType()` method to function and method builders.
+* Added `-h` and `--help` options to `php-parse` script.
+
+### Changed
+
+* Invalid octal literals now throw a parse error in PHP 7 mode.
+* The pretty printer takes all the new attributes mentioned in the previous section into account.
+* The protected `AbstractPrettyPrinter::pComments()` method no longer returns a trailing newline.
+* The bundled autoloader supports library files being stored in a different directory than
+ `PhpParser` for easier downstream distribution.
+
+### Deprecated
+
+* The `Comment::setLine()` and `Comment::setText()` methods have been deprecated. Construct new
+ objects instead.
+
+### Removed
+
+* The internal (but public) method `Scalar\LNumber::parse()` has been removed. A non-internal
+ `LNumber::fromString()` method has been added instead.
+
+Version 2.0.1 (2016-02-28)
+--------------------------
+
+### Fixed
+
+* `declare() {}` and `declare();` are not semantically equivalent and will now result in different
+ ASTs. The format case will have an empty `stmts` array, while the latter will set `stmts` to
+ `null`.
+* Magic constants are now supported as semi-reserved keywords.
+* A shebang line like `#!/usr/bin/env php` is now allowed at the start of a namespaced file.
+ Previously this generated an exception.
+* The `prettyPrintFile()` method will not strip a trailing `?>` from the raw data that follows a
+ `__halt_compiler()` statement.
+* The `prettyPrintFile()` method will not strip an opening `slice()` which takes a subslice of a name.
+
+### Changed
+
+* `PhpParser\Parser` is now an interface, implemented by `Parser\Php5`, `Parser\Php7` and
+ `Parser\Multiple`. The `Multiple` parser will try multiple parsers, until one succeeds.
+* Token constants are now defined on `PhpParser\Parser\Tokens` rather than `PhpParser\Parser`.
+* The `Name->set()`, `Name->append()`, `Name->prepend()` and `Name->setFirst()` methods are
+ deprecated in favor of `Name::concat()` and `Name->slice()`.
+* The `NodeTraverser` no longer clones nodes by default. The old behavior can be restored by
+ passing `true` to the constructor.
+* The constructor for `Scalar` nodes no longer has a default value. E.g. `new LNumber()` should now
+ be written as `new LNumber(0)`.
+
+---
+
+**This changelog only includes changes from the 2.0 series. For older changes see the
+[1.x series changelog](https://github.com/nikic/PHP-Parser/blob/1.x/CHANGELOG.md) and the
+[0.9 series changelog](https://github.com/nikic/PHP-Parser/blob/0.9/CHANGELOG.md).**
\ No newline at end of file
diff --git a/vendor/nikic/php-parser/LICENSE b/vendor/nikic/php-parser/LICENSE
new file mode 100644
index 000000000..920cc5b1f
--- /dev/null
+++ b/vendor/nikic/php-parser/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2011-2018 by Nikita Popov.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * The names of the contributors may not be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/nikic/php-parser/README.md b/vendor/nikic/php-parser/README.md
new file mode 100644
index 000000000..2f62754ce
--- /dev/null
+++ b/vendor/nikic/php-parser/README.md
@@ -0,0 +1,99 @@
+PHP Parser
+==========
+
+[](https://travis-ci.org/nikic/PHP-Parser) [](https://coveralls.io/github/nikic/PHP-Parser?branch=master)
+
+This is a PHP 5.2 to PHP 7.1 parser written in PHP. Its purpose is to simplify static code analysis and
+manipulation.
+
+[**Documentation for version 3.x**][doc_master] (stable; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.1).
+
+[Documentation for version 2.x][doc_2_x] (stable; for running on PHP >= 5.4; for parsing PHP 5.2 to PHP 7.0).
+
+[Documentation for version 1.x][doc_1_x] (unsupported; for running on PHP >= 5.3; for parsing PHP 5.2 to PHP 5.6).
+
+In a Nutshell
+-------------
+
+The parser turns PHP source code into an abstract syntax tree. For example, if you pass the following code into the
+parser:
+
+```php
+ Expr_AssignOp_BitwiseAnd
+Expr_AssignBitwiseOr => Expr_AssignOp_BitwiseOr
+Expr_AssignBitwiseXor => Expr_AssignOp_BitwiseXor
+Expr_AssignConcat => Expr_AssignOp_Concat
+Expr_AssignDiv => Expr_AssignOp_Div
+Expr_AssignMinus => Expr_AssignOp_Minus
+Expr_AssignMod => Expr_AssignOp_Mod
+Expr_AssignMul => Expr_AssignOp_Mul
+Expr_AssignPlus => Expr_AssignOp_Plus
+Expr_AssignShiftLeft => Expr_AssignOp_ShiftLeft
+Expr_AssignShiftRight => Expr_AssignOp_ShiftRight
+
+Expr_BitwiseAnd => Expr_BinaryOp_BitwiseAnd
+Expr_BitwiseOr => Expr_BinaryOp_BitwiseOr
+Expr_BitwiseXor => Expr_BinaryOp_BitwiseXor
+Expr_BooleanAnd => Expr_BinaryOp_BooleanAnd
+Expr_BooleanOr => Expr_BinaryOp_BooleanOr
+Expr_Concat => Expr_BinaryOp_Concat
+Expr_Div => Expr_BinaryOp_Div
+Expr_Equal => Expr_BinaryOp_Equal
+Expr_Greater => Expr_BinaryOp_Greater
+Expr_GreaterOrEqual => Expr_BinaryOp_GreaterOrEqual
+Expr_Identical => Expr_BinaryOp_Identical
+Expr_LogicalAnd => Expr_BinaryOp_LogicalAnd
+Expr_LogicalOr => Expr_BinaryOp_LogicalOr
+Expr_LogicalXor => Expr_BinaryOp_LogicalXor
+Expr_Minus => Expr_BinaryOp_Minus
+Expr_Mod => Expr_BinaryOp_Mod
+Expr_Mul => Expr_BinaryOp_Mul
+Expr_NotEqual => Expr_BinaryOp_NotEqual
+Expr_NotIdentical => Expr_BinaryOp_NotIdentical
+Expr_Plus => Expr_BinaryOp_Plus
+Expr_ShiftLeft => Expr_BinaryOp_ShiftLeft
+Expr_ShiftRight => Expr_BinaryOp_ShiftRight
+Expr_Smaller => Expr_BinaryOp_Smaller
+Expr_SmallerOrEqual => Expr_BinaryOp_SmallerOrEqual
+
+Scalar_ClassConst => Scalar_MagicConst_Class
+Scalar_DirConst => Scalar_MagicConst_Dir
+Scalar_FileConst => Scalar_MagicConst_File
+Scalar_FuncConst => Scalar_MagicConst_Function
+Scalar_LineConst => Scalar_MagicConst_Line
+Scalar_MethodConst => Scalar_MagicConst_Method
+Scalar_NSConst => Scalar_MagicConst_Namespace
+Scalar_TraitConst => Scalar_MagicConst_Trait
+```
+
+These changes may affect custom pretty printers and code comparing the return value of `Node::getType()` to specific
+strings.
+
+### Miscellaneous
+
+ * The classes `Template` and `TemplateLoader` have been removed. You should use some other [code generation][code_gen]
+ project built on top of PHP-Parser instead.
+
+ * The `PrettyPrinterAbstract::pStmts()` method now emits a leading newline if the statement list is not empty.
+ Custom pretty printers should remove the explicit newline before `pStmts()` calls.
+
+ Old:
+
+ ```php
+ public function pStmt_Trait(PHPParser_Node_Stmt_Trait $node) {
+ return 'trait ' . $node->name
+ . "\n" . '{' . "\n" . $this->pStmts($node->stmts) . "\n" . '}';
+ }
+ ```
+
+ New:
+
+ ```php
+ public function pStmt_Trait(Stmt\Trait_ $node) {
+ return 'trait ' . $node->name
+ . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}';
+ }
+ ```
+
+ [code_gen]: https://github.com/nikic/PHP-Parser/wiki/Projects-using-the-PHP-Parser#code-generation
\ No newline at end of file
diff --git a/vendor/nikic/php-parser/UPGRADE-2.0.md b/vendor/nikic/php-parser/UPGRADE-2.0.md
new file mode 100644
index 000000000..1c61de54f
--- /dev/null
+++ b/vendor/nikic/php-parser/UPGRADE-2.0.md
@@ -0,0 +1,74 @@
+Upgrading from PHP-Parser 1.x to 2.0
+====================================
+
+### PHP version requirements
+
+PHP-Parser now requires PHP 5.4 or newer to run. It is however still possible to *parse* PHP 5.2 and
+PHP 5.3 source code, while running on a newer version.
+
+### Creating a parser instance
+
+Parser instances should now be created through the `ParserFactory`. Old direct instantiation code
+will not work, because the parser class was renamed.
+
+Old:
+
+```php
+use PhpParser\Parser, PhpParser\Lexer;
+$parser = new Parser(new Lexer\Emulative);
+```
+
+New:
+
+```php
+use PhpParser\ParserFactory;
+$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
+```
+
+The first argument to `ParserFactory` determines how different PHP versions are handled. The
+possible values are:
+
+ * `ParserFactory::PREFER_PHP7`: Try to parse code as PHP 7. If this fails, try to parse it as PHP 5.
+ * `ParserFactory::PREFER_PHP5`: Try to parse code as PHP 5. If this fails, try to parse it as PHP 7.
+ * `ParserFactory::ONLY_PHP7`: Parse code as PHP 7.
+ * `ParserFactory::ONLY_PHP5`: Parse code as PHP 5.
+
+For most practical purposes the difference between `PREFER_PHP7` and `PREFER_PHP5` is mainly whether
+a scalar type hint like `string` will be stored as `'string'` (PHP 7) or as `new Name('string')`
+(PHP 5).
+
+To use a custom lexer, pass it as the second argument to the `create()` method:
+
+```php
+use PhpParser\ParserFactory;
+$lexer = new MyLexer;
+$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7, $lexer);
+```
+
+### Rename of the `PhpParser\Parser` class
+
+`PhpParser\Parser` is now an interface, which is implemented by `Parser\Php5`, `Parser\Php7` and
+`Parser\Multiple`. Parser tokens are now defined in `Parser\Tokens`. If you use the `ParserFactory`
+described above to create your parser instance, these changes should have no further impact on you.
+
+### Removal of legacy aliases
+
+All legacy aliases for classes have been removed. This includes the old non-namespaced `PHPParser_`
+classes, as well as the classes that had to be renamed for PHP 7 support.
+
+### Deprecations
+
+The `set()`, `setFirst()`, `append()` and `prepend()` methods of the `Node\Name` class have been
+deprecated. Instead `Name::concat()` and `Name->slice()` should be used.
+
+### Miscellaneous
+
+* The `NodeTraverser` no longer clones nodes by default. If you want to restore the old behavior,
+ pass `true` to the constructor.
+* The legacy node format has been removed. If you use custom nodes, they are now expected to
+ implement a `getSubNodeNames()` method.
+* The default value for `Scalar` node constructors was removed. This means that something like
+ `new LNumber()` should be replaced by `new LNumber(0)`.
+* String parts of encapsed strings are now represented using `Scalar\EncapsStringPart` nodes, while
+ previously raw strings were used. This affects the `parts` child of `Scalar\Encaps` and
+ `Expr\ShellExec`.
\ No newline at end of file
diff --git a/vendor/nikic/php-parser/UPGRADE-3.0.md b/vendor/nikic/php-parser/UPGRADE-3.0.md
new file mode 100644
index 000000000..9e04f2afd
--- /dev/null
+++ b/vendor/nikic/php-parser/UPGRADE-3.0.md
@@ -0,0 +1,160 @@
+Upgrading from PHP-Parser 2.x to 3.0
+====================================
+
+The backwards-incompatible changes in this release may be summarized as follows:
+
+ * The specific details of the node representation have changed in some cases, primarily to
+ accomodate new PHP 7.1 features.
+ * There have been significant changes to the error recovery implementation. This may affect you,
+ if you used the error recovery mode or have a custom lexer implementation.
+ * A number of deprecated methods were removed.
+
+### PHP version requirements
+
+PHP-Parser now requires PHP 5.5 or newer to run. It is however still possible to *parse* PHP 5.2,
+5.3 and 5.4 source code, while running on a newer version.
+
+### Changes to the node structure
+
+The following changes are likely to require code changes if the respective nodes are used:
+
+ * The `List` subnode `vars` has been renamed to `items` and now contains `ArrayItem`s instead of
+ plain variables.
+ * The `Catch` subnode `type` has been renamed to `types` and is now an array of `Name`s.
+ * The `TryCatch` subnode `finallyStmts` has been replaced with a `finally` subnode that holds an
+ explicit `Finally` node.
+ * The `type` subnode on `Class`, `ClassMethod` and `Property` has been renamed to `flags`. The
+ `type` subnode has retained for backwards compatibility and is populated to the same value as
+ `flags`. However, writes to `type` will not update `flags` and use of `type` is discouraged.
+
+The following changes are unlikely to require code changes:
+
+ * The `ClassConst` constructor changed to accept an additional `flags` subnode.
+ * The `Trait` constructor now has the same form as the `Class` and `Interface` constructors: It
+ takes an array of subnodes. Unlike classes/interfaces, traits can only have a `stmts` subnode.
+ * The `Array` subnode `items` may now contain `null` elements (due to destructuring).
+ * `void` and `iterable` types are now stored as strings if the PHP 7 parser is used. Previously
+ these would have been represented as `Name` instances.
+
+### Changes to error recovery mode
+
+Previously, error recovery mode was enabled by setting the `throwOnError` option to `false` when
+creating the parser, while collected errors were retrieved using the `getErrors()` method:
+
+```php
+$lexer = ...;
+$parser = (new ParserFactory)->create(ParserFactor::ONLY_PHP7, $lexer, [
+ 'throwOnError' => true,
+]);
+
+$stmts = $parser->parse($code);
+$errors = $parser->getErrors();
+if ($errors) {
+ handleErrors($errors);
+}
+processAst($stmts);
+```
+
+Both the `throwOnError` option and the `getErrors()` method have been removed in PHP-Parser 3.0.
+Instead an instance of `ErrorHandler\Collecting` should be passed to the `parse()` method:
+
+```php
+$lexer = ...;
+$parser = (new ParserFactory)->create(ParserFactor::ONLY_PHP7, $lexer);
+
+$errorHandler = new ErrorHandler\Collecting;
+$stmts = $parser->parse($code, $errorHandler);
+if ($errorHandler->hasErrors()) {
+ handleErrors($errorHandler->getErrors());
+}
+processAst($stmts);
+```
+
+#### Multiple parser fallback in error recovery mode
+
+As a result of this change, if a `Multiple` parser is used (e.g. through the `ParserFactory` using
+`PREFER_PHP7` or `PREFER_PHP5`), it will now return the result of the first *non-throwing* parse. As
+parsing never throws in error recovery mode, the result from the first parser will always be
+returned.
+
+The PHP 7 parser is a superset of the PHP 5 parser, with the exceptions that `=& new` and
+`global $$foo->bar` are not supported (other differences are in representation only). The PHP 7
+parser will be able to recover from the error in both cases. For this reason, this change will
+likely pass unnoticed if you do not specifically test for this syntax.
+
+It is possible to restore the precise previous behavior with the following code:
+
+```php
+$lexer = ...;
+$parser7 = new Parser\Php7($lexer);
+$parser5 = new Parser\Php5($lexer);
+
+$errors7 = new ErrorHandler\Collecting();
+$stmts7 = $parser7->parse($code, $errors7);
+if ($errors7->hasErrors()) {
+ $errors5 = new ErrorHandler\Collecting();
+ $stmts5 = $parser5->parse($code, $errors5);
+ if (!$errors5->hasErrors()) {
+ // If PHP 7 parse has errors but PHP 5 parse has no errors, use PHP 5 result
+ return [$stmts5, $errors5];
+ }
+}
+// If PHP 7 succeeds or both fail use PHP 7 result
+return [$stmts7, $errors7];
+```
+
+#### Error handling in the lexer
+
+In order to support recovery from lexer errors, the signature of the `startLexing()` method changed
+to optionally accept an `ErrorHandler`:
+
+```php
+// OLD
+public function startLexing($code);
+// NEW
+public function startLexing($code, ErrorHandler $errorHandler = null);
+```
+
+If you use a custom lexer with overriden `startLexing()` method, it needs to be changed to accept
+the extra parameter. The value should be passed on to the parent method.
+
+#### Error checks in node constructors
+
+The constructors of certain nodes used to contain additional checks for semantic errors, such as
+creating a try block without either catch or finally. These checks have been moved from the node
+constructors into the parser. This allows recovery from such errors, as well as representing the
+resulting (invalid) AST.
+
+This means that certain error conditions are no longer checked for manually constructed nodes.
+
+### Removed methods, arguments, options
+
+The following methods, arguments or options have been removed:
+
+ * `Comment::setLine()`, `Comment::setText()`: Create new `Comment` instances instead.
+ * `Name::set()`, `Name::setFirst()`, `Name::setLast()`, `Name::append()`, `Name::prepend()`:
+ Use `Name::concat()` in combination with `Name::slice()` instead.
+ * `Error::getRawLine()`, `Error::setRawLine()`. Use `Error::getStartLine()` and
+ `Error::setStartLine()` instead.
+ * `Parser::getErrors()`. Use `ErrorHandler\Collecting` instead.
+ * `$separator` argument of `Name::toString()`. Use `strtr()` instead, if you really need it.
+ * `$cloneNodes` argument of `NodeTraverser::__construct()`. Explicitly clone nodes in the visitor
+ instead.
+ * `throwOnError` parser option. Use `ErrorHandler\Collecting` instead.
+
+### Miscellaneous
+
+ * The `NameResolver` will now resolve unqualified function and constant names in the global
+ namespace into fully qualified names. For example `foo()` in the global namespace resolves to
+ `\foo()`. For names where no static resolution is possible, a `namespacedName` attribute is
+ added now, containing the namespaced variant of the name.
+ * All methods on `PrettyPrinter\Standard` are now protected. Previoulsy most of them were public.
+ The pretty printer should only be invoked using the `prettyPrint()`, `prettyPrintFile()` and
+ `prettyPrintExpr()` methods.
+ * The node dumper now prints numeric values that act as enums/flags in a string representation.
+ If node dumper results are used in tests, updates may be needed to account for this.
+ * The constants on `NameTraverserInterface` have been moved into the `NameTraverser` class.
+ * The emulative lexer now directly postprocesses tokens, instead of using `~__EMU__~` sequences.
+ This changes the protected API of the emulative lexer.
+ * The `Name::slice()` method now returns `null` for empty slices, previously `new Name([])` was
+ used. `Name::concat()` now also supports concatenation with `null`.
diff --git a/vendor/nikic/php-parser/bin/php-parse b/vendor/nikic/php-parser/bin/php-parse
new file mode 100644
index 000000000..1760e758d
--- /dev/null
+++ b/vendor/nikic/php-parser/bin/php-parse
@@ -0,0 +1,202 @@
+#!/usr/bin/env php
+ array(
+ 'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments'
+)));
+$parser = (new PhpParser\ParserFactory)->create(
+ PhpParser\ParserFactory::PREFER_PHP7,
+ $lexer
+);
+$dumper = new PhpParser\NodeDumper([
+ 'dumpComments' => true,
+ 'dumpPositions' => $attributes['with-positions'],
+]);
+$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
+$serializer = new PhpParser\Serializer\XML;
+
+$traverser = new PhpParser\NodeTraverser();
+$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
+
+foreach ($files as $file) {
+ if (strpos($file, ' Code $code\n";
+ } else {
+ if (!file_exists($file)) {
+ die("File $file does not exist.\n");
+ }
+
+ $code = file_get_contents($file);
+ echo "====> File $file:\n";
+ }
+
+ if ($attributes['with-recovery']) {
+ $errorHandler = new PhpParser\ErrorHandler\Collecting;
+ $stmts = $parser->parse($code, $errorHandler);
+ foreach ($errorHandler->getErrors() as $error) {
+ $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
+ echo $message . "\n";
+ }
+ if (null === $stmts) {
+ continue;
+ }
+ } else {
+ try {
+ $stmts = $parser->parse($code);
+ } catch (PhpParser\Error $error) {
+ $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
+ die($message . "\n");
+ }
+ }
+
+ foreach ($operations as $operation) {
+ if ('dump' === $operation) {
+ echo "==> Node dump:\n";
+ echo $dumper->dump($stmts, $code), "\n";
+ } elseif ('pretty-print' === $operation) {
+ echo "==> Pretty print:\n";
+ echo $prettyPrinter->prettyPrintFile($stmts), "\n";
+ } elseif ('serialize-xml' === $operation) {
+ echo "==> Serialized XML:\n";
+ echo $serializer->serialize($stmts), "\n";
+ } elseif ('var-dump' === $operation) {
+ echo "==> var_dump():\n";
+ var_dump($stmts);
+ } elseif ('resolve-names' === $operation) {
+ echo "==> Resolved names.\n";
+ $stmts = $traverser->traverse($stmts);
+ }
+ }
+}
+
+function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) {
+ if ($withColumnInfo && $e->hasColumnInfo()) {
+ return $e->getMessageWithColumnInfo($code);
+ } else {
+ return $e->getMessage();
+ }
+}
+
+function showHelp($error = '') {
+ if ($error) {
+ echo $error . "\n\n";
+ }
+ die(<<