Is there some simple way to calculate a Weeknumber value from a date value stored in XML?
It needs to be pure XSLT solution. I cannot use any code :(
Is there some simple way to calculate a Weeknumber value from a date value stored in XML?
It needs to be pure XSLT solution. I cannot use any code :(
I program in Visual Basic, so I know how to do it using VB.NET. Read your XML date into a variable (let's call it SomeDate). Then you construct a new date that you know is the beginning of the year that contains your unknown date. Then, you let the DateDiff function do its work to tell you the week number.
Dim SomeDate As Date = ReadDateFromXML()
Dim YearStart As New Date(Year(SomeDate), 1, 1)
Dim WeekNumber As Integer = DateDiff(DateInterval.WeekOfYear, YearStart, SomeDate)
And in C#:
DateTime date = DateTime.Now;
int week = date.DayOfYear / 7;
Console.WriteLine(week);
Week calculation can get pretty complicated if you always want the week to start on the same day, because the first day of the year is always changing. There's an ISO standard for calculating it, see this Wikipedia article.
If you can use EXSLT, there are several date functions available. All of them are implemented in Saxon, but if you're using MSXSL, Chris Bayes has implemented them as extension functions, which you can actually place within your transform inside an msxsl:script element. His implementations are linked from each specific date function page.
Is week-in-year() the function you're looking for?
Edit: Per JeniT's comment, there's a pure XSLT 1.0 template available on the same site with the same functionality as week-in-year() (which she wrote, I think), which might fit your requirements better.
Check out the XSLT Cookbook by Sal Mangano. Interestingly enough it is available on books.google.com http://books.google.com/books?id=su4pWUPWwuEC&pg=PA125&lpg=PA125&dq=xslt+weeknumber&source=web&ots=nBBc3DVJYU&sig=l19cpOhwd9_PqrB72b9CCZk9wUA
The xslt 2.0 way is:
<xsl:function name="chkbk:calculate-week-number" as="xs:integer">
<xsl:param name="date" as="xs:date" />
<xsl:sequence select="xs:integer(format-date($date,'[W'))" />
</xsl:function>
For the 1.0 way, see the cookbox preview. BTW, I simply googled xslt weeknumber to locate this.
This is a pure XSLT 1.0 solution:
One can use the datetime_lib.xsl
stylesheet module by Martin Rowlinson, which comes with the XSelerator (a nice XSLT IDE, recently made freely available on sourceforge). You will have to download and install this application, then you will find a wealth of additional libraries and samples of advanced techniques and solutions.
The datetime_lib.xsl
file can be found (for a typical installation) on:
C:\Program Files\Marrowsoft\Xselerator25\Samples\Libraries\
From this library, here is the template named "week-number":
<xsl:template name="week-number"> <xsl:param name="year"/> <xsl:param name="month"/> <xsl:param name="day"/> <!-- or --> <xsl:param name="date" select="''"/> <!-- format: yyyymmdd or yyyy-mm-dd --> <!-- or --> <xsl:param name="julian-day" select="''"/> <!-- trim down date --> <xsl:variable name="tdate" select="translate($date,'-','')"/> <!-- decide which params were passed --> <xsl:variable name="yyyy"> <xsl:choose> <xsl:when test="string-length($date) > 0"><xsl:value-of select="substring($tdate,1,4)"/></xsl:when> <xsl:when test="string-length($julian-day) > 0"> <xsl:variable name="jdate"> <xsl:call-template name="julian-day-to-date"> <xsl:with-param name="julian-day" select="$julian-day"/> </xsl:call-template> </xsl:variable> <xsl:value-of select="substring($jdate,1,4)"/> </xsl:when> <xsl:otherwise><xsl:value-of select="$year"/></xsl:otherwise> </xsl:choose> </xsl:variable> <!-- get the julian day number --> <xsl:variable name="jd"> <xsl:choose> <xsl:when test="string-length($julian-day) > 0"><xsl:value-of select="$julian-day"/></xsl:when> <xsl:otherwise> <xsl:call-template name="date-to-julian-day"> <xsl:with-param name="year" select="$year"/> <xsl:with-param name="month" select="$month"/> <xsl:with-param name="day" select="$day"/> <xsl:with-param name="date" select="$date"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- get the julian day number for the first working day of next year --> <xsl:variable name="fyjd"> <xsl:call-template name="first-day-of-year"> <xsl:with-param name="year" select="$yyyy+1"/> <xsl:with-param name="as-julian-day" select="true()"/> </xsl:call-template> </xsl:variable> <!-- decide which the 'working' year for this date is --> <xsl:variable name="start-jd"> <xsl:choose> <xsl:when test="$jd >= $fyjd"><xsl:value-of select="$fyjd"/></xsl:when> <xsl:otherwise> <xsl:call-template name="date-to-julian-day"> <xsl:with-param name="date"> <xsl:call-template name="first-day-of-year"> <xsl:with-param name="year" select="$yyyy"/> </xsl:call-template> </xsl:with-param> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- final calc output --> <xsl:value-of select="floor(($jd - $start-jd) div 7) + 1"/> </xsl:template>
Here is a simple XSLT transformation using the"week-number" template:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"> <xsl:import href= "C:\Program Files\Marrowsoft\Xselerator25\Samples\Libraries\datetime_lib.xsl"/> <xsl:output method="text"/> <xsl:template match="/"> <xsl:call-template name="week-number"> <xsl:with-param name="date" select="'2008-11-16'"/> </xsl:call-template> </xsl:template> </xsl:stylesheet>
When applied on any source XML document (not used), the wanted result is produced:
46
Hope that this time the answer was really more helpful.
Cheers,
Dimitre Novatchev.