parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

2 Misha v.3 предложение по классу dtf.p

Эдуард Габдуллин 02.05.2006 00:21

Пытаясь использовать RSS каналы на своем сайте долго и упорно бился с датами, функция from822 класса dtf.p упорно не хотела принимать даты форматов:
1 May 2006 19:00:00 MSK;
Mon, 1 May 2006 19:00:00 +0400

пришлось немного дорабатывать данную функцию напильником:
###########################################################################
# $Id: dtf.p,v 1.21 2005/10/20 17:26:14 misha Exp $
#
# доступны методы:
# @create[date;default]					из строки/даты конструирует объект типа date
# @format[fmt;date;locale]				выводит полученную date, используя форматную строку
# @last-day[date]						возвращает дату последнего дня заданного[текущего] месяца
# @from822[string]						создает дату из переданной строки-даты в формате RFC822
# @to822[date;timezone]					сдвигает дату из текущей TZ в указанную TZ и выводит её в виде строки в формате RFC822
# @setLocale[locale]					задает новое значение locale, возвращая старое
# @resetLocale[]						сбрасывает locale в default
#
###########################################################################


###########################################################################
# принимает в строку-дату в формате RFC822 и создает из неё объект типа date
# still under construction/testing.
@from822[string][_tmp;_fields;_name;_k;_v;_d2;_diff]
^try{
	^if(!def $string){
		^throw[dtf.from822;Empty date]
	}
#	$_tmp[^string.match[(?:([a-z]{3}),\s+)?(\d{1,2})\s+([a-z]{3})\s+(\d{4}|\d{2})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})\s+(\w{3,5})?|(?:\s*([-+]?\d{1,2}(\d{2})?))?][i]]
	$_tmp[^string.match[(?:([a-z]{3}),\s+)?(\d{1,2})\s+([a-z]{3})\s+(\d{4}|\d{2})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})\s+(\w{3,5})?(?:\s*([-+]?\d{1,2})(\d{2})?)?][i]]
	^if($_tmp){
#		^if(^_tmp.1.match[\D]){
			$_fields[
				$.weekday_name[$_tmp.1]
				$.day($_tmp.2)
				$.month(0)
				$.month_name[$_tmp.3]
				$.year($_tmp.4)
				$.hour($_tmp.5)
				$.min($_tmp.6)
				$.sec($_tmp.7)
				$.tz[$_tmp.8]
				$.offset_hour[$_tmp.9]
				$.offset_min[$_tmp.10]
			]
#		}{
#			$_fields[
#				$.weekday_name[]
#				$.day($_tmp.1)
#				$.month(0)
#				$.month_name[$_tmp.2]
#				$.year($_tmp.3)
#				$.hour($_tmp.4)
#				$.min($_tmp.5)
#				$.sec($_tmp.6)
#				$.tz[$_tmp.7]
#				$.offset_hour[$_tmp.8]
#				$.offset_min[$_tmp.9]
#			]
#		}
		^rem{ *** check month abbr *** }
		$_name[^_fields.month_name.lower[]]
		^es-locale.month.foreach[_k;_v]{
			^if(^_v.lower[] eq $_name){
				$_fields.month($_k)
			}
		}
		^if(!$_fields.month){
			^throw[dtf.from822;Unknown month '$_fields.month_name']
		}

		^if(def $_fields.offset_hour && !def $_fields.tz){
			$_fields.tz[GMT]
		}
		
		$result[^date::create($_fields.year;$_fields.month;$_fields.day;$_fields.hour;$_fields.min;$_fields.sec)]

		^rem{ *** check weekday abbr *** }
		^if(def $_fields.weekday_name){
			^if(^_fields.weekday_name.lower[] ne ^es-locale.weekday.[$result.weekday].lower[]){
				^throw[dtf.from822;Incorrect day of week '$_fields.weekday_name' in RFC822 date (must be '$es-locale.weekday.[$result.weekday]')]
			}
		}
		
		^rem{ *** roll time to timezone *** }
		^if(def $tz.[$_fields.tz]){
			$_d2[^date::create($result)]
			^_d2.roll[TZ;$tz.[$_fields.tz]]
			$_diff(^date::create($_d2.year;$_d2.month;$_d2.day;$_d2.hour;$_d2.minute;$_d2.second) - $result)
			$result[^date::create($_d2 - $_diff)]
		}
		
		^rem{ *** apply timezone offset *** }
		^if(def $_fields.offset_hour){
#			$result[^date::create($result - ($_fields.offset_hour + ^_fields.offset_min.int(0) / 60) / 24)]
#			Вносим поправку на летнее время
			$result[^date::create($result - ($_fields.offset_hour + ^_fields.offset_min.int(0) / 60 - ^result.daylightsaving.int(0)) / 24)]
		}
	}{
		^throw[dtf.from822;Wrong RFC822 date format]
	}
}{
	^if($exception.type ne "dtf.from822"){
		$exception.handled(1)
		^throw[dtf.from822;Can't create date (${_fields.year}-${_fields.month}-$_fields.day ${_fields.hour}:${_fields.min}:${_fields.sec}).]
	}
}
#end @from822[]
теперь принимаются даты:
Mon, 1 May 2006 19:00:00 MSK;
Mon, 1 May 2006 19:00:00 +0400;
1 May 2006 19:00:00 MSK;
1 May 2006 19:00:00 +0400;

с учетом перехода на летнее время.