Dates

1. Obtain date and time from a website,
2. Obtaining the date in a stylesheet
3. Date formatting
4. Formatting Dates
5. Calculating days up until today
6. Sorting by date
7. Compare Dates
8. Incorporating the current date time
9. Date conversions

1.

Obtain date and time from a website,

Daniel Bibbens



>  >    * An improved date stamp service is available at:
>  >      http://xobjex.com/service/date.xsl
>
> Can I make a couple of suggestions.
>
> The stamp attribute is close to ISO 8601 but not quite compliant.
> It should be either "2005-01-11T10:27:49+00:00" (extended format) or 
> "20050111T102749+0000" (basic format).
>
> You might consider putting in a reference for your time source.  I'm 
> guessing that you would use NTP, so perhaps a stratum number and some 
> basic stats.

Excellent suggestions and thank you for making them. I think you'll find the stamp attribute is now compliant for the extended format. I've also added attributes to the root element to include: ntp-stratum, source, and frequency.

The retrievd timestamp is (or was when I wrote this up),

<utc stamp="2005-01-29T13:12:17+00:00"> <year>2005</year> <month>01</month> <day>29</day> <hour>13</hour> <minute>12</minute> <second>17</second> </utc>

So a usage might be

 <p>The time is now
        <xsl:variable name="now">
          <xsl:copy-of select="
document('http://xobjex.com/service/date.xsl')/date/utc/*"/>
      </xsl:variable>
    
<xsl:text>Yr </xsl:text>      <xsl:value-of select="$now/year"/>  <br />
<xsl:text>month </xsl:text>    <xsl:value-of select="$now/month"/>  <br />
<xsl:text>day </xsl:text>  <xsl:value-of select="$now/day"/> <br />
<xsl:text>hour </xsl:text>    <xsl:value-of select="$now/hour"/> <br />
<xsl:text>min </xsl:text>  <xsl:value-of select="$now/min"/> <br />
<xsl:text>sec </xsl:text>  <xsl:value-of select="$now/second"/> <br />
<xsl:text>or in iso format, </xsl:text>

<xsl:value-of select="document('http://xobjex.com/service/date.xsl')/date/utc/@stamp"/>

</p>

2.

Obtaining the date in a stylesheet

Karl Marklund

Ednote. Asked so often I decided I'd add this solution from Karl. Note it is Linux specific, but MS programmers can obtain the date and pass it to the stylesheet as a command line parameter in a similar way

I was having trouble getting the current date into my xslt Finally I came up with this solution for Linux:

xsltproc -o foo.html --stringparam date "`date`" foo.xsl foo.xml

Inside foo.xsl:

 <xsl:param name="date">un-known</xsl:param>

 .
 .
 .
 <!-- This will give you the date of the last update -->
 <xsl:template match="last-updated">
    <xsl:value-of select="$date"/>
 </xsl:template>

3.

Date formatting

Heather Lindsay

I have a date which is in the form of "CCYYMMDD.HHMMSS" and I'm formatting this date to look like this: "MM/DD/YYYY HH:MM:SS GMT".

XML:
<Date>19981003.133045</Date>

XSL:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Date">
	<html>
		<head></head>
		<body>
			<p>
				<xsl:value-of
select="substring(.,5,2)"/><xsl:text>/</xsl:text><xsl:value-of
select="substring(.,7,2)"/><xsl:text>/</xsl:text><xsl:value-of
select="substring(.,1,4)"/><xsl:text> </xsl:text><xsl:value-of
select="substring(.,10,2)"/><xsl:text>:</xsl:text><xsl:value-of
select="substring(.,12,2)"/><xsl:text>:</xsl:text><xsl:value-of
select="substring(.,14)"/><xsl:text> GMT</xsl:text>
			</p>
		</body>
	</html>
</xsl:template>
</xsl:stylesheet>

OUTPUT:

<html>
	<head></head>
	<body>
	<p>10/03/1998 01:30:45 GMT</p>
	</body>
</html>

Christopher R. Maden adds: the code can be found, with documentation, at my website. The stylesheet (iso8601.xsl) may be of interest to anyone looking for an example of recursive string processing, ISO 8601 date and time strings, and semi-complex sorting problems. The whole package may be of interest to anyone doing XML consulting and billing by the hour.

Archive:  invoice.zip
   Length     Date   Time    Name

      1229  06-05-00 17:46   invoice.css
     14119  06-07-00 09:56   invoice.dtd
     41642  06-05-00 17:46   invoice.xsl
      2331  08-02-00 12:34   sample.xml
      2182  05-17-00 14:36   testinvoice.xml

     61503                   5 files

The XSL file can process either XML file to produce HTML output. The DTD is needed to identify IDs within the XML files; the CSS is included in the HTML output. (I was referencing it from the HTML, but multi-file invoices were a little too complicated for accounting types to deal with.)

I'll try to do a little documentation over the weekend, but it might be useful in advance of that.

A documented version of the invoice package is now available at my web page.

Comments and questions are welcome; I hope the ISO 8601 code proves useful to someone. If you expand its functionality or streamline it, please let me know; I can add modifications back into the published code.

4.

Formatting Dates

Matthew Bentley

Heres three functions for formatting a date of the form "YYYYMMDD" into other formats in XSLT:

<xsl:template name="standard_date">
	<xsl:param name="date" />
	<!-- Day -->
	<xsl:value-of select="substring($date, 7, 2)" />
	<xsl:text>/</xsl:text>
	<!-- Month -->
	<xsl:value-of select="substring($date, 5, 2)" />
	<xsl:text>/</xsl:text>
	<!-- Year -->
	<xsl:value-of select="substring($date, 3, 2)" />
</xsl:template>

<xsl:template name="short_date">
	<xsl:param name="date" />
	<!-- Month -->
	<xsl:value-of select="substring($date, 5, 2)" />
	<xsl:text>/</xsl:text>
	<!-- Year -->
	<xsl:value-of select="substring($date, 3, 2)" />
</xsl:template>

<xsl:template name="long_date">
	<xsl:param name="date" />
	<!-- Day -->
	<xsl:value-of select="number(substring($date, 7, 2))" />
	<xsl:text> </xsl:text>
	<!-- Month -->
	<xsl:variable name="month" 
     select="number(substring($date, 5, 2))"/>
	<xsl:choose>
		<xsl:when test="$month=1">January</xsl:when>
		<xsl:when test="$month=2">February</xsl:when>
		<xsl:when test="$month=3">March</xsl:when>
		<xsl:when test="$month=4">April</xsl:when>
		<xsl:when test="$month=5">May</xsl:when>
		<xsl:when test="$month=6">June</xsl:when>
		<xsl:when test="$month=7">July</xsl:when>
		<xsl:when test="$month=8">August</xsl:when>
		<xsl:when test="$month=9">September</xsl:when>
		<xsl:when test="$month=10">October</xsl:when>
		<xsl:when test="$month=11">November</xsl:when>
		<xsl:when test="$month=12">December</xsl:when>
		<xsl:otherwise>INVALID MONTH</xsl:otherwise>
	</xsl:choose>
	<xsl:text> </xsl:text>
	<!-- Year -->
	<xsl:value-of select="substring($date, 1, 4)" />
</xsl:template>


5.

Calculating days up until today

Oliver Becker

Ednote: month and date params added for testing.

<xsl:stylesheet version="1.0"
		xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
		xmlns:data="urn:data-section"
		exclude-result-prefixes="data">
<xsl:param name="month" select="Jan"/>
<xsl:param name="date" select="1"/>

<data:month name="Jan" days="0" />
<data:month name="Feb" days="31" />
<data:month name="Mar" days="59" />
<data:month name="Apr" days="90" />
<data:month name="May" days="120" />
<data:month name="Jun" days="151" />
<data:month name="Jul" days="181" />
<data:month name="Aug" days="212" />
<data:month name="Sep" days="243" />
<data:month name="Oct" days="273" />
<data:month name="Nov" days="304" />
<data:month name="Dec" days="334" />

<xsl:template match="/">
   Days since January, 1.:
   <xsl:value-of 
   select="document('')/*/data:month[@name=$month]/@days + $date />
</xsl:template>

</xsl:stylesheet>

6.

Sorting by date

David Carlisle

I have an XML file with a list of <content> elements as shown below. I need to be able to sort them by publicationDate and only dipslay the first 20 Does anyone have any ideas?.

You might want to consider using an extension function to a language with built in date parsing, but if not....

restricted to outputting first 5 in oorder, and showing the sort key for clarity:

<x>

<content id="66228-135831" displayText="banjo"  
	  publicationDate="Wed Jan 01
00:00:00 GMT 1999" />
<content id="66228-135832" displayText="banjo"  
	  publicationDate="Wed Aug 02
00:00:00 GMT 2001" />
<content id="66228-135833" displayText="banjo"  
	  publicationDate="Wed Jul 03
00:00:00 GMT 2000" />
<content id="66228-135834" displayText="banjo"  
	  publicationDate="Wed Jun 04
00:00:00 GMT 2000" />
<content id="66228-135835" displayText="banjo"  
	  publicationDate="Wed May 05
00:00:00 GMT 1999" />
<content id="66228-135836" displayText="banjo"  
	  publicationDate="Wed Apr 06
00:00:00 GMT 2000" />
<content id="66228-135840" displayText="banjo"  
	  publicationDate="Wed Mar 07
00:00:00 GMT 2001" />
<content id="66228-135889" displayText="banjo"  
	  publicationDate="Wed Feb 08
00:00:00 GMT 1998" />
<content id="66228-135890" displayText="banjo"  
	  publicationDate="Wed Jan 09
00:00:00 GMT 2000" />
<content id="66228-135618" displayText="lotus"  
	  publicationDate="Wed Mar 02 
00:00:00 GMT 2000" />
<content id="66228-135713" displayText="nother Test" 
	  publicationDate="Wed Dec 13 00:00:00 GMT 2000" />

</x>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0"
                xmlns:month="data:,month"
                >

<xsl:output method="xml" indent="yes"/>

<month:x m="Jan" pos="01" />
<month:x m="Feb" pos="02" />
<month:x m="Mar" pos="03" />
<month:x m="Apr" pos="04" />
<month:x m="May" pos="05" />
<month:x m="Jun" pos="06" />
<month:x m="Jul" pos="07" />
<month:x m="Aug" pos="08" />
<month:x m="Sep" pos="09" />
<month:x m="Oct" pos="10" />
<month:x m="Nov" pos="11" />
<month:x m="Dec" pos="12" />


<xsl:template match="x">
<xsl:for-each select="content">
<xsl:sort select="concat(substring(@publicationDate,25,4),
                   document('')//month:x
                    [@m=substring(current()/@publicationDate,5,3)]/@pos,
                   substring(@publicationDate,9,2))"/>

<xsl:if test="position() &lt; 5">
[<xsl:value-of select="concat(substring(@publicationDate,25,4),
                   document('')//month:x
                    [@m=substring(current()/@publicationDate,5,3)]/@pos,
                   substring(@publicationDate,9,2))"/>]
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>


$ xt date.xml date.xsl
<?xml version="1.0" encoding="utf-8"?>

[19980208]
<content id="66228-135889" displayText="banjo" 
	  publicationDate="Wed Feb 08 00:00:00 GMT 1998"/>
[19990101]
<content id="66228-135831" displayText="banjo" 
	  publicationDate="Wed Jan 01 00:00:00 GMT 1999"/>
[19990505]
<content id="66228-135835" displayText="banjo" 
	  publicationDate="Wed May 05 00:00:00 GMT 1999"/>
[20000109]
<content id="66228-135890" displayText="banjo" 
	  publicationDate="Wed Jan 09 00:00:00 GMT 2000"/>

7.

Compare Dates

Chris Bayes


>I want to compare two dates to find out which comes first.
>2000-12-19
>What I don't want to do is to compare each number, if I validate the
>formate is there a XSL function to see which date comes first.

Try

<xsl:if test="number(translate(date1, '-', '')) > number(translate(date2,
'-', ''))">

8.

Incorporating the current date time

Allan Jones

one trick i've used a couple of times for this is to use batch files to perform the transform, and to use command line parameters to create an xml file containing the current date.

for example, through dos you'd have a start.txt file:

<?xml version="1.0" encoding="UTF-8"?>
<datetime>
	<time>

and a middle.txt file:

	</time>
	<date>

and a finish.txt file:

	</date>
</datetime>

you'd then have a dos batch file (say, datetime.bat) looking something like this:

@echo off
type start.txt
time /t
type middle.txt
date /t
type finish.txt

after putting all of these files in the same folder, you'd call this file as follows:

call datetime.bat > datetime.xml

what you end up with is a file called datetime.xml that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<datetime>
   <time>10:53
	</time>
	<date>Tue 10/12/2002
	</date>
</datetime>

using the document() function you can then import this file in your xsl, and do whatever you want with the content. of course, this is only useful if you're using batch files, as you'd still have to call the batch file before doing the transform, and if you're doing that then you may as well just pass in a parameter. i've found it useful, though, because i can make batch files that bit more generic using this method, and i can also transform the content of the datetime.xml file very easily.

i've only tested this on windows 2000, but i expect that it'd work on any dos version.

p.s. if you need to transform this into an xs:datetime format, this might help:

<!--
create a timestamp variable from the timestamp.xml file
of the form yyyy-mm-ddThh:mm:ss
note that the timestamp.xml file was created at the command
line using batch files and the 'type' command applied to
text files, so the spacing is a little suspect.  to counteract
this, i've used 'normalize-space' to strip leading and trailing
spaces from the file's values before i use them
-->
<xsl:variable name="timestamp">
	<xsl:variable name="date">
		<xsl:value-of
select="substring-after(normalize-space(
document('datetime.xml')/datetime/date), ' ')"/>
	</xsl:variable>
	<!--
	the batch file produces the date in the format:
	day dd/mm/yyyy
	we need it in the form yyyy-mm-dd, so we separate
	out the components using substrings, and then recombine
	them in the right order
	-->
	<xsl:variable name="day">
		<xsl:value-of select="substring-before($date, '/')"/>
	</xsl:variable>
	<xsl:variable name="month_and_year">
		<xsl:value-of select="substring-after($date, '/')"/>
	</xsl:variable>
	<xsl:variable name="month">
		<xsl:value-of select="substring-before($month_and_year,
'/')"/>
	</xsl:variable>
	<xsl:variable name="year">
		<xsl:value-of select="substring-after($month_and_year,
'/')"/>
	</xsl:variable>
	<xsl:value-of select="concat($year, '-', $month, '-', $day)"/>
	<!-- we need a 'T' before the time itself -->
	<xsl:text>T</xsl:text>
	<!-- select the time from the document -->
	<xsl:value-of
select="normalize-space(document('datetime.xml')/datetime/time)"/>
	<!--
	add seconds at end to complete the timestamp format
	we now have the xs:dateTime format as required:
	yyyy-mm-ddThh:mm:ss
	-->
	<xsl:text>:00</xsl:text>
</xsl:variable>

9.

Date conversions

Jarno Elovirta



>  I receive for example a date in a concatenated 
> format:

> Ex: 20041207

> And I have to retrieve it in a readable format through my xslt-fo 
> transformation.

> Ex. 12 July 2004

Substring function <W3C>.

 concat(substring(., 5, 2), ' ',
substring('JanFebMarAprMayJunJulAugSepOctNovDec', substring(., 7, 2) * 3 -
2, 3), ' ', substring(., 1, 4))

will give you "12 Jul 2004", but for complete month names

  concat(substring(., 5, 2), ' ', document('')/*/x:months/month[position() =
substring(current(), 7, 2)], ' ', substring(., 1, 4))

with a top level element

  <x:months>
    <month>January</month>
    <month>February</month>
    <month>March</month>
    ...
  </x:months>