Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/**
4
 * NumberFormatInfo class file.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the BSD License.
8
 *
9
 * Copyright(c) 2004 by Qiang Xue. All rights reserved.
10
 *
11
 * To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue}
12
 * The latest version of PRADO can be obtained from:
13
 * {@link http://prado.sourceforge.net/}
14
 *
15
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
16
 * @version $Revision: 1.3 $  $Date: 2005/08/04 05:27:19 $
17
 * @package System.I18N.core
18
 */
19
 
20
/**
21
 * Get the CultureInfo class file.
22
 */
23
require_once(dirname(__FILE__).'/CultureInfo.php');
24
 
25
/**
26
 * NumberFormatInfo class
27
 *
28
 * Defines how numeric values are formatted and displayed,
29
 * depending on the culture. Numeric values are formatted using
30
 * standard or custom patterns stored in the properties of a
31
 * NumberFormatInfo.
32
 *
33
 * This class contains information, such as currency, decimal
34
 * separators, and other numeric symbols.
35
 *
36
 * To create a NumberFormatInfo for a specific culture,
37
 * create a CultureInfo for that culture and retrieve the
38
 * CultureInfo->NumberFormat property. Or use
39
 * NumberFormatInfo::getInstance($culture).
40
 * To create a NumberFormatInfo for the invariant culture, use the
41
 * InvariantInfo::getInvariantInfo().
42
 *
43
 *
44
 * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
45
 * @version v1.0, last update on Sun Dec 05 14:48:26 EST 2004
46
 * @package System.I18N.core
47
 */
48
class NumberFormatInfo
49
{
50
 
51
	/**
52
	 * ICU number formatting data.
53
	 * @var array
54
	 */
55
	private $data = array();
56
 
57
	/**
58
	 * A list of properties that are accessable/writable.
59
	 * @var array
60
	 */
61
	protected $properties = array();
62
 
63
	/**
64
	 * The number pattern.
65
	 * @var array
66
	 */
67
	protected $pattern = array();
68
 
69
	const DECIMAL = 0;
70
	const CURRENCY = 1;
71
	const PERCENTAGE = 2;
72
	const SCIENTIFIC = 3;
73
 
74
	/**
75
	 * Allow functions that begins with 'set' to be called directly
76
	 * as an attribute/property to retrieve the value.
77
	 * @return mixed
78
	 */
79
	public function __get($name)
80
	{
81
		$getProperty = 'get'.$name;
82
		if(in_array($getProperty, $this->properties))
83
			return $this->$getProperty();
84
		else
85
			throw new Exception('Property '.$name.' does not exists.');
86
	}
87
 
88
	/**
89
	 * Allow functions that begins with 'set' to be called directly
90
	 * as an attribute/property to set the value.
91
	 */
92
	public function __set($name, $value)
93
	{
94
		$setProperty = 'set'.$name;
95
		if(in_array($setProperty, $this->properties))
96
			$this->$setProperty($value);
97
		else
98
			throw new Exception('Property '.$name.' can not be set.');
99
	}
100
 
101
	/**
102
	 * Initializes a new writable instance of the NumberFormatInfo class
103
	 * that is dependent on the ICU data for number, decimal, and currency
104
	 * formatting information. <b>N.B.</b>You should not initialize this
105
	 * class directly unless you know what you are doing. Please use use
106
	 * NumberFormatInfo::getInstance() to create an instance.
107
	 * @param array ICU data for date time formatting.
108
	 * @see getInstance()
109
	 */
110
	public function __construct($data=array(), $type=NumberFormatInfo::DECIMAL)
111
	{
112
		$this->properties = get_class_methods($this);
113
 
114
		if(empty($data))
115
			throw new Exception('Please provide the ICU data to initialize.');
116
 
117
		$this->data = $data;
118
 
119
		$this->setPattern($type);
120
	}
121
 
122
	/**
123
	 * Set the pattern for a specific number pattern. The validate patterns
124
	 * NumberFormatInfo::DECIMAL, NumberFormatInfo::CURRENCY,
125
     * NumberFormatInfo::PERCENTAGE, or NumberFormatInfo::SCIENTIFIC
126
	 * @param int pattern type.
127
	 */
128
	public function setPattern($type=NumberFormatInfo::DECIMAL)
129
	{
130
		if(is_int($type))
131
			$this->pattern =
132
				$this->parsePattern($this->data['NumberPatterns'][$type]);
133
		else
134
			$this->pattern = $this->parsePattern($type);
135
 
136
		$this->pattern['negInfty'] =
137
			$this->data['NumberElements'][6].
138
			$this->data['NumberElements'][9];
139
 
140
		$this->pattern['posInfty'] =
141
			$this->data['NumberElements'][11].
142
			$this->data['NumberElements'][9];
143
	}
144
 
145
	public function getPattern()
146
	{
147
		return $this->pattern;
148
	}
149
 
150
	/**
151
	 * Gets the default NumberFormatInfo that is culture-independent
152
	 * (invariant).
153
	 * @return NumberFormatInfo default NumberFormatInfo.
154
	 */
155
    public static function getInvariantInfo($type=NumberFormatInfo::DECIMAL)
156
    {
157
        static $invariant;
158
		if($invariant === null)
159
        {
160
            $culture = CultureInfo::getInvariantCulture();
161
            $invariant = $culture->NumberFormat;
162
            $invariant->setPattern($type);
163
        }
164
		return $invariant;
165
    }
166
 
167
    /**
168
     * Returns the NumberFormatInfo associated with the specified culture.
169
     * @param CultureInfo the culture that gets the NumberFormat property.
170
     * @param int the number formatting type, it should be
171
     * NumberFormatInfo::DECIMAL, NumberFormatInfo::CURRENCY,
172
     * NumberFormatInfo::PERCENTAGE, or NumberFormatInfo::SCIENTIFIC
173
     * @return NumberFormatInfo NumberFormatInfo for the specified
174
     * culture.
175
     * @see getCurrencyInstance();
176
     * @see getPercentageInstance();
177
     * @see getScientificInstance();
178
     */
179
    public static function getInstance($culture=null,
180
    								   $type=NumberFormatInfo::DECIMAL)
181
    {
182
   		if ($culture instanceof CultureInfo)
183
   		{
184
            $formatInfo = $culture->NumberFormat;
185
            $formatInfo->setPattern($type);
186
            return $formatInfo;
187
   		}
188
       	else if(is_string($culture))
189
       	{
190
       		$cultureInfo = new CultureInfo($culture);
191
       		$formatInfo = $cultureInfo->NumberFormat;
192
       		$formatInfo->setPattern($type);
193
       		return $formatInfo;
194
       	}
195
       	else
196
       	{
197
            $cultureInfo = new CultureInfo();
198
       		$formatInfo = $cultureInfo->NumberFormat;
199
       		$formatInfo->setPattern($type);
200
       		return $formatInfo;
201
       	}
202
    }
203
 
204
    /**
205
     * Returns the currency format info associated with the specified culture.
206
     * @param CultureInfo the culture that gets the NumberFormat property.
207
     * @return NumberFormatInfo NumberFormatInfo for the specified
208
     * culture.
209
     */
210
    public static function getCurrencyInstance($culture=null)
211
    {
212
        return self::getInstance($culture, self::CURRENCY);
213
    }
214
 
215
    /**
216
     * Returns the percentage format info associated with the specified culture.
217
     * @param CultureInfo the culture that gets the NumberFormat property.
218
     * @return NumberFormatInfo NumberFormatInfo for the specified
219
     * culture.
220
     */
221
    public static function getPercentageInstance($culture=null)
222
    {
223
        return self::getInstance($culture, self::PERCENTAGE);
224
    }
225
 
226
    /**
227
     * Returns the scientific format info associated with the specified culture.
228
     * @param CultureInfo the culture that gets the NumberFormat property.
229
     * @return NumberFormatInfo NumberFormatInfo for the specified
230
     * culture.
231
     */
232
    public static function getScientificInstance($culture=null)
233
    {
234
        return self::getInstance($culture, self::SCIENTIFIC);
235
    }
236
 
237
    /**
238
     * Parse the given pattern and return a list of known properties.
239
     * @param string a number pattern.
240
     * @return array list of pattern properties.
241
     */
242
    protected function parsePattern($pattern)
243
	{
244
		$pattern = explode(';',$pattern);
245
 
246
		$negative = null;
247
		if(count($pattern) > 1)
248
			$negative = $pattern[1];
249
		$pattern = $pattern[0];
250
 
251
		$comma = ',';
252
		$dot = '.';
253
		$digit = '0';
254
		$hash = '#';
255
 
256
		//find the first group point, and decimal point
257
		$groupPos1 = strrpos($pattern,$comma);
258
		$decimalPos = strrpos($pattern,$dot);
259
 
260
		$groupPos2 = false;
261
		$groupSize1 = false;
262
		$groupSize2 = false;
263
		$decimalPoints = is_int($decimalPos)?-1:false;
264
 
265
		$info['negPref'] = $this->data['NumberElements'][6];
266
		$info['negPost'] = '';
267
 
268
		$info['negative'] = $negative;
269
		$info['positive'] = $pattern;
270
 
271
		//find the negative prefix and postfix
272
		if($negative)
273
		{
274
			$prefixPostfix = $this->getPrePostfix($negative);
275
			$info['negPref'] = $prefixPostfix[0];
276
			$info['negPost'] = $prefixPostfix[1];
277
		}
278
 
279
		$posfix = $this->getPrePostfix($pattern);
280
		$info['posPref'] = $posfix[0];
281
		$info['posPost'] = $posfix[1];
282
 
283
		//var_dump($pattern);
284
		//var_dump($decimalPos);
285
		if(is_int($groupPos1))
286
		{
287
			//get the second group
288
			$groupPos2 = strrpos(substr($pattern,0,$groupPos1),$comma);
289
 
290
			//get the number of decimal digits
291
			if(is_int($decimalPos))
292
			{
293
				$groupSize1 = $decimalPos - $groupPos1-1;
294
 
295
			}
296
			else
297
			{
298
				//no decimal point, so traverse from the back
299
				//to find the groupsize 1.
300
				for($i=strlen($pattern)-1; $i>=0; $i--)
301
				{
302
					if($pattern{$i} == $digit || $pattern{$i}==$hash)
303
					{
304
						$groupSize1 = $i - $groupPos1;
305
						break;
306
					}
307
				}
308
			}
309
 
310
			//get the second group size
311
			if(is_int($groupPos2))
312
				$groupSize2 = $groupPos1 - $groupPos2-1;
313
		}
314
 
315
		if(is_int($decimalPos))
316
		{
317
			for($i=strlen($pattern)-1; $i>=0; $i--)
318
			{
319
				if($pattern{$i} == $dot) break;
320
				if($pattern{$i} == $digit)
321
				{
322
					$decimalPoints = $i - $decimalPos;
323
					break;
324
				}
325
			}
326
		}
327
 
328
		if(is_int($decimalPos))
329
			$digitPattern = substr($pattern,0,$decimalPos);
330
		else
331
			$digitPattern  = $pattern;
332
 
333
		$digitPattern  = preg_replace('/[^0]/','',$digitPattern);
334
 
335
		$info['groupPos1'] = $groupPos1;
336
		$info['groupSize1'] = $groupSize1;
337
		$info['groupPos2'] = $groupPos2;
338
		$info['groupSize2'] = $groupSize2;
339
		$info['decimalPos'] = $decimalPos;
340
		$info['decimalPoints'] = $decimalPoints;
341
		$info['digitSize'] = strlen($digitPattern);
342
		return $info;
343
	}
344
 
345
	/**
346
	 * Get the prefix and postfix of a pattern.
347
	 * @param string pattern
348
	 * @return array of prefix and postfix, array(prefix,postfix).
349
	 */
350
	protected function getPrePostfix($pattern)
351
	{
352
		$regexp = '/[#,\.0]+/';
353
		$result = preg_split($regexp, $pattern);
354
		return array($result[0],$result[1]);
355
	}
356
 
357
 
358
    /**
359
     * Indicates the number of decimal places.
360
     * @return int number of decimal places.
361
     */
362
    function getDecimalDigits()
363
    {
364
    	return $this->pattern['decimalPoints'];
365
    }
366
 
367
    /**
368
     * Set the number of decimal places.
369
     * @param int number of decimal places.
370
     */
371
    function setDecimalDigits($value)
372
    {
373
    	return $this->pattern['decimalPoints'] = $value;
374
    }
375
 
376
    function getDigitSize()
377
    {
378
    	return $this->pattern['digitSize'];
379
    }
380
 
381
    function setDigitSize($value)
382
    {
383
    	$this->pattern['digitSize'] = $value;
384
    }
385
 
386
    /**
387
     * Gets the string to use as the decimal separator.
388
     * @return string decimal separator.
389
     */
390
    function getDecimalSeparator()
391
    {
392
    	return $this->data['NumberElements'][0];
393
    }
394
 
395
    /**
396
     * Set the string to use as the decimal separator.
397
     * @param string the decimal point
398
     */
399
    function setDecimalSeparator($value)
400
    {
401
    	return $this->data['NumberElements'][0] = $value;
402
    }
403
 
404
    /**
405
     * Gets the string that separates groups of digits to the left
406
     * of the decimal in currency values.
407
     * @param parameter
408
     * @return string currency group separator.
409
     */
410
    function getGroupSeparator()
411
    {
412
    	return $this->data['NumberElements'][1];
413
    }
414
 
415
    /**
416
     * Set the string to use as the group separator.
417
     * @param string the group separator.
418
     */
419
    function setGroupSeparator($value)
420
    {
421
    	return $this->data['NumberElements'][1] = $value;
422
    }
423
 
424
    /**
425
     * Gets the number of digits in each group to the left of the decimal
426
     * There can be two grouping sizes, this fucntion
427
     * returns <b>array(group1, group2)</b>, if there is only 1 grouping size,
428
     * group2 will be false.
429
     * @return array grouping size(s).
430
     */
431
    function getGroupSizes()
432
    {
433
    	$group1 = $this->pattern['groupSize1'];
434
    	$group2 = $this->pattern['groupSize2'];
435
 
436
    	return array($group1, $group2);
437
    }
438
 
439
    /**
440
     * Set the number of digits in each group to the left of the decimal.
441
     * There can be two grouping sizes, the value should
442
     * be an <b>array(group1, group2)</b>, if there is only 1 grouping size,
443
     * group2 should be false.
444
     * @param array grouping size(s).
445
     */
446
    function setGroupSizes($groupSize)
447
    {
448
   		$this->pattern['groupSize1'] = $groupSize[0];
449
   		$this->pattern['groupSize2'] = $groupSize[1];
450
    }
451
 
452
    /**
453
     * Gets the format pattern for negative values.
454
     * The negative pattern is composed of a prefix, and postfix.
455
     * This function returns <b>array(prefix, postfix)</b>.
456
     * @return arary negative pattern.
457
     */
458
    function getNegativePattern()
459
    {
460
    	$prefix = $this->pattern['negPref'];
461
    	$postfix = $this->pattern['negPost'];
462
    	return array($prefix, $postfix);
463
    }
464
 
465
    /**
466
     * Set the format pattern for negative values.
467
     * The negative pattern is composed of a prefix, and postfix in the form
468
     * <b>array(prefix, postfix)</b>.
469
     * @param arary negative pattern.
470
     */
471
    function setNegativePattern($pattern)
472
    {
473
    	$this->pattern['negPref'] = $pattern[0];
474
    	$this->pattern['negPost'] = $pattern[1];
475
    }
476
 
477
    /**
478
     * Gets the format pattern for positive values.
479
     * The positive pattern is composed of a prefix, and postfix.
480
     * This function returns <b>array(prefix, postfix)</b>.
481
     * @return arary positive pattern.
482
     */
483
    function getPositivePattern()
484
    {
485
    	$prefix = $this->pattern['posPref'];
486
    	$postfix = $this->pattern['posPost'];
487
    	return array($prefix, $postfix);
488
    }
489
 
490
    /**
491
     * Set the format pattern for positive values.
492
     * The positive pattern is composed of a prefix, and postfix in the form
493
     * <b>array(prefix, postfix)</b>.
494
     * @param arary positive pattern.
495
     */
496
    function setPositivePattern($pattern)
497
    {
498
    	$this->pattern['posPref'] = $pattern[0];
499
    	$this->pattern['posPost'] = $pattern[1];
500
    }
501
 
502
    /**
503
     * Gets the string to use as the currency symbol.
504
     * @return string currency symbol.
505
     */
506
    function getCurrencySymbol($currency='USD')
507
    {
508
    	if(isset($this->pattern['symbol']))
509
			return $this->pattern['symbol'];
510
    	else
511
    		return $this->data['Currencies'][$currency][0];
512
    }
513
 
514
 
515
    /**
516
     * Set the string to use as the currency symbol.
517
     * @param string currency symbol.
518
     */
519
    function setCurrencySymbol($symbol)
520
    {
521
    	$this->pattern['symbol'] = $symbol;
522
    }
523
 
524
    /**
525
     * Gets the string that represents negative infinity.
526
     * @return string negative infinity.
527
     */
528
    function getNegativeInfinitySymbol()
529
    {
530
		return $this->pattern['negInfty'];
531
    }
532
 
533
    /**
534
     * Set the string that represents negative infinity.
535
     * @param string negative infinity.
536
     */
537
    function setNegativeInfinitySymbol($value)
538
    {
539
		$this->pattern['negInfty'] = $value;
540
    }
541
 
542
    /**
543
     * Gets the string that represents positive infinity.
544
     * @return string positive infinity.
545
     */
546
    function getPositiveInfinitySymbol()
547
    {
548
		return $this->pattern['posInfty'];
549
    }
550
 
551
    /**
552
     * Set the string that represents positive infinity.
553
     * @param string positive infinity.
554
     */
555
    function setPositiveInfinitySymbol($value)
556
    {
557
		$this->pattern['posInfty'] = $value;
558
    }
559
 
560
    /**
561
     * Gets the string that denotes that the associated number is negative.
562
     * @return string negative sign.
563
     */
564
    function getNegativeSign()
565
    {
566
    	return $this->data['NumberElements'][6];
567
    }
568
 
569
    /**
570
     * Set the string that denotes that the associated number is negative.
571
     * @param string negative sign.
572
     */
573
    function setNegativeSign($value)
574
    {
575
    	$this->data['NumberElements'][6] = $value;
576
    }
577
 
578
    /**
579
     * Gets the string that denotes that the associated number is positive.
580
     * @return string positive sign.
581
     */
582
    function getPositiveSign()
583
    {
584
    	return $this->data['NumberElements'][11];
585
    }
586
 
587
    /**
588
     * Set the string that denotes that the associated number is positive.
589
     * @param string positive sign.
590
     */
591
    function setPositiveSign($value)
592
    {
593
    	$this->data['NumberElements'][11] = $value;
594
    }
595
 
596
    /**
597
     * Gets the string that represents the IEEE NaN (not a number) value.
598
     * @return string NaN symbol.
599
     */
600
    function getNaNSymbol()
601
    {
602
    	return $this->data['NumberElements'][10];
603
    }
604
 
605
    /**
606
     * Set the string that represents the IEEE NaN (not a number) value.
607
     * @param string NaN symbol.
608
     */
609
    function setNaNSymbol($value)
610
    {
611
    	$this->data['NumberElements'][10] = $value;
612
    }
613
 
614
    /**
615
     * Gets the string to use as the percent symbol.
616
     * @return string percent symbol.
617
     */
618
    function getPercentSymbol()
619
    {
620
    	return $this->data['NumberElements'][3];
621
    }
622
 
623
    /**
624
     * Set the string to use as the percent symbol.
625
     * @param string percent symbol.
626
     */
627
    function setPercentSymbol($value)
628
    {
629
    	$this->data['NumberElements'][3] = $value;
630
    }
631
 
632
    /**
633
     * Gets the string to use as the per mille symbol.
634
     * @return string percent symbol.
635
     */
636
    function getPerMilleSymbol()
637
    {
638
    	return $this->data['NumberElements'][8];
639
    }
640
 
641
    /**
642
     * Set the string to use as the per mille symbol.
643
     * @param string percent symbol.
644
     */
645
    function setPerMilleSymbol($value)
646
    {
647
    	$this->data['NumberElements'][8] = $value;
648
    }
649
}
650