xsl-list
[Top] [All Lists]

Re: [xsl] Function converting RFC 2822 date to xsd:dateTime

2019-04-08 22:45:28
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>&#x0A;</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.
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>