]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/framework/I18N/core/DateFormat.php
Add Baculum
[bacula/bacula] / gui / baculum / framework / I18N / core / DateFormat.php
1 <?php
2 /**
3  * DateFormat class file.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the BSD License.
7  *
8  * Copyright(c) 2004 by Qiang Xue. All rights reserved.
9  *
10  * To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue}
11  * The latest version of PRADO can be obtained from:
12  * {@link http://prado.sourceforge.net/}
13  *
14  * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
15  * @version $Revision: 1.8 $  $Date: 2005/12/15 07:14:49 $
16  * @package System.I18N.core
17  */
18
19 /**
20  * Get the DateTimeFormatInfo class.
21  */
22 require_once(dirname(__FILE__).'/DateTimeFormatInfo.php');
23
24 /**
25  * Get the encoding utilities
26  */
27 require_once(dirname(__FILE__).'/util.php');
28
29 /**
30  * DateFormat class.
31  *
32  * The DateFormat class allows you to format dates and times with
33  * predefined styles in a locale-sensitive manner. Formatting times
34  * with the DateFormat class is similar to formatting dates.
35  *
36  * Formatting dates with the DateFormat class is a two-step process.
37  * First, you create a formatter with the getDateInstance method.
38  * Second, you invoke the format method, which returns a string containing
39  * the formatted date.
40  *
41  * DateTime values are formatted using standard or custom patterns stored
42  * in the properties of a DateTimeFormatInfo.
43  *
44  * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
45  * @version v1.0, last update on Sat Dec 04 14:10:49 EST 2004
46  * @package System.I18N.core
47  */
48 class DateFormat
49 {
50         /**
51          * A list of tokens and their function call.
52          * @var array
53          */
54         protected $tokens = array(
55                         'G'=>'Era',
56                         'y'=>'Year',
57                         'M'=>'Month',
58                         'd'=>'Day',
59                         'h'=>'Hour12',
60                         'H'=>'Hour24',
61                         'm'=>'Minutes',
62                         's'=>'Seconds',
63                         'E'=>'DayInWeek',
64                         'D'=>'DayInYear',
65                         'F'=>'DayInMonth',
66                         'w'=>'WeekInYear',
67                         'W'=>'WeekInMonth',
68                         'a'=>'AMPM',
69                         'k'=>'HourInDay',
70                         'K'=>'HourInAMPM',
71                         'z'=>'TimeZone'
72                         );
73
74         /**
75          * A list of methods, to be used by the token function calls.
76          * @var array
77          */
78         protected $methods = array();
79
80         /**
81          * The DateTimeFormatInfo, containing culture specific patterns and names.
82          * @var DateTimeFormatInfo
83          */
84         protected $formatInfo;
85
86         /**
87          * Initialize a new DateFormat.
88          * @param mixed either, null, a CultureInfo instance,
89          * a DateTimeFormatInfo instance, or a locale.
90          * @return DateFormat instance
91          */
92         function __construct($formatInfo=null)
93         {
94                 if($formatInfo === null)
95                         $this->formatInfo = DateTimeFormatInfo::getInvariantInfo();
96                 else if($formatInfo instanceof CultureInfo)
97                         $this->formatInfo = $formatInfo->DateTimeFormat;
98                 else if($formatInfo instanceof DateTimeFormatInfo)
99                         $this->formatInfo = $formatInfo;
100                 else
101                         $this->formatInfo = DateTimeFormatInfo::getInstance($formatInfo);
102
103                 $this->methods = get_class_methods($this);
104         }
105
106         /**
107          * Format a date according to the pattern.
108          * @param mixed the time as integer or string in strtotime format.
109          * @return string formatted date time.
110          */
111         public function format($time, $pattern='F', $charset='UTF-8')
112         {
113                 if (is_numeric($time)) //assumes unix epoch
114                         $time = floatval($time);
115                 else if(is_string($time))
116                         $time = @strtotime($time);
117
118                 if($pattern === null)
119                         $pattern = 'F';
120
121                 $s = Prado::createComponent('System.Util.TDateTimeStamp');
122
123                 $date = $s->getDate($time);
124
125                 $pattern = $this->getPattern($pattern);
126
127                 $tokens = $this->getTokens($pattern);
128
129                 for($i = 0, $k = count($tokens); $i<$k; ++$i)
130                 {
131                         $pattern = $tokens[$i];
132                         if($pattern{0} == "'"
133                                 && $pattern{strlen($pattern)-1} == "'")
134                         {
135                                 $sub = preg_replace('/(^\')|(\'$)/','',$pattern);
136                                 $tokens[$i] =  str_replace('``````','\'',$sub);
137                         }
138                         else if($pattern == '``````')
139                         {
140                                 $tokens[$i] = '\'';
141                         }
142                         else
143                         {
144                                 $function = $this->getFunctionName($pattern);
145                                 if($function != null)
146                                 {
147                                         $fName = 'get'.$function;
148                                         if(in_array($fName, $this->methods))
149                                         {
150                                                 $rs = $this->$fName($date, $pattern);
151                                                 $tokens[$i] = $rs;
152                                         }
153                                         else
154                                                 throw new
155                                                 Exception('function '.$function.' not found.');
156                                 }
157                         }                       
158                 }
159
160                 return I18N_toEncoding(implode('',$tokens), $charset);
161         }
162
163         /**
164          * For a particular token, get the corresponding function to call.
165          * @param string token
166          * @return mixed the function if good token, null otherwise.
167          */
168         protected function getFunctionName($token)
169         {
170                 if(isset($this->tokens[$token{0}]))
171                         return $this->tokens[$token{0}];
172         }
173
174         /**
175          * Get the pattern from DateTimeFormatInfo or some predefined patterns.
176          * If the $pattern parameter is an array of 2 element, it will assume
177          * that the first element is the date, and second the time
178          * and try to find an appropriate pattern and apply
179          * DateTimeFormatInfo::formatDateTime
180          * See the tutorial documentation for futher details on the patterns.
181          * @param mixed a pattern.
182          * @return string a pattern.
183          * @see DateTimeFormatInfo::formatDateTime()
184          */
185         protected function getPattern($pattern)
186         {
187                 if(is_array($pattern) && count($pattern) == 2)
188                 {
189                         return $this->formatInfo->formatDateTime(
190                                                         $this->getPattern($pattern[0]),
191                                                         $this->getPattern($pattern[1]));
192                 }
193
194                 switch($pattern)
195                 {
196                         case 'd':
197                                 return $this->formatInfo->ShortDatePattern;
198                                 break;
199                         case 'D':
200                                 return $this->formatInfo->LongDatePattern;
201                                 break;
202                         case 'p':
203                                 return $this->formatInfo->MediumDatePattern;
204                                 break;
205                         case 'P':
206                                 return $this->formatInfo->FullDatePattern;
207                                 break;
208                         case 't':
209                                 return $this->formatInfo->ShortTimePattern;
210                                 break;
211                         case 'T':
212                                 return $this->formatInfo->LongTimePattern;
213                                 break;
214                         case 'q':
215                                 return $this->formatInfo->MediumTimePattern;
216                                 break;
217                         case 'Q':
218                                 return $this->formatInfo->FullTimePattern;
219                                 break;
220                         case 'f':
221                                 return $this->formatInfo->formatDateTime(
222                                         $this->formatInfo->LongDatePattern,
223                                         $this->formatInfo->ShortTimePattern);
224                                 break;
225                         case 'F':
226                                 return $this->formatInfo->formatDateTime(
227                                         $this->formatInfo->LongDatePattern,
228                                         $this->formatInfo->LongTimePattern);
229                                 break;
230                         case 'g':
231                                 return $this->formatInfo->formatDateTime(
232                                         $this->formatInfo->ShortDatePattern,
233                                         $this->formatInfo->ShortTimePattern);
234                                 break;
235                         case 'G':
236                                 return $this->formatInfo->formatDateTime(
237                                         $this->formatInfo->ShortDatePattern,
238                                         $this->formatInfo->LongTimePattern);
239                                 break;
240                         case 'M':
241                         case 'm':
242                                 return 'MMMM dd';
243                                 break;
244                         case 'R':
245                         case 'r':
246                                 return 'EEE, dd MMM yyyy HH:mm:ss';
247                                 break;
248                         case 's':
249                                 return 'yyyy-MM-ddTHH:mm:ss';
250                                 break;
251                         case 'u':
252                                 return 'yyyy-MM-dd HH:mm:ss z';
253                                 break;
254                         case 'U':
255                                 return 'EEEE dd MMMM yyyy HH:mm:ss';
256                                 break;
257                         case 'Y':
258                         case 'y':
259                                 return 'yyyy MMMM';
260                                 break;
261                         default :
262                                 return $pattern;
263                 }
264         }
265
266         /**
267          * Tokenize the pattern. The tokens are delimited by group of
268          * similar characters, e.g. 'aabb' will form 2 tokens of 'aa' and 'bb'.
269          * Any substrings, starting and ending with a single quote (')
270          * will be treated as a single token.
271          * @param string pattern.
272          * @return array string tokens in an array.
273          */
274         protected function getTokens($pattern)
275         {
276                 $char = null;
277                 $tokens = array();
278                 $token = null;
279
280                 $text = false;
281                 $pattern = preg_replace("/''/", '``````', $pattern);
282
283                 for($i = 0; $i < strlen($pattern); $i++)
284                 {
285                         if($char==null || $pattern{$i} == $char || $text)
286                         {
287                                 $token .= $pattern{$i};
288                         }
289                         else
290                         {
291                                 $tokens[] = str_replace("","'",$token);
292                                 $token = $pattern{$i};
293                         }
294
295                         if($pattern{$i} == "'" && $text == false)
296                                 $text = true;
297                         else if($text && $pattern{$i} == "'" && $char == "'")
298                                 $text = true;
299                         else if($text && $char != "'" && $pattern{$i} == "'")
300                                 $text = false;
301
302                         $char = $pattern{$i};
303
304                 }
305                 $tokens[] = $token;
306                 return $tokens;
307         }
308
309         /**
310          * Get the year.
311          * "yy" will return the last two digits of year.
312          * "yyyy" will return the full integer year.
313          * @param array getdate format.
314          * @param string a pattern.
315          * @return string year
316          */
317         protected function getYear($date, $pattern='yyyy')
318         {
319                 $year = $date['year'];
320                 switch($pattern)
321                 {
322                         case 'yy':
323                                 return substr($year,2);
324                         case 'yyyy':
325                                 return $year;
326                         default:
327                                 throw new Exception('The pattern for year is either "yy" or "yyyy".');
328                 }
329         }
330
331         /**
332          * Get the month.
333          * "M" will return integer 1 through 12
334          * "MM" will return the narrow month name, e.g. "J"
335          * "MMM" will return the abrreviated month name, e.g. "Jan"
336          * "MMMM" will return the month name, e.g. "January"
337          * @param array getdate format.
338          * @param string a pattern.
339          * @return string month name
340          */
341         protected function getMonth($date, $pattern='M')
342         {
343                 $month = $date['mon'];
344
345                 switch($pattern)
346                 {
347                         case 'M':
348                                 return $month;
349                         case 'MM':
350                                 return str_pad($month, 2,'0',STR_PAD_LEFT);
351                         case 'MMM':
352                                 return $this->formatInfo->AbbreviatedMonthNames[$month-1];
353                                 break;
354                         case 'MMMM':
355                                 return $this->formatInfo->MonthNames[$month-1];
356                         default:
357                                 throw new Exception('The pattern for month '.
358                                                 'is "M", "MM", "MMM", or "MMMM".');
359                 }
360         }
361
362         /**
363          * Get the day of the week.
364          * "E" will return integer 0 (for Sunday) through 6 (for Saturday).
365          * "EE" will return the narrow day of the week, e.g. "M"
366          * "EEE" will return the abrreviated day of the week, e.g. "Mon"
367          * "EEEE" will return the day of the week, e.g. "Monday"
368          * @param array getdate format.
369          * @param string a pattern.
370          * @return string day of the week.
371          */
372         protected function getDayInWeek($date, $pattern='EEEE')
373         {
374                 $day = $date['wday'];
375
376                 switch($pattern)
377                 {
378                         case 'E':
379                                 return $day;
380                                 break;
381                         case 'EE':
382                                 return $this->formatInfo->NarrowDayNames[$day];
383                         case 'EEE':
384                                 return $this->formatInfo->AbbreviatedDayNames[$day];
385                                 break;
386                         case 'EEEE':
387                                 return $this->formatInfo->DayNames[$day];
388                                 break;
389                         default:
390                                 throw new Exception('The pattern for day of the week '.
391                                                 'is "E", "EE", "EEE", or "EEEE".');
392                 }
393         }
394
395         /**
396          * Get the day of the month.
397          * "d" for non-padding, "dd" will always return 2 characters.
398          * @param array getdate format.
399          * @param string a pattern.
400          * @return string day of the month
401          */
402         protected function getDay($date, $pattern='d')
403         {
404                 $day = $date['mday'];
405
406                 switch($pattern)
407                 {
408                         case 'd':
409                                 return $day;
410                         case 'dd':
411                                 return str_pad($day, 2,'0',STR_PAD_LEFT);
412                         default:
413                                 throw new Exception('The pattern for day of '.
414                                                 'the month is "d" or "dd".');
415                 }
416         }
417
418
419         /**
420          * Get the era. i.e. in gregorian, year > 0 is AD, else BC.
421          * @todo How to support multiple Eras?, e.g. Japanese.
422          * @param array getdate format.
423          * @param string a pattern.
424          * @return string era
425          */
426         protected function getEra($date, $pattern='G')
427         {
428
429                 if($pattern != 'G')
430                         throw new Exception('The pattern for era is "G".');
431
432                 $year = $date['year'];
433                 if($year > 0)
434                         return $this->formatInfo->getEra(1);
435                 else
436                         return $this->formatInfo->getEra(0);
437         }
438
439         /**
440          * Get the hours in 24 hour format, i.e. [0-23].
441          * "H" for non-padding, "HH" will always return 2 characters.
442          * @param array getdate format.
443          * @param string a pattern.
444          * @return string hours in 24 hour format.
445          */
446         protected function getHour24($date, $pattern='H')
447         {
448                 $hour = $date['hours'];
449
450                 switch($pattern)
451                 {
452                         case 'H':
453                                 return $hour;
454                         case 'HH':
455                                 return str_pad($hour, 2,'0',STR_PAD_LEFT);
456                         default:
457                                 throw new Exception('The pattern for 24 hour '.
458                                                 'format is "H" or "HH".');
459                 }
460         }
461
462         /**
463          * Get the AM/PM designator, 12 noon is PM, 12 midnight is AM.
464          * @param array getdate format.
465          * @param string a pattern.
466          * @return string AM or PM designator
467          */
468         protected function getAMPM($date, $pattern='a')
469         {
470                 if($pattern != 'a')
471                         throw new Exception('The pattern for AM/PM marker is "a".');
472
473                 $hour = $date['hours'];
474                 $ampm = (int)($hour/12);
475                 return $this->formatInfo->AMPMMarkers[$ampm];
476         }
477
478         /**
479          * Get the hours in 12 hour format.
480          * "h" for non-padding, "hh" will always return 2 characters.
481          * @param array getdate format.
482          * @param string a pattern.
483          * @return string hours in 12 hour format.
484          */
485         protected function getHour12($date, $pattern='h')
486         {
487                 $hour = $date['hours'];
488                 $hour = ($hour==12|$hour==0)?12:($hour)%12;
489
490                 switch($pattern)
491                 {
492                         case 'h':
493                                 return $hour;
494                         case 'hh':
495                                 return str_pad($hour, 2,'0',STR_PAD_LEFT);
496                         default:
497                                 throw new Exception('The pattern for 24 hour '.
498                                                 'format is "H" or "HH".');
499                 }
500         }
501
502         /**
503          * Get the minutes.
504          * "m" for non-padding, "mm" will always return 2 characters.
505          * @param array getdate format.
506          * @param string a pattern.
507          * @return string minutes.
508          */
509         protected function getMinutes($date, $pattern='m')
510         {
511                 $minutes = $date['minutes'];
512
513                 switch($pattern)
514                 {
515                         case 'm':
516                                 return $minutes;
517                         case 'mm':
518                                 return str_pad($minutes, 2,'0',STR_PAD_LEFT);
519                         default:
520                         throw new Exception('The pattern for minutes is "m" or "mm".');
521                 }
522         }
523
524         /**
525          * Get the seconds.
526          * "s" for non-padding, "ss" will always return 2 characters.
527          * @param array getdate format.
528          * @param string a pattern.
529          * @return string seconds
530          */
531         protected function getSeconds($date, $pattern='s')
532         {
533                 $seconds = $date['seconds'];
534
535                 switch($pattern)
536                 {
537                         case 's':
538                                 return $seconds;
539                         case 'ss':
540                                 return str_pad($seconds, 2,'0',STR_PAD_LEFT);
541                         default:
542                         throw new Exception('The pattern for seconds is "s" or "ss".');
543                 }
544         }
545
546         /**
547          * Get the timezone from the server machine.
548          * @todo How to get the timezone for a different region?
549          * @param array getdate format.
550          * @param string a pattern.
551          * @return string time zone
552          */
553         protected function getTimeZone($date, $pattern='z')
554         {
555                 if($pattern != 'z')
556                         throw new Exception('The pattern for time zone is "z".');
557
558                 return @date('T', @mktime($date['hours'], $date['minutes'], $date['seconds'], $date['mon'], $date['mday'], $date['year']));
559         }
560
561         /**
562          * Get the day in the year, e.g. [1-366]
563          * @param array getdate format.
564          * @param string a pattern.
565          * @return int hours in AM/PM format.
566          */
567         protected function getDayInYear($date, $pattern='D')
568         {
569                 if($pattern != 'D')
570                         throw new Exception('The pattern for day in year is "D".');
571
572                 return $date['yday'];
573         }
574
575         /**
576          * Get day in the month.
577          * @param array getdate format.
578          * @param string a pattern.
579          * @return int day in month
580          */
581         protected function getDayInMonth($date, $pattern='FF')
582         {
583                 switch ($pattern) {
584                     case 'F':
585                       return @date('j', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
586                       break;
587                     case 'FF':
588                       return @date('d', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
589                       break;
590                     default:
591                       throw new Exception('The pattern for day in month is "F" or "FF".');
592                 }
593         }
594
595         /**
596          * Get the week in the year.
597          * @param array getdate format.
598          * @param string a pattern.
599          * @return int week in year
600          */
601         protected function getWeekInYear($date, $pattern='w')
602         {
603                 if($pattern != 'w')
604                         throw new Exception('The pattern for week in year is "w".');
605
606                 return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year']));
607         }
608
609         /**
610          * Get week in the month.
611          * @param array getdate format.
612          * @return int week in month
613          */
614         protected function getWeekInMonth($date, $pattern='W')
615         {
616                 if($pattern != 'W')
617                         throw new Exception('The pattern for week in month is "W".');
618
619                 return @date('W', @mktime(0, 0, 0, $date['mon'], $date['mday'], $date['year'])) - date('W', mktime(0, 0, 0, $date['mon'], 1, $date['year']));
620         }
621
622         /**
623          * Get the hours [1-24].
624          * @param array getdate format.
625          * @param string a pattern.
626          * @return int hours [1-24]
627          */
628         protected function getHourInDay($date, $pattern='k')
629         {
630                 if($pattern != 'k')
631                         throw new Exception('The pattern for hour in day is "k".');
632
633                 return $date['hours']+1;
634         }
635
636         /**
637          * Get the hours in AM/PM format, e.g [1-12]
638          * @param array getdate format.
639          * @param string a pattern.
640          * @return int hours in AM/PM format.
641          */
642         protected function getHourInAMPM($date, $pattern='K')
643         {
644                 if($pattern != 'K')
645                         throw new Exception('The pattern for hour in AM/PM is "K".');
646
647                 return ($date['hours']+1)%12;
648         }
649
650 }
651