Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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
 
652
?>