Date Functions
Is there a way within a template do do "date arithmetic"?
An example would be is that we would like to take the "order date" and have printed in the email or report a date that would be say 2 days later than the "order date".
Thanks,
Carl
-
Official comment
Hi, Willy B -
When we see the 'source10.xsl' error on a template preview, we just need to close and reopen ShipWorks. Please give that a try! I'll reach out in a support ticket directly to make sure there's no further troubleshooting that we need to do after that.
Thanks!
AJ
Comment actions -
try something like this.
<!DOCTYPE xsl:stylesheet[ <!ENTITY nl "
"> ]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sw="http://www.interapptive.com/shipworks" extension-element-prefixes="sw" xmlns:user="urn:my-scripts" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:import href="System\Snippets" />
<msxsl:script language="CSharp" implements-prefix="user">
<msxsl:assembly name="System.Web"/>
<msxsl:using namespace="System.Web"/>
<![CDATA[
public DateTime GetDateValue(DateTime ODate)
{
DateTime od = ODate;
return od.AddDays(2);
}
]]>
</msxsl:script>
<xsl:output method="text" encoding="utf-8" />
<!-- Start of template -->
<xsl:template match="/"><xsl:apply-templates /></xsl:template>
<xsl:template match="ShipWorks">
<xsl:variable name="Order" select="Customer/Order" />
<xsl:text>FullName,OrderNumber,OrderDate,ModifiedOrderDate&nl;</xsl:text>
<xsl:for-each select="$Order">
<xsl:value-of select="./Address[@type='ship']/FullName" /><xsl:text>,</xsl:text>
<xsl:value-of select="./Number" /><xsl:text>,</xsl:text>
<xsl:value-of select="./Date" /><xsl:text>,</xsl:text>
<xsl:value-of select="user:GetDateValue(./Date)" />
<xsl:text>&nl;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet> -
Nathan,
In a quick review of the code you provided it appears you have given an example with the "today's date", is that correct?
If that's so, is there a way to also do this with the "order date"?
I will work with what you have provided in a bit and if I have any questions I will let you know.
Thanks,
Carl
-
Hi Nathan -
Is there any way to adapt this function to only add or subtract business days? We would like to calculate a "ship by date" by subtracting some number of business days from a date stored in a variable, so if the stored date is 10/1/20, and we need to ship 4 business days before that, we want the template to calculate 4 business days before that, which would be 9/25.
I'm stumped!
Thanks! -
@...
I did this kind of fast so please double check my work but I believe this should give you what your looking for.
This does not take Holidays into consideration as it would require a much larger solution or adding a calendar table to the database to pull from.
<!DOCTYPE xsl:stylesheet[ <!ENTITY nl "
"> ]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sw="http://www.interapptive.com/shipworks" extension-element-prefixes="sw" xmlns:user="urn:my-scripts" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:import href="System\Snippets" />
<msxsl:script language="CSharp" implements-prefix="user">
<msxsl:assembly name="System.Web"/>
<msxsl:using namespace="System.Web"/>
<![CDATA[
public static DateTime AddBusinessDays(DateTime date, int days)
{
if (days == 0) return date;
if (date.DayOfWeek == DayOfWeek.Sunday)
{
date = date.AddDays(-2);
days -= 1;
}
else if (date.DayOfWeek == DayOfWeek.Saturday)
{
date = date.AddDays(-1);
days -= 1;
}
date = date.AddDays(days / -5 * -7);
int extraDays = days % -5;
if ((int)date.DayOfWeek - extraDays > -5)
{
extraDays -= 2;
}
return date.AddDays(extraDays);
}
]]>
</msxsl:script>
<xsl:output method="text" encoding="utf-8" />
<!-- Start of template -->
<xsl:template match="/"><xsl:apply-templates /></xsl:template>
<xsl:template match="ShipWorks">
<xsl:variable name="Order" select="Customer/Order" />
<xsl:text>FullName,OrderNumber,OrderDate,ModifiedOrderDate&nl;</xsl:text>
<xsl:for-each select="$Order">
<xsl:value-of select="./Address[@type='ship']/FullName" /><xsl:text>,</xsl:text>
<xsl:value-of select="./Number" /><xsl:text>,</xsl:text>
<xsl:value-of select="./Date" /><xsl:text>,</xsl:text>
<xsl:value-of select="user:AddBusinessDays(./Date, -4)" />
<xsl:text>&nl;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet> -
@...
Here is a much better solution.
<!DOCTYPE xsl:stylesheet[ <!ENTITY nl "
"> ]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sw="http://www.interapptive.com/shipworks" extension-element-prefixes="sw" xmlns:user="urn:my-scripts" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:import href="System\Snippets" />
<msxsl:script language="CSharp" implements-prefix="user">
<msxsl:assembly name="System.Web"/>
<msxsl:using namespace="System.Web"/>
<![CDATA[
public static DateTime AddBusinessDays(DateTime current, int days)
{
var sign = Math.Sign(days);
var unsignedDays = Math.Abs(days);
for (var i = 0; i < unsignedDays; i++)
{
do
{
current = current.AddDays(sign);
} while (current.DayOfWeek == DayOfWeek.Saturday ||
current.DayOfWeek == DayOfWeek.Sunday);
}
return current;
}
]]>
</msxsl:script>
<xsl:output method="text" encoding="utf-8" />
<!-- Start of template -->
<xsl:template match="/"><xsl:apply-templates /></xsl:template>
<xsl:template match="ShipWorks">
<xsl:variable name="Order" select="Customer/Order" />
<xsl:text>FullName,OrderNumber,OrderDate,ModifiedOrderDate&nl;</xsl:text>
<xsl:for-each select="$Order">
<xsl:value-of select="./Address[@type='ship']/FullName" /><xsl:text>,</xsl:text>
<xsl:value-of select="./Number" /><xsl:text>,</xsl:text>
<xsl:value-of select="./Date" /><xsl:text>,</xsl:text>
<xsl:value-of select="user:AddBusinessDays(./Date, -4)" />
<xsl:text>&nl;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet> -
Thanks Nathan -
I think I'm close on this, but unfortunately I keep crashing Shipworks when I try to get the last step. Here's the code I'm trying:
================================================
<!DOCTYPE xsl:stylesheet[ <!ENTITY nl "
"> ]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sw="http://www.interapptive.com/shipworks" extension-element-prefixes="sw" xmlns:user="urn:my-scripts" xmlns:msxsl="urn:schemas-microsoft-com:xslt"><xsl:import href="System\Snippets" />
<msxsl:script language="CSharp" implements-prefix="user">
<msxsl:assembly name="System.Web"/>
<msxsl:using namespace="System.Web"/>
<![CDATA[
public static DateTime AddBusinessDays(DateTime current, int days)
{
var sign = Math.Sign(days);
var unsignedDays = Math.Abs(days);
for (var i = 0; i < unsignedDays; i++)
{
do
{
current = current.AddDays(sign);
} while (current.DayOfWeek == DayOfWeek.Saturday ||
current.DayOfWeek == DayOfWeek.Sunday);
}
return current;
}
]]>
</msxsl:script>
<xsl:output method="text" encoding="utf-8" /><!-- Start of template -->
<xsl:template match="/"><xsl:apply-templates /></xsl:template>
<xsl:template match="ShipWorks">
<xsl:variable name="Order" select="Customer/Order" />
<!--Here I'm setting "reqship" as a string from the stored requested shipping.
<xsl:variable name="reqship" select="RequestedShipping" />
But since your "requested shipping" will not match mine, I'll manually set it as a variable instead-->
<xsl:variable name="reqship" select="'Deliver By: 10/19'"></xsl:variable>
<!--Now I want to pull out the 10/19. This code will later be expanded to work with any variation of the requested shipping that we get.-->
<xsl:variable name="deldate" select="substring($reqship, 13)" />
<!--Now to convert the string to a Shipworks date-->
<xsl:variable name="swdeldate" select="sw:ToShortDate($deldate)" />
<xsl:text>FullName,OrderNumber,Requested Delivery Date,Ship By Date&nl;</xsl:text>
<xsl:for-each select="$Order">
<xsl:value-of select="./Address[@type='ship']/FullName" /><xsl:text>,</xsl:text>
<xsl:value-of select="./Number" /><xsl:text>,</xsl:text><!--Output the requested delivery date extracted from above -->
<xsl:value-of select="$swdeldate" /><xsl:text>,</xsl:text>
<!--Subtract four workdays from that day -->
<xsl:value-of select="user:AddBusinessDays($swdeldate, -4)" />
<xsl:text>&nl;</xsl:text>
</xsl:for-each></xsl:template>
</xsl:stylesheet>================================================
It seems that my line <xsl:value-of select="user:AddBusinessDays($swdeldate, -4)" /> is the problem, and I assume it's because I'm passing an improperly formatted date to the function. Any suggestions?
-
I reformatted the date string I had to fit the datetime format and this worked wonderfully.
With a few logic steps to calculate a transit time based on order state, this allows us to automatically calculate a rough "must ship by date" to print on any paperwork related to an order.
Thanks a ton for your help with this. Having this functionality is a really big improvement to our workflow.
Please sign in to leave a comment.
Comments
16 comments