Date Functions

Comments

16 comments

  • Official comment
    Avatar
    AJ Meyer

    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 Permalink
  • Avatar
    Nathan Head

    This is not possible with XSLT 1.0 alone. You would need the help of scripts, Give me a few min.

    0
    Comment actions Permalink
  • Avatar
    Nathan Head

    try something like this.

    <!DOCTYPE xsl:stylesheet[ <!ENTITY nl "&#xd;&#xa;"> ]>
    <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>
    0
    Comment actions Permalink
  • Avatar
    Nathan Head

    Let me know if you have any questions or need help with implementing this on your own template.

    0
    Comment actions Permalink
  • Avatar
    Carl Berman

    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

     

    0
    Comment actions Permalink
  • Avatar
    Nathan Head

    Carl,

    That is not correct, the date that is being passed to the function in my example is the order date.

    0
    Comment actions Permalink
  • Avatar
    Carl Berman

    Ah ... ok

     

    Thanks

    0
    Comment actions Permalink
  • Avatar
    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!

    0
    Comment actions Permalink
  • Avatar
    Nathan Head

    @Willy B,

    Yes, you would just pass the date into GetDateValue(date variable here)

    And change: return od.AddDays(2);
    To: return od.AddDays(-4);

     

    EDIT: Sorry, I did not read the question correctly. 

    I will reply back with the correct solution

    0
    Comment actions Permalink
  • Avatar
    Carl

    Any progress on this? I was hoping that there is just a "addworkdays" type function, but otherwise I could put in a check to see if the day is a Saturday or Sunday and if so subtract another one or two days. Thoughts?

    0
    Comment actions Permalink
  • Avatar
    Nathan Head

    @...

    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 "&#xd;&#xa;"> ]>
    <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>
    0
    Comment actions Permalink
  • Avatar
    Carl

    Thanks very much for this Nathan. When I copy and paste I get an error "XSLT compile error. Could not find file 'source10.xsl'. Line: 55 , Position: 1" 

    Line 55 is the first line after the last </xsl:stylesheet> in your code.

    Is there some issue in the stylesheet here?

    Thanks!

     

    0
    Comment actions Permalink
  • Avatar
    Nathan Head

    @...

    Here is a much better solution.

    <!DOCTYPE xsl:stylesheet[ <!ENTITY nl "&#xd;&#xa;"> ]>
    <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>
    0
    Comment actions Permalink
  • Avatar
    Carl

    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 "&#xd;&#xa;"> ]>
    <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?

     

    0
    Comment actions Permalink
  • Avatar
    Nathan Head

    @...

    The first argument for AddBusinessDays() is expecting a DateTime value.

    0
    Comment actions Permalink
  • Avatar
    Carl

    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.

     

    0
    Comment actions Permalink

Please sign in to leave a comment.