3 <!-- This is a public domain script released from http://exslt.org/ -->
5 <xsl:stylesheet version=
"1.0"
6 xmlns:
xsl=
"http://www.w3.org/1999/XSL/Transform"
7 xmlns:
date=
"http://exslt.org/dates-and-times"
8 extension-element-prefixes=
"date">
11 <date:month>31</date:month>
12 <date:month>28</date:month>
13 <date:month>31</date:month>
14 <date:month>30</date:month>
15 <date:month>31</date:month>
16 <date:month>30</date:month>
17 <date:month>31</date:month>
18 <date:month>31</date:month>
19 <date:month>30</date:month>
20 <date:month>31</date:month>
21 <date:month>30</date:month>
22 <date:month>31</date:month>
25 <xsl:template name=
"date:add">
26 <xsl:param name=
"date-time" />
27 <xsl:param name=
"duration" />
28 <xsl:variable name=
"dt-neg" select=
"starts-with($date-time, '-')" />
29 <xsl:variable name=
"dt-no-neg">
31 <xsl:when test=
"$dt-neg or starts-with($date-time, '+')">
32 <xsl:value-of select=
"substring($date-time, 2)" />
35 <xsl:value-of select=
"$date-time" />
39 <xsl:variable name=
"dt-no-neg-length" select=
"string-length($dt-no-neg)" />
40 <xsl:variable name=
"timezone">
42 <xsl:when test=
"substring($dt-no-neg, $dt-no-neg-length) = 'Z'">Z
</xsl:when>
44 <xsl:variable name=
"tz" select=
"substring($dt-no-neg, $dt-no-neg-length - 5)" />
45 <xsl:if test=
"(substring($tz, 1, 1) = '-' or
46 substring($tz, 1, 1) = '+') and
47 substring($tz, 4, 1) = ':'">
48 <xsl:value-of select=
"$tz" />
53 <xsl:variable name=
"new-dt">
54 <xsl:if test=
"not(string($timezone)) or
56 (substring($timezone, 2, 2) <= 23 and
57 substring($timezone, 5, 2) <= 59)">
58 <xsl:variable name=
"dt" select=
"substring($dt-no-neg, 1, $dt-no-neg-length - string-length($timezone))" />
59 <xsl:variable name=
"dt-length" select=
"string-length($dt)" />
60 <xsl:variable name=
"du-neg" select=
"starts-with($duration, '-')" />
61 <xsl:variable name=
"du">
63 <xsl:when test=
"$du-neg"><xsl:value-of select=
"substring($duration, 2)" /></xsl:when>
64 <xsl:otherwise><xsl:value-of select=
"$duration" /></xsl:otherwise>
67 <xsl:if test=
"starts-with($du, 'P') and
68 not(translate($du, '0123456789PYMDTHS.', ''))">
69 <xsl:variable name=
"du-date">
71 <xsl:when test=
"contains($du, 'T')"><xsl:value-of select=
"substring-before(substring($du, 2), 'T')" /></xsl:when>
72 <xsl:otherwise><xsl:value-of select=
"substring($du, 2)" /></xsl:otherwise>
75 <xsl:variable name=
"du-time">
76 <xsl:if test=
"contains($du, 'T')"><xsl:value-of select=
"substring-after($du, 'T')" /></xsl:if>
78 <xsl:if test=
"(not($du-date) or
79 (not(translate($du-date, '0123456789YMD', '')) and
80 not(substring-after($du-date, 'D')) and
81 (contains($du-date, 'D') or
82 (not(substring-after($du-date, 'M')) and
83 (contains($du-date, 'M') or
84 not(substring-after($du-date, 'Y'))))))) and
86 (not(translate($du-time, '0123456789HMS.', '')) and
87 not(substring-after($du-time, 'S')) and
88 (contains($du-time, 'S') or
89 not(substring-after($du-time, 'M')) and
90 (contains($du-time, 'M') or
91 not(substring-after($du-time, 'Y'))))))">
92 <xsl:variable name=
"duy-str">
94 <xsl:when test=
"contains($du-date, 'Y')"><xsl:value-of select=
"substring-before($du-date, 'Y')" /></xsl:when>
95 <xsl:otherwise>0</xsl:otherwise>
98 <xsl:variable name=
"dum-str">
100 <xsl:when test=
"contains($du-date, 'M')">
102 <xsl:when test=
"contains($du-date, 'Y')"><xsl:value-of select=
"substring-before(substring-after($du-date, 'Y'), 'M')" /></xsl:when>
103 <xsl:otherwise><xsl:value-of select=
"substring-before($du-date, 'M')" /></xsl:otherwise>
106 <xsl:otherwise>0</xsl:otherwise>
109 <xsl:variable name=
"dud-str">
111 <xsl:when test=
"contains($du-date, 'D')">
113 <xsl:when test=
"contains($du-date, 'M')"><xsl:value-of select=
"substring-before(substring-after($du-date, 'M'), 'D')" /></xsl:when>
114 <xsl:when test=
"contains($du-date, 'Y')"><xsl:value-of select=
"substring-before(substring-after($du-date, 'Y'), 'D')" /></xsl:when>
115 <xsl:otherwise><xsl:value-of select=
"substring-before($du-date, 'D')" /></xsl:otherwise>
118 <xsl:otherwise>0</xsl:otherwise>
121 <xsl:variable name=
"duh-str">
123 <xsl:when test=
"contains($du-time, 'H')"><xsl:value-of select=
"substring-before($du-time, 'H')" /></xsl:when>
124 <xsl:otherwise>0</xsl:otherwise>
127 <xsl:variable name=
"dumin-str">
129 <xsl:when test=
"contains($du-time, 'M')">
131 <xsl:when test=
"contains($du-time, 'H')"><xsl:value-of select=
"substring-before(substring-after($du-time, 'H'), 'M')" /></xsl:when>
132 <xsl:otherwise><xsl:value-of select=
"substring-before($du-time, 'M')" /></xsl:otherwise>
135 <xsl:otherwise>0</xsl:otherwise>
138 <xsl:variable name=
"dus-str">
140 <xsl:when test=
"contains($du-time, 'S')">
142 <xsl:when test=
"contains($du-time, 'M')"><xsl:value-of select=
"substring-before(substring-after($du-time, 'M'), 'S')" /></xsl:when>
143 <xsl:when test=
"contains($du-time, 'H')"><xsl:value-of select=
"substring-before(substring-after($du-time, 'H'), 'S')" /></xsl:when>
144 <xsl:otherwise><xsl:value-of select=
"substring-before($du-time, 'S')" /></xsl:otherwise>
147 <xsl:otherwise>0</xsl:otherwise>
150 <xsl:variable name=
"mult" select=
"($du-neg * -2) + 1" />
151 <xsl:variable name=
"duy" select=
"$duy-str * $mult" />
152 <xsl:variable name=
"dum" select=
"$dum-str * $mult" />
153 <xsl:variable name=
"dud" select=
"$dud-str * $mult" />
154 <xsl:variable name=
"duh" select=
"$duh-str * $mult" />
155 <xsl:variable name=
"dumin" select=
"$dumin-str * $mult" />
156 <xsl:variable name=
"dus" select=
"$dus-str * $mult" />
158 <xsl:variable name=
"year" select=
"substring($dt, 1, 4) * (($dt-neg * -2) + 1)" />
160 <xsl:when test=
"$year and
161 string($duy) = 'NaN' or
162 string($dum) = 'NaN' or
163 string($dud) = 'NaN' or
164 string($duh) = 'NaN' or
165 string($dumin) = 'NaN' or
166 string($dus) = 'NaN'" />
167 <xsl:when test=
"$dt-length > 4 or
168 $dum or $dud or $duh or $dumin or $dus">
169 <xsl:variable name=
"month">
171 <xsl:when test=
"$dt-length > 4">
172 <xsl:if test=
"substring($dt, 5, 1) = '-'">
173 <xsl:value-of select=
"substring($dt, 6, 2)" />
176 <xsl:otherwise>1</xsl:otherwise>
180 <xsl:when test=
"not($month) or $month > 12" />
181 <xsl:when test=
"$dt-length > 7 or
182 $dud or $duh or $dumin or $dus">
183 <xsl:variable name=
"day">
185 <xsl:when test=
"$dt-length > 7">
186 <xsl:if test=
"substring($dt, 8, 1) = '-'">
187 <xsl:value-of select=
"substring($dt, 9, 2)" />
190 <xsl:otherwise>1</xsl:otherwise>
194 <xsl:when test=
"not($day) or $day > 31" />
195 <xsl:when test=
"$dt-length > 10 or
196 $duh or $dumin or $dus">
197 <xsl:if test=
"$dt-length = 10 or
198 (substring($dt, 11, 1) = 'T' and
199 substring($dt, 14, 1) = ':' and
200 substring($dt, 17, 1) = ':')">
201 <xsl:variable name=
"hour">
203 <xsl:when test=
"$dt-length > 10"><xsl:value-of select=
"substring($dt, 12, 2)" /></xsl:when>
204 <xsl:otherwise>0</xsl:otherwise>
207 <xsl:variable name=
"minute">
209 <xsl:when test=
"$dt-length > 10"><xsl:value-of select=
"substring($dt, 15, 2)" /></xsl:when>
210 <xsl:otherwise>0</xsl:otherwise>
213 <xsl:variable name=
"second">
215 <xsl:when test=
"$dt-length > 10"><xsl:value-of select=
"substring($dt, 18)" /></xsl:when>
216 <xsl:otherwise>0</xsl:otherwise>
219 <xsl:if test=
"$hour <= 23 and $minute <= 59 and $second <= 60">
220 <xsl:variable name=
"new-second" select=
"$second + $dus" />
221 <xsl:variable name=
"new-minute" select=
"$minute + $dumin + floor($new-second div 60)" />
222 <xsl:variable name=
"new-hour" select=
"$hour + $duh + floor($new-minute div 60)" />
223 <xsl:variable name=
"new-month" select=
"$month + $dum" />
224 <xsl:call-template name=
"date:_add-days">
225 <xsl:with-param name=
"year" select=
"$year + $duy + floor(($new-month - 1) div 12)" />
226 <xsl:with-param name=
"month">
227 <xsl:variable name=
"m">
229 <xsl:when test=
"$new-month < 1"><xsl:value-of select=
"$new-month + 12" /></xsl:when>
230 <xsl:otherwise><xsl:value-of select=
"$new-month" /></xsl:otherwise>
234 <xsl:when test=
"$m mod 12">
235 <xsl:value-of select=
"format-number($m mod 12, '00')" />
237 <xsl:otherwise>12</xsl:otherwise>
240 <xsl:with-param name=
"day" select=
"$day" />
241 <xsl:with-param name=
"days" select=
"$dud + floor($new-hour div 24)" />
243 <xsl:text>T
</xsl:text>
244 <xsl:value-of select=
"format-number(($new-hour + 24) mod 24, '00')" />
245 <xsl:text>:
</xsl:text>
246 <xsl:value-of select=
"format-number($new-minute mod 60, '00')" />
247 <xsl:text>:
</xsl:text>
248 <xsl:if test=
"$new-second mod 60 < 10">0</xsl:if>
249 <xsl:value-of select=
"$new-second mod 60" />
250 <xsl:value-of select=
"$timezone" />
255 <xsl:variable name=
"new-month" select=
"$month + $dum" />
256 <xsl:call-template name=
"date:_add-days">
257 <xsl:with-param name=
"year" select=
"$year + $duy + floor(($new-month - 1) div 12)" />
258 <xsl:with-param name=
"month">
259 <xsl:variable name=
"m">
261 <xsl:when test=
"$new-month < 1"><xsl:value-of select=
"$new-month + 12" /></xsl:when>
262 <xsl:otherwise><xsl:value-of select=
"$new-month" /></xsl:otherwise>
266 <xsl:when test=
"$m mod 12">
267 <xsl:value-of select=
"format-number($m mod 12, '00')" />
269 <xsl:otherwise>12</xsl:otherwise>
272 <xsl:with-param name=
"day" select=
"$day" />
273 <xsl:with-param name=
"days" select=
"$dud" />
275 <xsl:value-of select=
"$timezone" />
280 <xsl:variable name=
"new-month" select=
"$month + $dum" />
281 <xsl:value-of select=
"format-number($year + $duy + floor(($new-month - 1) div 12), '0000')" />
282 <xsl:text>-
</xsl:text>
283 <xsl:variable name=
"m">
285 <xsl:when test=
"$new-month < 1"><xsl:value-of select=
"$new-month + 12" /></xsl:when>
286 <xsl:otherwise><xsl:value-of select=
"$new-month" /></xsl:otherwise>
290 <xsl:when test=
"$m mod 12">
291 <xsl:value-of select=
"format-number($m mod 12, '00')" />
293 <xsl:otherwise>12</xsl:otherwise>
295 <xsl:value-of select=
"$timezone" />
300 <xsl:value-of select=
"format-number($year + $duy, '0000')" />
301 <xsl:value-of select=
"$timezone" />
309 <xsl:when test=
"string-length($date-time) > 10">
310 <xsl:value-of select=
"$new-dt" />
313 <xsl:value-of select=
"substring($new-dt, 1, string-length($date-time))" />
318 <xsl:template name=
"date:_add-days">
319 <xsl:param name=
"year" />
320 <xsl:param name=
"month" />
321 <xsl:param name=
"day" />
322 <xsl:param name=
"days" />
323 <xsl:param name=
"new-day" select=
"'NaN'" />
324 <xsl:variable name=
"leap" select=
"(not($year mod 4) and $year mod 100) or not($year mod 400)" />
325 <xsl:variable name=
"month-days" select=
"document('')/*/date:month-lengths/date:month" />
326 <xsl:variable name=
"days-in-month">
328 <xsl:when test=
"$month = 2 and $leap">
329 <xsl:value-of select=
"$month-days[number($month)] + 1" />
332 <xsl:value-of select=
"$month-days[number($month)]" />
337 <xsl:when test=
"$new-day = 'NaN'">
338 <xsl:call-template name=
"date:_add-days">
339 <xsl:with-param name=
"year" select=
"$year" />
340 <xsl:with-param name=
"month" select=
"$month" />
341 <xsl:with-param name=
"new-day">
343 <xsl:when test=
"$day > $days-in-month">
344 <xsl:value-of select=
"$days-in-month + $days" />
346 <xsl:otherwise><xsl:value-of select=
"$day + $days" /></xsl:otherwise>
353 <xsl:when test=
"$new-day < 1">
354 <xsl:call-template name=
"date:_add-days">
355 <xsl:with-param name=
"year" select=
"$year - ($month = 1)" />
356 <xsl:with-param name=
"month">
358 <xsl:when test=
"$month = 1">12</xsl:when>
359 <xsl:otherwise><xsl:value-of select=
"$month - 1" /></xsl:otherwise>
362 <xsl:with-param name=
"new-day">
363 <xsl:variable name=
"days-in-new-month">
365 <xsl:when test=
"$leap and $month = 3">29</xsl:when>
366 <xsl:when test=
"$month = 1">31</xsl:when>
368 <xsl:value-of select=
"$month-days[$month - 1]" />
372 <xsl:value-of select=
"$new-day + $days-in-new-month" />
376 <xsl:when test=
"$new-day > $days-in-month">
377 <xsl:call-template name=
"date:_add-days">
378 <xsl:with-param name=
"year" select=
"$year + ($month = 12)" />
379 <xsl:with-param name=
"month">
381 <xsl:when test=
"$month = 12">1</xsl:when>
382 <xsl:otherwise><xsl:value-of select=
"$month + 1" /></xsl:otherwise>
385 <xsl:with-param name=
"new-day" select=
"$new-day - $days-in-month" />
389 <xsl:value-of select=
"format-number($year, '0000')" />
390 <xsl:text>-
</xsl:text>
391 <xsl:value-of select=
"format-number($month, '00')" />
392 <xsl:text>-
</xsl:text>
393 <xsl:value-of select=
"format-number($new-day, '00')" />