Что нового

Библиотека для парсинга даты на русском?

Suppir

Продвинутый
Сообщения
967
Репутация
62
Есть даты вида:

1/01/2010
01.01.2010
1 января 2010
1 янв. 2010 г.
1 января 2010г.
1 января, 2010 г.

и т.п. Существует ли библиотека для автоматического парсинга русских дат?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Suppir [?]
Существует ли библиотека для автоматического парсинга русских дат?
насколько мне известно - нет.
а что ты подразумеваешь под парсингом? вот получает скрипт на входе одну из строк предложенных тобой, что он должен выплюнуть в ответ?
 
Автор
S

Suppir

Продвинутый
Сообщения
967
Репутация
62
Ну да, посылаешь функции строку с датой в любом формате, а она выдаст массив: год, месяц, день.


Добавлено:
Сообщение автоматически объединено:

А еще лучше так. Посылаешь функцию строку, которая содержит дату, а функция возвращает:

массив: день, месяц, год - по умолчанию
строку: дд/мм/гггг - если у функции параметр 1
строку: дд.мм.гггг - если у функции параметр 2
строку: 1 января 2010 г. - если у функции параметр 3
и так далее.

Была бы очень полезная функция.


Добавлено:
Сообщение автоматически объединено:

Вот, например, на Ruby такая функция. На странице
http://ruby-doc.org/docs/ProgrammingRuby/
найди модуль module ParseDate (чуть ниже середины страницы)
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
ух... задача очень вызывающая... правда щас совсем времени нет. как появится можно и взяться. если другие пользователи форума не сделают этого раньше...
эвристика вещь тонкая.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
IMHO эта универсальность скажется на производительности не в лучшую сторону. Да и проще это делать под конкретные задачи. И как понять например в 10/11/10 где что есть? В результате получится куча "If", "Select" и "Switch".
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 471
Репутация
2 401
Suppir [?]
А еще лучше так. Посылаешь функцию строку, которая содержит дату, а функция возвращает
Вот так примерно:

Код:
$sDate = _Date_Formate("01, 01, 2010", 3, 1)
ConsoleWrite($sDate & @LF)

Func _Date_Formate($sDate, $iRetFormat = 0, $iLocale = 0)
	Local $sDelims_Pattern, $sDay_Pattern, $sMonth_Pattern, $sYear_Pattern, $sSearch_Pattern, $sMonth
	
	$sDelims_Pattern = '[\Q /\.,\E]+'
	$sDay_Pattern = '(\d{1,2})'
	$sMonth_Pattern = '(\d{1,2}|[январьфелмтпйиюгусбокд]{3,8}|[decmbrnovtspaugjlyihf]{3,9})'
	$sYear_Pattern = '(\d{4})\h?(?:г\.)?'
	
	$sSearch_Pattern = '(?i)' & $sDay_Pattern & $sDelims_Pattern & $sMonth_Pattern & $sDelims_Pattern & $sYear_Pattern
	
	$sMonth = _DateMonthStrToInt(StringRegExpReplace($sDate, $sSearch_Pattern, '\2'))
	
	Switch $iRetFormat
		Case 0, -1, Default
			Return StringRegExp($sDate, $sSearch_Pattern, 3)
		Case 1
			Return StringRegExpReplace($sDate, $sSearch_Pattern, '\1/' & $sMonth & '/\3')
		Case 2
			Return StringRegExpReplace($sDate, $sSearch_Pattern, '\1.' & $sMonth & '.\3')
		Case 3
			$sMonth = _DateMonthIntToStr(StringRegExpReplace($sDate, $sSearch_Pattern, '\2'), $iLocale, 1)
			Return StringRegExpReplace($sDate, $sSearch_Pattern, '\1 ' & $sMonth & ' \3 г.')
	EndSwitch
	
	Return SetError(1, 0, $sDate)
EndFunc

Func _DateMonthIntToStr($iMonth, $iLocale = 0, $iRetMode = 0)
	Local $aMonthNumber_En[13] = ["", "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"]
	Local $aMonthNumber_Ru[13] = ["", "январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"]
	Local $aMonthNumber_Ru_mod[13] = ["", "января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"]
	
	If Not StringIsInt($iMonth) Or $iMonth < 1 Or $iMonth > 12 Then
		Return SetError(1, 0, $iMonth)
	EndIf
	
	Switch $iLocale
		Case 1
			If $iRetMode = 1 Then
				Return $aMonthNumber_Ru_mod[$iMonth]
			Else
				Return $aMonthNumber_Ru[$iMonth]
			EndIf
		Case Else
			Return $aMonthNumber_En[$iMonth]
	EndSwitch
EndFunc

Func _DateMonthStrToInt($sMonth)
	Local $aMonths_En = StringSplit('january|february|march|april|may|june|july|august|september|october|november|december', '|')
	Local $aMonths_Ru = StringSplit('январь|февраль|март|апрель|май|июнь|июль|август|сентябрь|октябрь|ноябрь|декабрь', '|')
	Local $aMonths_Ru_mod = StringSplit('января|февраля|марта|апреля|мая|июня|июля|августа|сентября|октября|ноября|декабря', '|')
	
	For $i = 1 To $aMonths_En[0]
		If $sMonth = $aMonths_En[$i] Then
			Return StringFormat('%.2i', $i)
		EndIf
	Next
	
	For $i = 1 To $aMonths_Ru[0]
		If $sMonth = $aMonths_Ru[$i] Then
			Return StringFormat('%.2i', $i)
		EndIf
	Next
	
	For $i = 1 To $aMonths_Ru_mod[0]
		If $sMonth = $aMonths_Ru_mod[$i] Then
			Return StringFormat('%.2i', $i)
		EndIf
	Next
	
	Return SetError(1, 0, $sMonth)
EndFunc




Добавлено:
Сообщение автоматически объединено:

А вот ещё лучше, формат задаётся строкой :laugh: :

Код:
$sDate = _Date_Formate("01, 01, 2010", 'dd mmm~ yyyy г.', 1)
ConsoleWrite($sDate & @LF)

Func _Date_Formate($sDate, $sRetFormat = -1, $iLocale = 0, $iReplaceCount = 1)
	Local $sDelims_Pattern, $sDay_Pattern, $sMonth_Pattern, $sYear_Pattern, $sSearch_Pattern, $sDay, $sMonth, $sYear, $iMode
	
	$sDelims_Pattern = '[\Q /\.,\E]+'
	$sDay_Pattern = '(\d{1,2})'
	$sMonth_Pattern = '(\d{1,2}|[январьфелмтпйиюгусбокд]{3,8}|[decmbrnovtspaugjlyihf]{3,9})'
	$sYear_Pattern = '(\d{4})\h?(?:г\.)?'
	
	$sSearch_Pattern = '(?i)' & $sDay_Pattern & $sDelims_Pattern & $sMonth_Pattern & $sDelims_Pattern & $sYear_Pattern
	
	Switch $sRetFormat
		Case -1, Default
			Return StringRegExp($sDate, $sSearch_Pattern, 3)
		Case Else
			$sDay = StringRegExpReplace($sDate, $sSearch_Pattern, '\1')
			$sMonth = StringRegExpReplace($sDate, $sSearch_Pattern, '\2')
			$sYear = StringRegExpReplace($sDate, $sSearch_Pattern, '\3')
			
			If StringIsDigit($sMonth) And Not StringRegExp($sRetFormat, '(?i)[^m]mm?[^m]') Then
				$iMode = 0
				
				If StringInStr($sRetFormat, 'mmm~') Then ;Needs to be expanded - for our reach russian language :)
					$iMode = 1
				EndIf
				
				$sMonth = _DateMonthIntToStr($sMonth, $iLocale, $iMode)
			ElseIf Not StringInStr($sRetFormat, 'mmm') Then
				$sMonth = _DateMonthStrToInt($sMonth)
			EndIf
			
			$sRet = StringReplace($sRetFormat, 'dd', StringFormat('%.2i', $sDay), $iReplaceCount)
			
			If @extended = 0 Then
				$sRet = StringReplace($sRet, 'd', StringFormat('%.1i', $sDay), $iReplaceCount)
			EndIf
			
			$sRet = StringRegExpReplace($sRet, '(?i)mmm~?', $sMonth, $iReplaceCount)
			
			If @extended = 0 Then
				$sRet = StringReplace($sRet, 'mm', StringFormat('%.2i', $sMonth), $iReplaceCount)
				
				If @extended = 0 Then
					$sRet = StringReplace($sRet, 'm', StringFormat('%.1i', $sMonth), $iReplaceCount)
				EndIf
			EndIf
			
			$sRet = StringReplace($sRet, 'yyyy', $sYear, $iReplaceCount)
			
			If @extended = 0 Then
				$sRet = StringReplace($sRet, 'yy', StringRight($sYear, 2), $iReplaceCount)
			EndIf
			
			Return $sRet
	EndSwitch
	
	Return SetError(1, 0, $sDate)
EndFunc

Func _DateMonthIntToStr($iMonth, $iLocale = 0, $iRetMode = 0)
	Local $aMonthNumber_En[13] = ["", "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"]
	Local $aMonthNumber_Ru[13] = ["", "январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"]
	Local $aMonthNumber_Ru_Mod[13] = ["", "января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"]
	
	If Not StringIsInt($iMonth) Or $iMonth < 1 Or $iMonth > 12 Then
		Return SetError(1, 0, $iMonth)
	EndIf
	
	Switch $iLocale
		Case 1
			If $iRetMode = 1 Then
				Return StringUpper(StringLeft($aMonthNumber_Ru_Mod[$iMonth], 1)) & StringMid($aMonthNumber_Ru_Mod[$iMonth], 2)
			Else
				Return StringUpper(StringLeft($aMonthNumber_Ru[$iMonth], 1)) & StringMid($aMonthNumber_Ru[$iMonth], 2)
			EndIf
		Case Else
			Return StringUpper(StringLeft($aMonthNumber_En[$iMonth], 1)) & StringMid($aMonthNumber_En[$iMonth], 2)
	EndSwitch
EndFunc

Func _DateMonthStrToInt($sMonth)
	Local $aMonths_En = StringSplit('january|february|march|april|may|june|july|august|september|october|november|december', '|')
	Local $aMonths_En_Shrt = StringSplit('jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec', '|')
	
	For $i = 1 To $aMonths_En[0]
		If $sMonth = $aMonths_En[$i] Then
			Return StringFormat('%.2i', $i)
		EndIf
	Next
	
	For $i = 1 To $aMonths_En_Shrt[0]
		If $sMonth = $aMonths_En_Shrt[$i] Then
			Return StringFormat('%.2i', $i)
		EndIf
	Next
	
	Local $aMonths_Ru = StringSplit('январь|февраль|март|апрель|май|июнь|июль|август|сентябрь|октябрь|ноябрь|декабрь', '|')
	Local $aMonths_Ru_Shrt = StringSplit('янв|февр|март|апр|май|июнь|июль|авг.|сент|окт|нояб|дек', '|')
	Local $aMonths_Ru_Mod = StringSplit('января|февраля|марта|апреля|мая|июня|июля|августа|сентября|октября|ноября|декабря', '|')
	
	For $i = 1 To $aMonths_Ru[0]
		If $sMonth = $aMonths_Ru[$i] Then
			Return StringFormat('%.2i', $i)
		EndIf
	Next
	
	For $i = 1 To $aMonths_Ru_Shrt[0]
		If $sMonth = $aMonths_Ru_Shrt[$i] Then
			Return StringFormat('%.2i', $i)
		EndIf
	Next
	
	For $i = 1 To $aMonths_Ru_Mod[0]
		If $sMonth = $aMonths_Ru_Mod[$i] Then
			Return StringFormat('%.2i', $i)
		EndIf
	Next
	
	Return SetError(1, 0, $sMonth)
EndFunc


Пару нюансов и заметок:

* Для расширения «Январь» в «Января», к «mmm» в строке формата нужно добавлять тильду (~) - см. пример выше.
* Если вместо mmm указать mm/m, то месяц будет отображаться в числовом виде.
* Если указать одну букву формата (d, m, или yy в случае с годом), то она будет представлена в одно-значном виде (для года в двух-значном).
 
Автор
S

Suppir

Продвинутый
Сообщения
967
Репутация
62
Супер! Потестирую на выходных, может что-то смогу добавить!
 

neu

Новичок
Сообщения
1
Репутация
0
Для того чтобы поиск месяца сделать универсальным рекомендую добавить StringInStr

Код:
For $i = 1 To $aMonths_Ru_Mod[0]
        If StringInStr ($sMonth, $aMonths_Ru_Mod[$i]) Then
            Return StringFormat('%.2i', $i)
        EndIf
 Next
 
Верх