Что нового

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

Suppir

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

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

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

kaster

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

Suppir

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


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

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

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

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


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

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

kaster

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

Yashied

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,670
Репутация
2,463
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
 
Верх