• Модуль: main
  • Путь к файлу: ~/bitrix/modules/main/lib/text/dateconverter.php
  • Класс: BitrixMainTextDateConverter
  • Вызов: DateConverter::decode
static function decode($text, $limit = 0)
{
	$result = Array();
	if ($text == '')
	{
		return $result;
	}

	$metrics = Array();
	$date = new BitrixMainTypeDateTime();

	if ($limit > 0 && mb_strlen($text) > $limit)
	{
		$text = mb_substr($text, 0, $limit);
	}

	$originalText = $text;
	$text = mb_strtolower($text);

	$workTimeStart = explode('.', BitrixMainConfigOption::get('calendar', 'work_time_start', '9'));
	$timeOfStartDate = str_pad(intval($workTimeStart[0] ?? 0), 2, "0", STR_PAD_LEFT).':'.str_pad(intval($workTimeStart[1] ?? 0), 2, "0", STR_PAD_LEFT);

	$workTimeEnd = explode('.', BitrixMainConfigOption::get('calendar', 'work_time_end', '18'));
	$timeOfEndDate = str_pad(intval($workTimeEnd[0] ?? 0), 2, "0", STR_PAD_LEFT).':'.str_pad(intval($workTimeEnd[1] ?? 0), 2, "0", STR_PAD_LEFT);

	$defaultPregExceptionSearch =  Array('.', '/', '-', ':');
	$defaultPregExceptionReplace = Array('.', '/', '-', ':');

	// metric 1: near date
	$pattern = Array();
	for ($i = 1; $i <= 11; $i++)
	{
		$pattern[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_1_".$i));
		$pattern[$i] = $pattern[$i] <> ''? $pattern[$i]: 'bxt2dmetricskip';
		$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $pattern[$i]);
	}
	if (preg_match_all("/(".implode('|', $pattern).")/", $text, $match, PREG_OFFSET_CAPTURE))
	{
		foreach ($match[0] as $matchPattern)
		{
			$matchType = '';
			switch($matchPattern[0])
			{
				case $pattern[1]:
					$matchType = 'DAYAFTERTOMORROW';
					break;
				case $pattern[2]:
					$matchType = 'TOMORROW';
					break;
				case $pattern[3]:
					$matchType = 'TODAY';
					break;
				case $pattern[4]:
					$matchType = 'YESTERDAY';
					break;
				case $pattern[5]:
					$matchType = 'DAYBEFOREYESTERDAY';
					break;
				case $pattern[9]:
					$matchType = 'WEEK';
					break;
				case $pattern[10]:
					$matchType = 'WEEKEND';
					break;
				case $pattern[11]:
					$matchType = 'MONTH';
					break;
			}
			if ($matchType <> '')
			{
				$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
				$matchWord = self::getMatchWord($originalText, $position);

				$metrics[1][] = Array(
					'TYPE' => $matchType,
					'COUNT' => mb_strlen($matchWord),
					'POSITION' => $position,
					'MATCH' => $matchWord
				);
			}
		}
	}

	// metric 2: day of weeks
	$pattern = Array();
	for ($i = 1; $i <= 10; $i++)
	{
		$pattern[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_2_".$i));
		$pattern[$i] = $pattern[$i] <> ''? $pattern[$i]: 'bxt2dmetricskip';
		$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $pattern[$i]);
	}
	if (preg_match_all("/(".implode('|', $pattern).")/", $text, $match, PREG_OFFSET_CAPTURE))
	{
		foreach ($match[0] as $matchPattern)
		{
			$matchType = '';
			switch($matchPattern[0])
			{
				case $pattern[1]:
					$matchType = 'MONDAY';
					if (is_array($metrics[1]))
					{
						foreach ($metrics[1] as $key => $metric)
						{
							if ($metric['TYPE'] == 'WEEK')
							{
								$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
								$matchWord = self::getMatchWord($originalText, $position);

								if ($matchPattern[1] < $metric['POSITION'] && $matchPattern[1] + mb_strlen($matchWord) >= $metric['POSITION'] + $metric['COUNT'])
								{
									unset($metrics[1][$key]);
									if (empty($metrics[1]))
									{
										unset($metrics[1]);
									}
								}
							}
						}
					}
				break;
				case $pattern[2]:
					$matchType = 'TUESDAY';
				break;
				case $pattern[3]:
				case $pattern[4]:
				case $pattern[5]:
					$matchType = 'WEDNESDAY';
				break;
				case $pattern[6]:
					$matchType = 'THURSDAY';
				break;
				case $pattern[7]:
					$matchType = 'FRIDAY';
				break;
				case $pattern[8]:
					$matchType = 'SATURDAY';
				break;
				case $pattern[9]:
				case $pattern[10]:
					$matchType = 'SUNDAY';
				break;
			}

			if ($matchType <> '')
			{
				$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
				$matchWord = self::getMatchWord($originalText, $position);

				$metrics[2][] = Array(
					'TYPE' => $matchType,
					'COUNT' => mb_strlen($matchWord),
					'POSITION' => $position,
					'MATCH' => $matchWord
				);
			}
		}
	}

	// metric 3: modificators before/after and time
	$pattern = Array();
	for ($i = 1; $i <= 9; $i++)
	{
		$pattern[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_3_".$i));
		$pattern[$i] = $pattern[$i] <> ''? $pattern[$i]: 'bxt2dmetricskip';
		$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $pattern[$i]);
	}
	if (preg_match_all("/(".implode('|', $pattern).")/", $text, $match, PREG_OFFSET_CAPTURE))
	{
		foreach ($match[0] as $matchPattern)
		{
			$matchType = '';
			switch($matchPattern[0])
			{
				case $pattern[1]:
					$matchType = 'BEFORE';
				break;
				case $pattern[2]:
					$matchType = 'AFTER';
				break;
				case $pattern[3]:
					$matchType = 'NEXT';
				break;
				case $pattern[4]:
					$matchType = 'PREVIOUS';
				break;
				case $pattern[5]:
				case $pattern[6]:
					$matchType = 'ENDOF';
				break;
				case $pattern[7]:
					$matchType = 'MIDDLEOF';
				break;
				case $pattern[8]:
					$matchType = 'STARTOF';
				break;
				case $pattern[9]:
				case $pattern[10]:
					$matchType = 'THIS';
				break;
			}

			if (in_array($matchType, Array('BEFORE', 'AFTER')) && isset($metrics[1]))
			{
				foreach ($metrics[1] as $key => $metric)
				{
					if (in_array($metric['TYPE'], Array('DAYAFTERTOMORROW', 'DAYBEFOREYESTERDAY')))
					{
						if ($metric['POSITION'] == $matchPattern[1])
						{
							$matchType = '';
						}
					}
					else if (in_array($metric['TYPE'], Array('TOMORROW', 'YESTERDAY')))
					{
						if ($metric['POSITION'] == $matchPattern[1] + mb_strlen($matchPattern[0])+1)
						{
							if ($metric['TYPE'] == 'TOMORROW')
							{
								$metrics[1][$key]['TYPE'] = $matchType == 'AFTER'? 'DAYAFTERTOMORROW': 'TODAY';
							}
							else
							{
								$metrics[1][$key]['TYPE'] = $matchType == 'AFTER'? 'TODAY': 'DAYBEFOREYESTERDAY';
							}
							$matchType = '';
						}
					}
				}
			}

			if ($matchType <> '')
			{
				$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
				$matchWord = self::getMatchWord($originalText, $position);

				$metrics[3][] = Array(
					'TYPE' => $matchType,
					'COUNT' => mb_strlen($matchWord),
					'POSITION' => $position,
					'MATCH' => $matchWord
				);
			}
		}
	}
	if (preg_match_all("/([0-2][0-9]:[0-5][0-9])/", $text, $match, PREG_OFFSET_CAPTURE))
	{
		foreach ($match[0] as $matchPattern)
		{
			$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
			$matchWord = self::getMatchWord($originalText, $position);

			$metrics[3][] = Array(
				'TYPE' => 'HHMM',
				'VALUE' => $matchPattern[0],
				'COUNT' => mb_strlen($matchPattern[0]),
				'POSITION' => $position,
				'MATCH' => $matchWord
			);
		}
	}

	// metric 4: date
	$pattern = Array();
	$patternOriginal = Array();
	$patternLength = Array();
	for ($i = 1; $i <= 3; $i++)
	{
		$patternOriginal[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_4_".$i));
		$patternOriginal[$i] = $patternOriginal[$i] <> ''? $patternOriginal[$i]: 'bxt2dmetricskip';
		$patternLength[$i] = mb_strlen($patternOriginal[$i]);
		if ($patternOriginal[$i] != 'bxt2dmetricskip')
		{
			$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $patternOriginal[$i]);
			$pattern[$i] = str_replace(
				Array('yyyy', 'yy', 'mm', 'dd'),
				Array('[1-2][0-9][0-9][0-9]', '[0-9][0-9]', '[0-1][0-9]', '[0-3][0-9]'),
				$pattern[$i]
			);
			$pattern[$i] = '^(?>[s|t]?)('.$pattern[$i].')|[s|^|t]('.$pattern[$i].')(?=[s|$|r|t])';
		}
	}
	if (preg_match_all("/".implode('|', $pattern)."/", $text, $match, PREG_OFFSET_CAPTURE))
	{
		$count = count($match)-1;
		for ($i = 1; $i <= $count; $i++)
		{
			foreach ($match[$i] as $matchPattern)
			{
				if (!$matchPattern[0])
				{
					continue;
				}

				$matchType = '';
				$matchLength = '';
				switch(mb_strlen($matchPattern[0]))
				{
					case $patternLength[1]:
						$matchType = 'DDMMYYYY';
						$matchYear = mb_substr($matchPattern[0], mb_strpos($patternOriginal[1], 'yyyy'), 4);
						$matchMonth = mb_substr($matchPattern[0], mb_strpos($patternOriginal[1], 'mm'), 2);
						$matchDay = mb_substr($matchPattern[0], mb_strpos($patternOriginal[1], 'dd'), 2);
						$matchPattern[0] = $matchYear.'-'.$matchMonth.'-'.$matchDay;
						$matchLength = $patternLength[1];
						break;
					case $patternLength[2]:
						$matchType = 'DDMMYY';
						$matchYear = mb_substr($matchPattern[0], mb_strpos($patternOriginal[2], 'yy'), 2);
						$matchMonth = mb_substr($matchPattern[0], mb_strpos($patternOriginal[2], 'mm'), 2);
						$matchDay = mb_substr($matchPattern[0], mb_strpos($patternOriginal[2], 'dd'), 2);
						$matchPattern[0] = '20'.$matchYear.'-'.$matchMonth.'-'.$matchDay;
						$matchLength = $patternLength[2];
						break;
					case $patternLength[3]:
						$matchType = 'DDMM';
						$matchMonth = mb_substr($matchPattern[0], mb_strpos($patternOriginal[3], 'mm'), 2);
						$matchDay = mb_substr($matchPattern[0], mb_strpos($patternOriginal[3], 'dd'), 2);
						$matchPattern[0] = $date->format('Y').'-'.$matchMonth.'-'.$matchDay;
						$matchLength = $patternLength[3];
						break;
				}

				$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
				$matchWord = mb_substr($originalText, $position, $matchLength);

				$metrics[4][] = Array(
					'TYPE' => $matchType,
					'VALUE' => $matchPattern[0],
					'COUNT' => $matchLength,
					'POSITION' => $position,
					'MATCH' => $matchWord
				);
			}
		}
	}

	// metric 5: modificators of time
	$pattern = Array();
	for ($i = 1; $i <= 5; $i++)
	{
		$pattern[$i] = mb_strtolower(Loc::getMessage("MAIN_TDC_METRIC_5_".$i));
		$pattern[$i] = $pattern[$i] <> ''? $pattern[$i]: 'bxt2dmetricskip';
		$pattern[$i] = str_replace($defaultPregExceptionSearch, $defaultPregExceptionReplace, $pattern[$i]);
	}
	if (preg_match_all("/(".implode('|', $pattern).")/", $text, $match, PREG_OFFSET_CAPTURE))
	{
		foreach ($match[0] as $matchPattern)
		{
			$matchType = '';
			$matchValue = '';
			switch($matchPattern[0])
			{
				case $pattern[1]:
					$matchType = 'MORNING';
					$matchValue = $timeOfStartDate;
				break;
				case $pattern[2]:
					$matchType = 'LUNCH';
					$matchValue = '14:00';
				break;
				case $pattern[3]:
				break;
				case $pattern[4]:
					$matchType = 'WORKDAY';
					$matchValue = $timeOfEndDate;

					if (isset($metrics[1]))
					{
						foreach ($metrics[1] as $key => $metric)
						{
							if ($metric['TYPE'] == 'TODAY')
							{
								if ($metric['POSITION'] == $matchPattern[1] + mb_strlen($matchPattern[3]))
								{
									$matchType = '';
								}
							}
						}
					}
				break;
				case $pattern[5]:
					$matchType = 'EVENING';
					$matchValue = '20:00';
				break;
			}
			if ($matchType <> '')
			{
				$position = defined("BX_UTF")? mb_strlen(substr($text, 0, $matchPattern[1])) : $matchPattern[1];
				$matchWord = self::getMatchWord($originalText, $position);

				$metrics[5][] = Array(
					'TYPE' => $matchType,
					'VALUE' => $matchValue,
					'COUNT' => mb_strlen($matchWord),
					'POSITION' => $position,
					'MATCH' => $matchWord
				);
			}
		}
	}

	$countOfMetrics = 0;
	foreach ($metrics as $values)
	{
		if (!empty($values))
		{
			$countOfMetrics++;
		}
	}

	$useDefault = false;
	if ($countOfMetrics == 1 && (isset($metrics[3]) || isset($metrics[5])))
	{}
	else if ($countOfMetrics == 1)
	{
		$useDefault = true;
	}
	else if ($countOfMetrics == 2 && isset($metrics[3]))
	{
		$useDefault = !isset($metrics[5]);
	}
	else if ($countOfMetrics == 2 && isset($metrics[5]) && (isset($metrics[1]) || isset($metrics[2]) || isset($metrics[4])))
	{
		if (isset($metrics[1]))
		{
			foreach ($metrics[1] as $metric)
			{
				$progressDate = self::createDateUsingMetrics(1, $metric, $metrics[5]);
				$matchParams = self::getTextForReplace($originalText, $metric, $metrics[5]);
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_RELATIVE, $metric, $metrics[5]);
			}
		}
		else if (isset($metrics[2]))
		{
			foreach ($metrics[2] as $metric)
			{
				$progressDate = self::createDateUsingMetrics(2, $metric, $metrics[5]);
				$matchParams = self::getTextForReplace($originalText, $metric, $metrics[5]);
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_DAYOFWEEK, $metric, $metrics[5]);
			}
		}
		else if (isset($metrics[4]))
		{
			foreach ($metrics[4] as $metric)
			{
				$progressDate = self::createDateUsingMetrics(4, $metric, $metrics[5]);
				$matchParams = self::getTextForReplace($originalText, $metric, $metrics[5]);
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_CALENDAR, $metric, $metrics[5]);
			}
		}
	}
	else if ($countOfMetrics == 2 && isset($metrics[1]) && (isset($metrics[2]) || isset($metrics[4])))
	{
		if (isset($metrics[2]))
		{
			foreach ($metrics[2] as $metric)
			{
				$array = array();
				$progressDate = self::createDateUsingMetrics(2, $metric, $array);
				$matchParams = self::getTextForReplace($originalText, $metric, array());
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_DAYOFWEEK, $metric);
			}
		}
		elseif (isset($metrics[4]))
		{
			foreach ($metrics[4] as $metric)
			{
				$array = array();
				$progressDate = self::createDateUsingMetrics(4, $metric, $array);
				$matchParams = self::getTextForReplace($originalText, $metric, array());
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_CALENDAR, $metric);
			}
		}
	}
	else
	{
		$useDefault = true;
	}

	if ($useDefault)
	{
		$modificators = $metrics[3] ?? array();
		if (isset($metrics[4]) && count($metrics[4]))
		{
			foreach ($metrics[4] as $metric)
			{
				$progressDate = self::createDateUsingMetrics(4, $metric, $modificators);
				$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_CALENDAR, $metric, $modificators);
			}
		}
		else if (isset($metrics[2]) && count($metrics[2]))
		{
			foreach ($metrics[2] as $metric)
			{
				$progressDate = self::createDateUsingMetrics(2, $metric, $modificators);
				$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_DAYOFWEEK, $metric, $modificators);
			}
		}
		else if (isset($metrics[1]) && count($metrics[1]))
		{
			foreach ($metrics[1] as $metric)
			{
				$progressDate = self::createDateUsingMetrics(1, $metric, $modificators);
				$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_RELATIVE, $metric, $modificators);
			}
		}
		else if (isset($metrics[5]) && count($metrics[5]))
		{
			foreach ($metrics[5] as $metric)
			{
				$progressDate = self::createDateUsingMetrics(5, $metric, $modificators);
				$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_PARTOFDAY, $metric, $modificators);
			}
		}
		else if (isset($metrics[3]) && count($metrics[3]))
		{
			foreach ($metrics[3] as $metric)
			{
				$array = array();
				$progressDate = self::createDateUsingMetrics(3, $metric, $array);
				$matchParams = self::getTextForReplace($originalText, $metric, $modificators);
				$result[] = new DateConverterResult($progressDate, $matchParams, DateConverterResult::TYPE_MODIFIER, $metric);
			}
		}

	}

	return $result;
}