Skip to content

Instantly share code, notes, and snippets.

@bzerangue
Created March 9, 2011 16:11
Show Gist options
  • Save bzerangue/862469 to your computer and use it in GitHub Desktop.
Save bzerangue/862469 to your computer and use it in GitHub Desktop.
[XSLT] Convert RFC 2822 format to ISO date format
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Name: RSS feed date format to Symphony date format
Version: 1.0
Author: Brian Zerangue <brian.zerangue@gmail.com>
URL: http://symphony21.com/downloads/xslt/file/20457/
Description:
Convert RSS feed date format to Symphony date format
Convert RFC 2822 timestamp format to ISO date format minus the time info (Symphony CMS date format)
RFC 2822 format: Sun, 7 Jan 2007 12:00:00 GMT
ISO 8601 format (minus the time info): 2007-01-07
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="format-from-rfc-to-iso">
<xsl:param name="rfc-date"/>
<xsl:param name="day-with-zero" select="format-number(substring(substring($rfc-date,6,11),1,2),'00')"/>
<xsl:param name="month-with-zero">
<xsl:if test="contains($rfc-date,'Jan')">01</xsl:if>
<xsl:if test="contains($rfc-date,'Feb')">02</xsl:if>
<xsl:if test="contains($rfc-date,'Mar')">03</xsl:if>
<xsl:if test="contains($rfc-date,'Apr')">04</xsl:if>
<xsl:if test="contains($rfc-date,'May')">05</xsl:if>
<xsl:if test="contains($rfc-date,'Jun')">06</xsl:if>
<xsl:if test="contains($rfc-date,'Jul')">07</xsl:if>
<xsl:if test="contains($rfc-date,'Aug')">08</xsl:if>
<xsl:if test="contains($rfc-date,'Sep')">09</xsl:if>
<xsl:if test="contains($rfc-date,'Oct')">10</xsl:if>
<xsl:if test="contains($rfc-date,'Nov')">11</xsl:if>
<xsl:if test="contains($rfc-date,'Dec')">12</xsl:if>
</xsl:param>
<xsl:param name="year-full" select="format-number(substring(substring($rfc-date,6,11),7,5),'####')"/>
<xsl:param name="rfc-date-to-iso" select="concat($year-full,'-',$month-with-zero,'-',$day-with-zero)"/>
<xsl:value-of select="$rfc-date-to-iso"/>
</xsl:template>
</xsl:stylesheet>
@aendra-rininsland
Copy link

You, sir, are a gentleman and a scholar. G'day to you! 👍

@namedgraph
Copy link

Useful!

@namedgraph
Copy link

namedgraph commented Apr 4, 2019

I've turned this into an XSLT 2.0 function that uses regex:

<xsl:function name="aex:rfc2822dateTime-to-dateTime" as="xs:dateTime">
    <xsl:param name="date-time" as="xs:string"/> <!-- Tue, 9 Apr 2019 00:07:24 +1200 (NZST) -->
    <xsl:variable name="months" select="'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'" as="xs:string*"/>
    <!-- https://stackoverflow.com/questions/9352003/rfc-2822-date-regex -->
    <xsl:analyze-string select="$date-time"
        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:sequence select="xs:dateTime(concat(format-number(xs:integer(regex-group(4)), '0001'), '-', format-number(index-of($months, regex-group(3)), '01'), '-', format-number(xs:integer(regex-group(2)), '01'), 'T', format-number(xs:integer(regex-group(5)), '01'), ':', format-number(xs:integer(regex-group(6)), '01'), ':', format-number(xs:integer(regex-group(7)), '01'), substring(regex-group(8), 1, 3), ':', substring(regex-group(8), 4, 2)))"/>
        </xsl:matching-substring>
        <xsl:non-matching-substring>
            <xsl:message>Invalid RFC 2822 datetime: <xsl:value-of select="$date-time"/></xsl:message>
        </xsl:non-matching-substring>
    </xsl:analyze-string>
</xsl:function>

In XPath 3.0 there is a built-in parse-ietf-date() function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment