[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Function converting RFC 2822 date to xsd:dateTime

Subject: Re: 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
Re:  Function converting RFC 2822 date to xsd:dateTime
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.

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.