| author | Geoffrey Sneddon <geoffers@gmail.com> |
| Sun Aug 10 17:45:20 2008 +0200 (2 weeks ago) | |
| changeset 84 | 5a1173356865 |
| parent 68 | 7c579ee800fd |
| permissions | -rw-r--r-- |
1 <?php
3 /**
4 * Date Parser
5 *
6 * @package Date
7 */
8 class Parse_Date
9 {
10 /**
11 * Input data
12 *
13 * @var string
14 */
15 protected $date;
17 /**
18 * List of days, calendar day name => ordinal day number in the week
19 *
20 * @var array
21 */
22 protected $day = array(
23 // English
24 'mon' => 1,
25 'monday' => 1,
26 'tue' => 2,
27 'tuesday' => 2,
28 'wed' => 3,
29 'wednesday' => 3,
30 'thu' => 4,
31 'thursday' => 4,
32 'fri' => 5,
33 'friday' => 5,
34 'sat' => 6,
35 'saturday' => 6,
36 'sun' => 7,
37 'sunday' => 7,
38 // Dutch
39 'maandag' => 1,
40 'dinsdag' => 2,
41 'woensdag' => 3,
42 'donderdag' => 4,
43 'vrijdag' => 5,
44 'zaterdag' => 6,
45 'zondag' => 7,
46 // French
47 'lundi' => 1,
48 'mardi' => 2,
49 'mercredi' => 3,
50 'jeudi' => 4,
51 'vendredi' => 5,
52 'samedi' => 6,
53 'dimanche' => 7,
54 // German
55 'montag' => 1,
56 'dienstag' => 2,
57 'mittwoch' => 3,
58 'donnerstag' => 4,
59 'freitag' => 5,
60 'samstag' => 6,
61 'sonnabend' => 6,
62 'sonntag' => 7,
63 // Italian
64 'lunedì' => 1,
65 'martedì' => 2,
66 'mercoledì' => 3,
67 'giovedì' => 4,
68 'venerdì' => 5,
69 'sabato' => 6,
70 'domenica' => 7,
71 // Spanish
72 'lunes' => 1,
73 'martes' => 2,
74 'miércoles' => 3,
75 'jueves' => 4,
76 'viernes' => 5,
77 'sábado' => 6,
78 'domingo' => 7,
79 // Finnish
80 'maanantai' => 1,
81 'tiistai' => 2,
82 'keskiviikko' => 3,
83 'torstai' => 4,
84 'perjantai' => 5,
85 'lauantai' => 6,
86 'sunnuntai' => 7,
87 // Hungarian
88 'hétfő' => 1,
89 'kedd' => 2,
90 'szerda' => 3,
91 'csütörtok' => 4,
92 'péntek' => 5,
93 'szombat' => 6,
94 'vasárnap' => 7,
95 // Greek
96 'Δευ' => 1,
97 'Τρι' => 2,
98 'Τετ' => 3,
99 'Πεμ' => 4,
100 'Παρ' => 5,
101 'Σαβ' => 6,
102 'Κυρ' => 7,
103 );
105 /**
106 * List of months, calendar month name => calendar month number
107 *
108 * @var array
109 */
110 protected $month = array(
111 // English
112 'jan' => 1,
113 'january' => 1,
114 'feb' => 2,
115 'february' => 2,
116 'mar' => 3,
117 'march' => 3,
118 'apr' => 4,
119 'april' => 4,
120 'may' => 5,
121 // No long form of May
122 'jun' => 6,
123 'june' => 6,
124 'jul' => 7,
125 'july' => 7,
126 'aug' => 8,
127 'august' => 8,
128 'sep' => 9,
129 'september' => 8,
130 'oct' => 10,
131 'october' => 10,
132 'nov' => 11,
133 'november' => 11,
134 'dec' => 12,
135 'december' => 12,
136 // Dutch
137 'januari' => 1,
138 'februari' => 2,
139 'maart' => 3,
140 'april' => 4,
141 'mei' => 5,
142 'juni' => 6,
143 'juli' => 7,
144 'augustus' => 8,
145 'september' => 9,
146 'oktober' => 10,
147 'november' => 11,
148 'december' => 12,
149 // French
150 'janvier' => 1,
151 'février' => 2,
152 'mars' => 3,
153 'avril' => 4,
154 'mai' => 5,
155 'juin' => 6,
156 'juillet' => 7,
157 'août' => 8,
158 'septembre' => 9,
159 'octobre' => 10,
160 'novembre' => 11,
161 'décembre' => 12,
162 // German
163 'januar' => 1,
164 'februar' => 2,
165 'märz' => 3,
166 'april' => 4,
167 'mai' => 5,
168 'juni' => 6,
169 'juli' => 7,
170 'august' => 8,
171 'september' => 9,
172 'oktober' => 10,
173 'november' => 11,
174 'dezember' => 12,
175 // Italian
176 'gennaio' => 1,
177 'febbraio' => 2,
178 'marzo' => 3,
179 'aprile' => 4,
180 'maggio' => 5,
181 'giugno' => 6,
182 'luglio' => 7,
183 'agosto' => 8,
184 'settembre' => 9,
185 'ottobre' => 10,
186 'novembre' => 11,
187 'dicembre' => 12,
188 // Spanish
189 'enero' => 1,
190 'febrero' => 2,
191 'marzo' => 3,
192 'abril' => 4,
193 'mayo' => 5,
194 'junio' => 6,
195 'julio' => 7,
196 'agosto' => 8,
197 'septiembre' => 9,
198 'setiembre' => 9,
199 'octubre' => 10,
200 'noviembre' => 11,
201 'diciembre' => 12,
202 // Finnish
203 'tammikuu' => 1,
204 'helmikuu' => 2,
205 'maaliskuu' => 3,
206 'huhtikuu' => 4,
207 'toukokuu' => 5,
208 'kesäkuu' => 6,
209 'heinäkuu' => 7,
210 'elokuu' => 8,
211 'suuskuu' => 9,
212 'lokakuu' => 10,
213 'marras' => 11,
214 'joulukuu' => 12,
215 // Hungarian
216 'január' => 1,
217 'február' => 2,
218 'március' => 3,
219 'április' => 4,
220 'május' => 5,
221 'június' => 6,
222 'július' => 7,
223 'augusztus' => 8,
224 'szeptember' => 9,
225 'október' => 10,
226 'november' => 11,
227 'december' => 12,
228 // Greek
229 'Ιαν' => 1,
230 'Φεβ' => 2,
231 'Μάώ' => 3,
232 'Μαώ' => 3,
233 'Απρ' => 4,
234 'Μάι' => 5,
235 'Μαϊ' => 5,
236 'Μαι' => 5,
237 'Ιούν' => 6,
238 'Ιον' => 6,
239 'Ιούλ' => 7,
240 'Ιολ' => 7,
241 'Αύγ' => 8,
242 'Αυγ' => 8,
243 'Σεπ' => 9,
244 'Οκτ' => 10,
245 'Νοέ' => 11,
246 'Δεκ' => 12,
247 );
249 /**
250 * List of timezones, abbreviation => offset from UTC
251 *
252 * @var array
253 */
254 protected $timezone = array(
255 'ACDT' => 37800,
256 'ACIT' => 28800,
257 'ACST' => 34200,
258 'ACT' => -18000,
259 'ACWDT' => 35100,
260 'ACWST' => 31500,
261 'AEDT' => 39600,
262 'AEST' => 36000,
263 'AFT' => 16200,
264 'AKDT' => -28800,
265 'AKST' => -32400,
266 'AMDT' => 18000,
267 'AMT' => -14400,
268 'ANAST' => 46800,
269 'ANAT' => 43200,
270 'ART' => -10800,
271 'AZOST' => -3600,
272 'AZST' => 18000,
273 'AZT' => 14400,
274 'BIOT' => 21600,
275 'BIT' => -43200,
276 'BOT' => -14400,
277 'BRST' => -7200,
278 'BRT' => -10800,
279 'BST' => 3600,
280 'BTT' => 21600,
281 'CAST' => 18000,
282 'CAT' => 7200,
283 'CCT' => 23400,
284 'CDT' => -18000,
285 'CEDT' => 7200,
286 'CET' => 3600,
287 'CGST' => -7200,
288 'CGT' => -10800,
289 'CHADT' => 49500,
290 'CHAST' => 45900,
291 'CIST' => -28800,
292 'CKT' => -36000,
293 'CLDT' => -10800,
294 'CLST' => -14400,
295 'COT' => -18000,
296 'CST' => -21600,
297 'CVT' => -3600,
298 'CXT' => 25200,
299 'DAVT' => 25200,
300 'DTAT' => 36000,
301 'EADT' => -18000,
302 'EAST' => -21600,
303 'EAT' => 10800,
304 'ECT' => -18000,
305 'EDT' => -14400,
306 'EEST' => 10800,
307 'EET' => 7200,
308 'EGT' => -3600,
309 'EKST' => 21600,
310 'EST' => -18000,
311 'FJT' => 43200,
312 'FKDT' => -10800,
313 'FKST' => -14400,
314 'FNT' => -7200,
315 'GALT' => -21600,
316 'GEDT' => 14400,
317 'GEST' => 10800,
318 'GFT' => -10800,
319 'GILT' => 43200,
320 'GIT' => -32400,
321 'GST' => 14400,
322 'GST' => -7200,
323 'GYT' => -14400,
324 'HAA' => -10800,
325 'HAC' => -18000,
326 'HADT' => -32400,
327 'HAE' => -14400,
328 'HAP' => -25200,
329 'HAR' => -21600,
330 'HAST' => -36000,
331 'HAT' => -9000,
332 'HAY' => -28800,
333 'HKST' => 28800,
334 'HMT' => 18000,
335 'HNA' => -14400,
336 'HNC' => -21600,
337 'HNE' => -18000,
338 'HNP' => -28800,
339 'HNR' => -25200,
340 'HNT' => -12600,
341 'HNY' => -32400,
342 'IRDT' => 16200,
343 'IRKST' => 32400,
344 'IRKT' => 28800,
345 'IRST' => 12600,
346 'JFDT' => -10800,
347 'JFST' => -14400,
348 'JST' => 32400,
349 'KGST' => 21600,
350 'KGT' => 18000,
351 'KOST' => 39600,
352 'KOVST' => 28800,
353 'KOVT' => 25200,
354 'KRAST' => 28800,
355 'KRAT' => 25200,
356 'KST' => 32400,
357 'LHDT' => 39600,
358 'LHST' => 37800,
359 'LINT' => 50400,
360 'LKT' => 21600,
361 'MAGST' => 43200,
362 'MAGT' => 39600,
363 'MAWT' => 21600,
364 'MDT' => -21600,
365 'MESZ' => 7200,
366 'MEZ' => 3600,
367 'MHT' => 43200,
368 'MIT' => -34200,
369 'MNST' => 32400,
370 'MSDT' => 14400,
371 'MSST' => 10800,
372 'MST' => -25200,
373 'MUT' => 14400,
374 'MVT' => 18000,
375 'MYT' => 28800,
376 'NCT' => 39600,
377 'NDT' => -9000,
378 'NFT' => 41400,
379 'NMIT' => 36000,
380 'NOVST' => 25200,
381 'NOVT' => 21600,
382 'NPT' => 20700,
383 'NRT' => 43200,
384 'NST' => -12600,
385 'NUT' => -39600,
386 'NZDT' => 46800,
387 'NZST' => 43200,
388 'OMSST' => 25200,
389 'OMST' => 21600,
390 'PDT' => -25200,
391 'PET' => -18000,
392 'PETST' => 46800,
393 'PETT' => 43200,
394 'PGT' => 36000,
395 'PHOT' => 46800,
396 'PHT' => 28800,
397 'PKT' => 18000,
398 'PMDT' => -7200,
399 'PMST' => -10800,
400 'PONT' => 39600,
401 'PST' => -28800,
402 'PWT' => 32400,
403 'PYST' => -10800,
404 'PYT' => -14400,
405 'RET' => 14400,
406 'ROTT' => -10800,
407 'SAMST' => 18000,
408 'SAMT' => 14400,
409 'SAST' => 7200,
410 'SBT' => 39600,
411 'SCDT' => 46800,
412 'SCST' => 43200,
413 'SCT' => 14400,
414 'SEST' => 3600,
415 'SGT' => 28800,
416 'SIT' => 28800,
417 'SRT' => -10800,
418 'SST' => -39600,
419 'SYST' => 10800,
420 'SYT' => 7200,
421 'TFT' => 18000,
422 'THAT' => -36000,
423 'TJT' => 18000,
424 'TKT' => -36000,
425 'TMT' => 18000,
426 'TOT' => 46800,
427 'TPT' => 32400,
428 'TRUT' => 36000,
429 'TVT' => 43200,
430 'TWT' => 28800,
431 'UYST' => -7200,
432 'UYT' => -10800,
433 'UZT' => 18000,
434 'VET' => -14400,
435 'VLAST' => 39600,
436 'VLAT' => 36000,
437 'VOST' => 21600,
438 'VUT' => 39600,
439 'WAST' => 7200,
440 'WAT' => 3600,
441 'WDT' => 32400,
442 'WEST' => 3600,
443 'WFT' => 43200,
444 'WIB' => 25200,
445 'WIT' => 32400,
446 'WITA' => 28800,
447 'WKST' => 18000,
448 'WST' => 28800,
449 'YAKST' => 36000,
450 'YAKT' => 32400,
451 'YAPT' => 36000,
452 'YEKST' => 21600,
453 'YEKT' => 18000,
454 );
456 /**
457 * Cached PCRE for Parse_Date::$day
458 *
459 * @var string
460 */
461 protected $day_pcre;
463 /**
464 * Cached PCRE for Parse_Date::$month
465 *
466 * @var string
467 */
468 protected $month_pcre;
470 /**
471 * Array of user-added callback methods
472 *
473 * @var array
474 */
475 private $built_in = array();
477 /**
478 * Array of user-added callback methods
479 *
480 * @var array
481 */
482 private $user = array();
484 /**
485 * Create new Parse_Date object, with specific date string
486 *
487 * @param string $date Date string to parse
488 */
489 private function __construct()
490 {
491 $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
492 $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
494 static $cache;
495 if (!isset($cache[get_class($this)]))
496 {
497 if (extension_loaded('Reflection'))
498 {
499 $class = new ReflectionClass(get_class($this));
500 $methods = $class->getMethods();
501 $all_methods = array();
502 foreach ($methods as $method)
503 {
504 $all_methods[] = $method->getName();
505 }
506 }
507 else
508 {
509 $all_methods = get_class_methods($this);
510 }
512 foreach ($all_methods as $method)
513 {
514 if (stripos($method, 'date_') === 0)
515 {
516 $cache[get_class($this)][] = $method;
517 }
518 }
519 }
521 foreach ($cache[get_class($this)] as $method)
522 {
523 $this->built_in[] = $method;
524 }
525 }
527 /**
528 * Get the object
529 */
530 public function get()
531 {
532 static $object;
533 if (!$object)
534 {
535 $object = new Parse_Date;
536 }
537 return $object;
538 }
540 /**
541 * Parse the date
542 *
543 * @return int Timestamp corresponding to date string, or false on failure
544 */
545 final public function parse($date)
546 {
547 foreach ($this->user as $method)
548 {
549 if (($returned = call_user_func($method, $date)) !== false)
550 {
551 return $returned;
552 }
553 }
555 foreach ($this->built_in as $method)
556 {
557 if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
558 {
559 return $returned;
560 }
561 }
563 return false;
564 }
566 /**
567 * Add a callback method to parse a date
568 *
569 * @param callback $callback
570 */
571 final public function add_callback($callback)
572 {
573 if (is_callable($callback))
574 {
575 $this->user[] = $callback;
576 }
577 else
578 {
579 throw new Exception('Callback is not callable');
580 }
581 }
583 /**
584 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
585 * well as allowing any of upper or lower case "T", horizontal tabs, or
586 * spaces to be used as the time seperator (including more than one))
587 *
588 * @return int Timestamp
589 */
590 protected function date_w3cdtf($date)
591 {
592 static $pcre;
593 if (!$pcre)
594 {
595 $year = '([0-9]{4})';
596 $month = $day = $hour = $minute = $second = '([0-9]{2})';
597 $decimal = '([0-9]*)';
598 $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
599 $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
600 }
601 if (preg_match($pcre, $date, $match))
602 {
603 /*
604 Capturing subpatterns:
605 1: Year
606 2: Month
607 3: Day
608 4: Hour
609 5: Minute
610 6: Second
611 7: Decimal fraction of a second
612 8: Zulu
613 9: Timezone ±
614 10: Timezone hours
615 11: Timezone minutes
616 */
618 // Fill in empty matches
619 for ($i = count($match); $i <= 3; $i++)
620 {
621 $match[$i] = '1';
622 }
624 for ($i = count($match); $i <= 7; $i++)
625 {
626 $match[$i] = '0';
627 }
629 // Numeric timezone
630 if (isset($match[9]) && $match[9] !== '')
631 {
632 $timezone = $match[10] * 3600;
633 $timezone += $match[11] * 60;
634 if ($match[9] === '-')
635 {
636 $timezone = 0 - $timezone;
637 }
638 }
639 else
640 {
641 $timezone = 0;
642 }
644 // Convert the number of seconds to an integer, taking decimals into account
645 $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
647 return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
648 }
649 else
650 {
651 return false;
652 }
653 }
655 /**
656 * Remove RFC822 comments
657 *
658 * @param string $data Data to strip comments from
659 * @return string Comment stripped string
660 */
661 protected function remove_rfc2822_comments($string)
662 {
663 $string = (string) $string;
664 $position = 0;
665 $length = strlen($string);
666 $depth = 0;
668 $output = '';
670 while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
671 {
672 $output .= substr($string, $position, $pos - $position);
673 $position = $pos + 1;
674 if ($string[$pos - 1] !== '\\')
675 {
676 $depth++;
677 while ($depth && $position < $length)
678 {
679 $position += strcspn($string, '()', $position);
680 if ($string[$position - 1] === '\\')
681 {
682 $position++;
683 continue;
684 }
685 elseif (isset($string[$position]))
686 {
687 switch ($string[$position])
688 {
689 case '(':
690 $depth++;
691 break;
693 case ')':
694 $depth--;
695 break;
696 }
697 $position++;
698 }
699 else
700 {
701 break;
702 }
703 }
704 }
705 else
706 {
707 $output .= '(';
708 }
709 }
710 $output .= substr($string, $position);
712 return $output;
713 }
715 /**
716 * Parse RFC2822's date format
717 *
718 * @return int Timestamp
719 */
720 protected function date_rfc2822($date)
721 {
722 static $pcre;
723 if (!$pcre)
724 {
725 $wsp = '[\x09\x20]';
726 $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
727 $optional_fws = $fws . '?';
728 $day_name = $this->day_pcre;
729 $month = $this->month_pcre;
730 $day = '([0-9]{1,2})';
731 $hour = $minute = $second = '([0-9]{2})';
732 $year = '([0-9]{2,4})';
733 $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
734 $character_zone = '([A-Z]{1,5})';
735 $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
736 $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
737 }
738 if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
739 {
740 /*
741 Capturing subpatterns:
742 1: Day name
743 2: Day
744 3: Month
745 4: Year
746 5: Hour
747 6: Minute
748 7: Second
749 8: Timezone ±
750 9: Timezone hours
751 10: Timezone minutes
752 11: Alphabetic timezone
753 */
755 // Find the month number
756 $month = $this->month[strtolower($match[3])];
758 // Numeric timezone
759 if ($match[8] !== '')
760 {
761 $timezone = $match[9] * 3600;
762 $timezone += $match[10] * 60;
763 if ($match[8] === '-')
764 {
765 $timezone = 0 - $timezone;
766 }
767 }
768 // Character timezone
769 elseif (isset($this->timezone[strtoupper($match[11])]))
770 {
771 $timezone = $this->timezone[strtoupper($match[11])];
772 }
773 // Assume everything else to be -0000
774 else
775 {
776 $timezone = 0;
777 }
779 // Deal with 2/3 digit years
780 if ($match[4] < 50)
781 {
782 $match[4] += 2000;
783 }
784 elseif ($match[4] < 1000)
785 {
786 $match[4] += 1900;
787 }
789 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
790 }
791 else
792 {
793 return false;
794 }
795 }
797 /**
798 * Parse RFC850's date format
799 *
800 * @return int Timestamp
801 */
802 protected function date_rfc850($date)
803 {
804 static $pcre;
805 if (!$pcre)
806 {
807 $space = '[\x09\x20]+';
808 $day_name = $this->day_pcre;
809 $month = $this->month_pcre;
810 $day = '([0-9]{1,2})';
811 $year = $hour = $minute = $second = '([0-9]{2})';
812 $zone = '([A-Z]{1,5})';
813 $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
814 }
815 if (preg_match($pcre, $date, $match))
816 {
817 /*
818 Capturing subpatterns:
819 1: Day name
820 2: Day
821 3: Month
822 4: Year
823 5: Hour
824 6: Minute
825 7: Second
826 8: Timezone
827 */
829 // Month
830 $month = $this->month[strtolower($match[3])];
832 // Character timezone
833 if (isset($this->timezone[strtoupper($match[8])]))
834 {
835 $timezone = $this->timezone[strtoupper($match[8])];
836 }
837 // Assume everything else to be -0000
838 else
839 {
840 $timezone = 0;
841 }
843 // Deal with 2 digit year
844 if ($match[4] < 50)
845 {
846 $match[4] += 2000;
847 }
848 else
849 {
850 $match[4] += 1900;
851 }
853 return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
854 }
855 else
856 {
857 return false;
858 }
859 }
861 /**
862 * Parse C99's asctime()'s date format
863 *
864 * @return int Timestamp
865 */
866 protected function date_asctime($date)
867 {
868 static $pcre;
869 if (!$pcre)
870 {
871 $space = '[\x09\x20]+';
872 $wday_name = $this->day_pcre;
873 $mon_name = $this->month_pcre;
874 $day = '([0-9]{1,2})';
875 $hour = $sec = $min = '([0-9]{2})';
876 $year = '([0-9]{4})';
877 $terminator = '\x0A?\x00?';
878 $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
879 }
880 if (preg_match($pcre, $date, $match))
881 {
882 /*
883 Capturing subpatterns:
884 1: Day name
885 2: Month
886 3: Day
887 4: Hour
888 5: Minute
889 6: Second
890 7: Year
891 */
893 $month = $this->month[strtolower($match[2])];
894 return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
895 }
896 else
897 {
898 return false;
899 }
900 }
902 /**
903 * Parse dates using strtotime()
904 *
905 * @return int Timestamp
906 */
907 protected function date_strtotime($date)
908 {
909 $strtotime = strtotime($date);
910 if ($strtotime === -1 || $strtotime === false)
911 {
912 return false;
913 }
914 else
915 {
916 return $strtotime;
917 }
918 }