source: branches/feature-module-update/data/module/SOAP/Type/duration.php @ 16957

Revision 16957, 5.9 KB checked in by naka, 16 years ago (diff)

PEAR::SOAPモジュールアップ

Line 
1<?php
2/*
3http://www.w3.org/TR/xmlschema-2/
4
5[Definition:]   duration represents a duration of time. The value space of
6duration is a six-dimensional space where the coordinates designate the
7Gregorian year, month, day, hour, minute, and second components
8defined in  5.5.3.2 of [ISO 8601], respectively. These components are
9ordered in their significance by their order of appearance i.e. as year,
10month, day, hour, minute, and second.
11
123.2.6.1 Lexical representation
13The lexical representation for duration is the [ISO 8601] extended
14format PnYn MnDTnH nMnS, where nY represents the number of
15years, nM the number of months, nD the number of days, 'T' is the
16date/time separator, nH the number of hours, nM the number of
17minutes and nS the number of seconds. The number of seconds
18can include decimal digits to arbitrary precision.
19
20The values of the Year, Month, Day, Hour and Minutes components
21are not restricted but allow an arbitrary integer. Similarly, the
22value of the Seconds component allows an arbitrary decimal.
23Thus, the lexical representation of duration does not follow the
24alternative format of  5.5.3.2.1 of [ISO 8601].
25
26An optional preceding minus sign ('-') is allowed, to indicate a
27negative duration. If the sign is omitted a positive duration is
28indicated. See also ISO 8601 Date and Time Formats (D).
29
30For example, to indicate a duration of 1 year, 2 months, 3 days,
3110 hours, and 30 minutes, one would write: P1Y2M3DT10H30M.
32One could also indicate a duration of minus 120 days as: -P120D.
33
34Reduced precision and truncated representations of this format
35are allowed provided they conform to the following:
36
37If the number of years, months, days, hours, minutes, or seconds
38in any expression equals zero, the number and its corresponding
39designator *may* be omitted. However, at least one number and
40its designator *must* be present.
41The seconds part *may* have a decimal fraction.
42The designator 'T' shall be absent if all of the time items are absent.
43The designator 'P' must always be present.
44For example, P1347Y, P1347M and P1Y2MT2H are all allowed; P0Y1347M
45and P0Y1347M0D are allowed. P-1347M is not allowed although -P1347M
46is allowed. P1Y2MT is not allowed.
47
48*/
49
50/* this is only an aproximation of duration, more work still to do.
51   see above schema url for more info on duration
52   
53   TODO: figure out best aproximation for year and month conversion to seconds
54*/
55   
56$ereg_duration = '(-)?P([0-9]+Y)?([0-9]+M)?([0-9]+D)?T?([0-9]+H)?([0-9]+M)?([0-9]+S)?';
57class SOAP_Type_duration
58{
59    // format PnYnMnDTnHnMnS
60    function unix_to_duration($seconds) {
61        return SOAP_Type_duration::getduration($seconds);
62    }
63   
64    function mod($a, $b, &$d, &$r) {
65        $d = floor( $a / $b );
66        $r = $a % $b;
67    }
68   
69    function getduration($seconds) {
70        $neg = '';
71        if ($seconds < 0) {
72            $neg = '-';
73            $seconds = $seconds * -1;
74        }
75       
76        $_mi = 60;
77        $_h = $_mi * 60;
78        $_d = $_h * 24;
79        // XXX how do we properly handle month and year values?
80        $_m = $_d * 30;
81        $_y = $_d * 365;
82
83        SOAP_Type_duration::mod($seconds, $_y, $y, $seconds);
84        SOAP_Type_duration::mod($seconds, $_m, $m, $seconds);
85        SOAP_Type_duration::mod($seconds, $_d, $d, $seconds);
86        SOAP_Type_duration::mod($seconds, $_h, $h, $seconds);
87        SOAP_Type_duration::mod($seconds, $_mi, $mi, $s);
88       
89        $duration = $neg.'P';
90        if ($y) $duration .= $y.'Y';
91        if ($m) $duration .= $m.'M';
92        if ($d) $duration .= $d.'D';
93        if ($h || $mi || $s) $duration .='T';
94        if ($h) $duration .= $h.'H';
95        if ($mi) $duration .= $mi.'M';
96        if ($s) $duration .= $s.'S';
97        if ($duration == 'P' || $duration == '-P') $duration = 'PT0S';
98        return $duration;
99    }
100   
101    function mkduration($n, $Y, $Mo, $D, $H, $Mi, $S) {
102        $_mi = 60;
103        $_h = $_mi * 60;
104        $_d = $_h * 24;
105        // XXX how do we properly handle month and year values?
106        $_m = $_d * 30;
107        $_y = $_d * 365;
108       
109        $sec = $Y * $_y + $Mo * $_m + $D * $_d + $H * $_h + $Mi * $_mi + $S;
110        if ($n == '-') $sec = $sec * -1;
111        return $sec;
112    }
113   
114    function duration_to_unix($duration) {
115        global $ereg_duration;
116        if (ereg($ereg_duration,$duration,$regs)) {
117            return SOAP_Type_duration::mkduration($regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6], $regs[7]);
118        }
119        return FALSE;
120    }
121   
122    function is_duration($duration) {
123        global $ereg_duration;
124        return ereg($ereg_duration,$duration,$regs);
125    }
126   
127    function _test($time) {
128        if (SOAP_Type_duration::is_duration($time)) {
129            $t = SOAP_Type_duration::duration_to_unix($time);
130            echo "Duration: $time is ".$t." seconds\n";
131        } else {
132            $t = SOAP_Type_duration::unix_to_duration($time);
133            echo "Seconds: $time is ".$t." duration\n";
134        }
135        return $t;
136    }
137   
138    function add($d1, $d2) {
139        $s1 = SOAP_Type_duration::duration_to_unix($d1);
140        $s2 = SOAP_Type_duration::duration_to_unix($d2);
141        return SOAP_Type_duration::unix_to_duration($s1 + $s2);
142    }
143   
144    function subtract($d1, $d2) {
145        $s1 = SOAP_Type_duration::duration_to_unix($d1);
146        $s2 = SOAP_Type_duration::duration_to_unix($d2);
147        return SOAP_Type_duration::unix_to_duration($s1 - $s2);
148    }
149
150}
151
152/* tests */
153
154$t = SOAP_Type_duration::_test('P1Y2M3DT10H30M');
155SOAP_Type_duration::_test($t);
156$t = SOAP_Type_duration::_test('-P120D');
157SOAP_Type_duration::_test($t);
158
159// duration since 1970
160$t = SOAP_Type_duration::_test(time());
161SOAP_Type_duration::_test($t);
162
163print "Add should be PT0S: ".SOAP_Type_duration::add('-P120D','P4M')."\n";
164print "Subtract should be PT0S: ".SOAP_Type_duration::subtract('P120D','P4M')."\n";
165?>
Note: See TracBrowser for help on using the repository browser.