Subject: [xsl] localtime (accounting for summmertime/DST) in XSLT 2.0 From: Steven Hentschel <steven.hentschel@xxxxxxxxx> Date: Wed, 4 May 2011 09:46:18 +0100 |
"adjust-dateTime-to-timezone" without the second parameter will convert a dateTime to the implicit timezone which, in Saxon 9.3 at least, seems to be the UTC offset currently applying on the computer running the stylesheet. Hence "adjust-dateTime-to-timezone(current-dateTime())" will return local time accurately. However, if summertime or DST applies in a particular territory and a datetime, that falls outside the period the current UTC offset is in force, is passed into "adjust-dateTime-to-timezone", then the result is not the localtime representation of the datetime value. Is this a bug, a design decision or an ambiguity? I did bingle around for how to convert an arbitrary datetime into localtime but I couldn't find any so I had a go at writing my own. It turns out writing a custom function for Summertime/DST isn't that difficult as the format-date function can return the day of the week for a given date which can then be used to extrapolate the dates at the weekends at which the UTC offset changes. Here is my function: <!-- adjusts a dateTime to UK local time account for GMT/BST --> <xsl:function name="mynamespace:adjust-dateTime-to-uk-local-time" as="xs:dateTime"> <xsl:param name="DATETIMEIN" as="xs:dateTime"/> <xsl:variable name="ADJUSTGMT" select="adjust-dateTime-to- timezone($DATETIMEIN, xs:dayTimeDuration('PT0H'))"/> <!-- BST starts at 1 a.m UTC on last Sunday in March --> <xsl:variable name="BSTSTARTS" select="xs:dateTime(concat(year-from- dateTime($ADJUSTGMT), '-03-', 31 - xs:integer(replace(replace(replace(replace(replace(replace(replace( format-date(xs:date(concat(year-from-dateTime($ADJUSTGMT), '-03-31Z')), '[Fn, 2-2]') , 'su', '0'), 'mo', '1'), 'tu', '2'), 'we', '3'), 'th', '4'), 'fr', '5'), 'sa', '6')), 'T01:00:00Z'))" as="xs:dateTime"/> <!-- BST ends at 1 a.m UTC on last Sunday in October --> <xsl:variable name="BSTENDS" select="xs:dateTime(concat(year-from- dateTime($ADJUSTGMT), '-10-', 31 - xs:integer(replace(replace(replace(replace(replace(replace(replace( format-date(xs:date(concat(year-from-dateTime($ADJUSTGMT), '-10-31Z')), '[Fn, 2-2]') , 'su', '0'), 'mo', '1'), 'tu', '2'), 'we', '3'), 'th', '4'), 'fr', '5'), 'sa', '6')), 'T01:00:00Z'))" as="xs:dateTime"/> <xsl:choose> <xsl:when test="$ADJUSTGMT ge $BSTSTARTS and $ADJUSTGMT lt $BSTENDS"> <!--return UTC +1 in summer--> <xsl:value-of select="adjust-dateTime-to-timezone($DATETIMEIN, xs:dayTimeDuration('PT1H'))"/> </xsl:when> <xsl:otherwise> <!--return UTC +0 in winter --> <xsl:value-of select="$ADJUSTGMT"/> </xsl:otherwise> </xsl:choose> </xsl:function> It could easily be modified for other countries with summertime/DST. Note that the function won't necessarily work for historical dates as the present method of determining the datetime of the changeovers has only been in force since 2002.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] RE: Error message, doc no, Andrew Welch | Thread | [xsl] Looking for a concise way of , John McGowan |
Re: [xsl] Error message saying doc , Andrew Welch | Date | Re: [xsl] Error message saying doc , Michael Kay |
Month |