Subject: Re: [xsl] Function converting RFC 2822 date to xsd:dateTime From: "Syd Bauman s.bauman@xxxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> Date: Tue, 9 Apr 2019 03:45:16 -0000 |
Martynas -- As Michael Kay brought up, switching to XSLT 3.0 and using parse-ietf-date() is probably the best way to go. And I don't pretend to be a good enough programmer to know if there are improvements to be made to your algorithm. But when dealing with unwieldy stuff like this, I find it very helpful to name bits of code and to use whitespace liberally, especially within the regular expression (using the 'x' flag). Here is an XSLT 2.0 program that runs a modified version of your function. The only other changes I've made to the function are: * signature of $months is now '+', not '*' * different mechanism for inserting colon into TZ * return a dateTime even when there's an error in parsing ####################### <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all" xmlns:aex="http://idunno.example.org/" version="2.0"> <xsl:param name="dt" select="'Tue, 9 Apr 2019 00:07:24 +1200 (NZST)'" as="xs:string"/> <xsl:output method="text"/> <xsl:template match="/"> <xsl:text>Result: </xsl:text> <xsl:value-of select="aex:rfc2822dateTime-to-dateTime( $dt )"/> <xsl:text>
</xsl:text> </xsl:template> <xsl:function name="aex:rfc2822dateTime-to-dateTime" as="xs:dateTime"> <xsl:param name="date-time" as="xs:string"/> <xsl:variable name="months" as="xs:string+" select=" 'Jan', 'Feb', 'Mar','Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep','Oct', 'Nov', 'Dec'"/> <xsl:analyze-string select="$date-time" flags="x" regex=" ^ (?: (Sun|Mon|Tue|Wed|Thu|Fri|Sat),\s+ )? ( 0[1-9] | [1-2]?[0-9] | 3[01] ) \s+ (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \s+ ( 19[0-9]{{2}} | [2-9][0-9]{{3}} ) \s+ ( 2[0-3] | [0-1][0-9] ) : ( [0-5][0-9] ) (?: :( 60 | [0-5][0-9] ) )? \s+ ( [-\+] [0-9]{{2}}[0-5][0-9] | (?: UT | GMT | (?:E|C|M|P) (?:ST|DT) | [A-IK-Z] ) ) (\s+|\(([^\(\)]+|\\\(|\\\))*\))*$"> <xsl:matching-substring> <xsl:variable name="day" select="regex-group(1)"/><!-- unused --> <xsl:variable name="date" select="xs:integer( regex-group(2) )"/> <xsl:variable name="month" select="index-of( $months, regex-group(3) )"/> <xsl:variable name="year" select="xs:integer( regex-group(4) )"/> <xsl:variable name="hour" select="xs:integer( regex-group(5) )"/> <xsl:variable name="minute" select="xs:integer( regex-group(6) )"/> <xsl:variable name="second" select="xs:integer( regex-group(7) )"/> <xsl:variable name="timezone" select="replace( regex-group(8),'^(...)(.*)$','$1:$2' )"/> <xsl:variable name="dateTimeString" select="concat( format-number( $year,'0001'), '-', format-number( $month,'01'), '-', format-number( $date,'01'), 'T', format-number( $hour,'01'), ':', format-number( $minute,'01'), ':', format-number( $second,'01'), $timezone )"/> <xsl:value-of select="$dateTimeString"/> </xsl:matching-substring> <xsl:non-matching-substring> <xsl:message>Invalid RFC 2822 datetime: <xsl:value-of select="$date-time"/></xsl:message> <!-- 2 points to anyone who can say what happened at the date and time I've chosen to return in case of error. 2 hints: 1) I made up the seconds, to my knowledge it was only recorded to the minute; 2) it was pronounced "seventeen October nineteen forty-five" in the musical. --> <xsl:value-of select="xs:dateTime('1945-10-17T23:10:30-03:00')"/> </xsl:non-matching-substring> </xsl:analyze-string> </xsl:function> </xsl:stylesheet> ####################### Hope this is at least food for thought, if not outright helpful.
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Function converting RFC 2, Michael Kay mike@xxx | Thread | Re: [xsl] Function converting RFC 2, Martynas Jusevičius |
Re: [xsl] Function converting RFC 2, Michael Kay mike@xxx | Date | [xsl] Transforming large XML docume, Mukul Gandhi gandhi. |
Month |