Index: xml-xalan/c/src/xalanc/XalanEXSLT/XalanEXSLTDateTime.cpp
===================================================================
--- xml-xalan.orig/c/src/xalanc/XalanEXSLT/XalanEXSLTDateTime.cpp
+++ xml-xalan/c/src/xalanc/XalanEXSLT/XalanEXSLTDateTime.cpp
@@ -14,16 +14,14 @@
  * limitations under the License.
  */
 
+#include "XalanXSDateTime.hpp"
+#include "XalanXSDateTimeHelper.hpp"
+#include "XalanXSDateTimeException.hpp"
 #include "XalanEXSLTDateTime.hpp"
 #include "XalanEXSLTDateTimeImpl.hpp"
 
 
 
-#include <cstdio>
-#include <ctime>
-
-
-
 #include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
 
 
@@ -36,30 +34,6 @@ XALAN_CPP_NAMESPACE_BEGIN
 
 
 
-static const XalanEXSLTFunctionDateTime         s_dateTimeFunction;
-
-
-
-static const XalanDOMChar   s_dateTimeFunctionName[] =
-{
-    XalanUnicode::charLetter_d,
-    XalanUnicode::charLetter_a,
-    XalanUnicode::charLetter_t,
-    XalanUnicode::charLetter_e,
-    XalanUnicode::charHyphenMinus,
-    XalanUnicode::charLetter_t,
-    XalanUnicode::charLetter_i,
-    XalanUnicode::charLetter_m,
-    XalanUnicode::charLetter_e,
-    0
-};
-
-static const XalanEXSLTDateTimeFunctionsInstaller::FunctionTableEntry   theFunctionTable[] =
-{
-    { s_dateTimeFunctionName, &s_dateTimeFunction },
-    { 0, 0 }
-};
-
 static const XalanDOMChar   s_dateTimeNamespace[] =
 {
     XalanUnicode::charLetter_h,
@@ -99,166 +73,1613 @@ static const XalanDOMChar   s_dateTimeNa
 
 
 
-#if defined(XALAN_STRICT_ANSI_HEADERS)
-using std::sprintf;
-using std::time;
-using std::time_t;
-using std::tm;
-#endif
+static const XalanDOMChar   s_addFunctionName[] =
+{
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_d,
+    0
+};
+
 
 
+static const XalanDOMChar   s_addDurationFunctionName[] =
+{
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_u,
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    0
+};
 
-#if defined(XALAN_NO_REENTRANT_TIME_FUNCTIONS)
 
-#if defined(XALAN_STRICT_ANSI_HEADERS)
-using std::gmtime;
-using std::localtime;
-#endif
 
-static struct tm*
-localtime_r(const time_t *clock, struct tm *res)
+static const XalanDOMChar   s_dateFunctionName[] =
 {
-    assert( res != 0 );
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_e,
+    0
+};
 
-    struct tm * tmpTime = localtime(clock);
 
-    if (tmpTime == 0 )
-    {
-        return 0;
-    }
-    else
-    {
-        *res = *tmpTime;
 
-        return res;
-    }
-    
-}
+static const XalanDOMChar   s_dateTimeFunctionName[] =
+{
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_e,
+    0
+};
+
+
 
-static struct tm *
-gmtime_r(const time_t *clock, struct tm *res)
+static const XalanDOMChar   s_dayAbbreviationFunctionName[] =
 {
-    assert( res != 0 );
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_b,
+    XalanUnicode::charLetter_b,
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_v,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    0
+};
 
-    struct tm * tmpTime = gmtime(clock);
 
-    if (tmpTime == 0 )
-    {
-        return 0;
-    }
-    else
-    {
-        *res = *tmpTime;
 
-        return res;
-    }
-    
-}
+static const XalanDOMChar   s_dayInMonthFunctionName[] =
+{
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_h,
+    0
+};
+
 
-#endif
+
+static const XalanDOMChar   s_dayInWeekFunctionName[] =
+{
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_w,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_k,
+    0
+};
 
 
 
-XObjectPtr
-XalanEXSLTFunctionDateTime::execute(
-            XPathExecutionContext&          executionContext,
-            XalanNode*                      context,
-            const XObjectArgVectorType&     args,
-            const LocatorType*              locator) const
+static const XalanDOMChar   s_dayInYearFunctionName[] =
 {
-    if (args.size() != 0)
-    {
-        XalanDOMString theResult(executionContext.getMemoryManager());
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_r,
+    0
+};
+
+
+
+static const XalanDOMChar   s_dayNameFunctionName[] =
+{
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_e,
+	0
+};
+
 
-        executionContext.error(getError(theResult), context, locator);
-    }
 
-    XPathExecutionContext::GetAndReleaseCachedString    theGuard(executionContext);
+static const XalanDOMChar   s_dayOfWeekInMonthFunctionName[] =
+{
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_f,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_w,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_k,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_h,
+    0
+};
 
-    XalanDOMString&     theResult = theGuard.get();
-    
-    theResult.clear();
 
-    time_t long_time;
 
-    time( &long_time );
+static const XalanDOMChar   s_differenceFunctionName[] =
+{
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_f,
+    XalanUnicode::charLetter_f,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_c,
+    XalanUnicode::charLetter_e,
+    0
+};
 
-    struct tm localTime;
 
-    const struct tm*    ptrStrctTime = localtime_r(&long_time, &localTime);
 
-    if (ptrStrctTime != 0 )
-    {
-        struct tm gmtTime;
+static const XalanDOMChar   s_durationFunctionName[] =
+{
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_u,
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    0
+};
 
-        ptrStrctTime = gmtime_r(&long_time, &gmtTime);
 
-        if(ptrStrctTime != 0 )
-        {
 
-            const size_t    MAX_DATE_TIME_LEN = 1000;
-            char stringTime[MAX_DATE_TIME_LEN + 1];
+static const XalanDOMChar   s_formatDateFunctionName[] =
+{
+    XalanUnicode::charLetter_f,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_e,
+    0
+};
 
-            const size_t    result = strftime(stringTime, MAX_DATE_TIME_LEN, "%Y-%m-%dT%H:%M:%S", ptrStrctTime);
 
-            if (result != 0)
-            {
-                theResult.assign(stringTime);
-                
-                long localData = localTime.tm_year * 10000 + localTime.tm_mon * 100 + localTime.tm_mday;
-                long gmtData = gmtTime.tm_year * 10000 + gmtTime.tm_mon * 100 + gmtTime.tm_mday;
 
-                char timeZone[MAX_DATE_TIME_LEN+1];
-                
-                int offset = 0; 
+static const XalanDOMChar   s_hourInDayFunctionName[] =
+{
+    XalanUnicode::charLetter_h,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_u,
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_y,
+    0
+};
 
-                if( localData == gmtData )
-                {
-                    if(localTime.tm_hour == gmtTime.tm_hour)
-                    {
-                        offset = 100; //  much bigger then any legal offset
-                    }
-                    else
-                    {
-                        offset = localTime.tm_hour - gmtTime.tm_hour;
-                    }
-                }
-                else if(localData < gmtData)
-                {
-                    offset = localTime.tm_hour - gmtTime.tm_hour - 24;
-                }
-                else
-                {
-                    offset = localTime.tm_hour - gmtTime.tm_hour + 24;
-                }
 
-                if(offset == 100)
-                {
-                    sprintf(timeZone, "%s", "z");
-                }
-                else
-                {
-                    sprintf(timeZone, "%2.2d:00", offset);
-                }
 
-                theResult.append(timeZone);
-            }
-        }
-    }
+static const XalanDOMChar   s_leapYearFunctionName[] =
+{
+    XalanUnicode::charLetter_l,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_p,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_r,
+    0
+};
 
-    return executionContext.getXObjectFactory().createString(theResult);
-}
+
+
+static const XalanDOMChar   s_minuteInHourFunctionName[] =
+{
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_u,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_h,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_u,
+    XalanUnicode::charLetter_r,
+    0
+};
 
 
 
-const XalanDOMString&
-XalanEXSLTFunctionDateTime::getError(XalanDOMString&    theResult) const
+static const XalanDOMChar   s_monthAbbreviationFunctionName[] =
 {
-    return XalanMessageLoader::getMessage(
-                theResult,
-                XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
-                s_dateTimeFunctionName);
-}
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_h,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_b,
+    XalanUnicode::charLetter_b,
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_v,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    0
+};
+
+
+
+static const XalanDOMChar   s_monthInYearFunctionName[] =
+{
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_h,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_r,
+    0
+};
+
+
+
+static const XalanDOMChar   s_monthNameFunctionName[] =
+{
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_h,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_e,
+    0
+};
+
+
+
+static const XalanDOMChar   s_parseDateFunctionName[] =
+{
+    XalanUnicode::charLetter_p,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_r,
+    XalanUnicode::charLetter_s,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_e,
+    0
+};
+
+
+
+static const XalanDOMChar   s_secondInMinuteFunctionName[] =
+{
+    XalanUnicode::charLetter_s,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_c,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_u,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_e,
+    0
+};
+
+
+
+static const XalanDOMChar   s_secondsFunctionName[] =
+{
+    XalanUnicode::charLetter_s,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_c,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_d,
+    XalanUnicode::charLetter_s,
+    0
+};
+
+
+
+static const XalanDOMChar   s_sumFunctionName[] =
+{
+    XalanUnicode::charLetter_s,
+    XalanUnicode::charLetter_u,
+    XalanUnicode::charLetter_m,
+	0
+};
+
+
+
+static const XalanDOMChar   s_timeFunctionName[] =
+{
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_e,
+    0
+};
+
+
+
+static const XalanDOMChar   s_weekInMonthFunctionName[] =
+{
+    XalanUnicode::charLetter_w,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_k,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_m,
+    XalanUnicode::charLetter_o,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charLetter_t,
+    XalanUnicode::charLetter_h,
+    0
+};
+
+
+
+static const XalanDOMChar   s_weekInYearFunctionName[] =
+{
+    XalanUnicode::charLetter_w,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_k,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_i,
+    XalanUnicode::charLetter_n,
+    XalanUnicode::charHyphenMinus,
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_r,
+    0
+};
+
+
+
+static const XalanDOMChar   s_yearFunctionName[] =
+{
+    XalanUnicode::charLetter_y,
+    XalanUnicode::charLetter_e,
+    XalanUnicode::charLetter_a,
+    XalanUnicode::charLetter_r,
+    0
+};
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionDate01::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAccepts0Or1Arguments_1Param,
+                getFunctionName());
+}
+
+
+
+
+XObjectPtr
+XalanEXSLTFunctionDate01Number::execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const
+{
+	XObjectArgVectorType::size_type theSize = args.size();
+    if (theSize != 0 && theSize != 1)
+    {
+		XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+		XalanDOMString &theResult = theResultData.get();
+
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	double theResult = DoubleSupport::getNaN();
+	try
+	{
+		if (theSize == 0)
+		{
+			// Get current timestamp and use that as a default
+			XalanXSDateTime dt;
+			doExecute(dt, theResult);
+		}
+		else
+		{
+			XalanXSDateTime dt(executionContext.getMemoryManager(), args[0]->str());
+			doExecute(dt, theResult);
+		}
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: Warn?
+	}
+	return executionContext.getXObjectFactory().createNumber(theResult);
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionDate01String::execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+
+	XObjectArgVectorType::size_type theSize = args.size();
+    if (theSize != 0 && theSize != 1)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	try
+	{
+		if (theSize == 0)
+		{
+			// Get current timestamp & use that as a default
+			XalanXSDateTime dt;
+			doExecute(dt, theResult);
+		}
+		else
+		{
+			XalanXSDateTime dt(executionContext.getMemoryManager(), args[0]->str());
+			doExecute(dt, theResult);
+		}
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: Warn?
+		theResult.clear();
+	}
+	return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionAdd::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+    if (args.size() != 2)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	try
+	{
+		// Construct an XS date time with the current offset & format it
+		XalanXSDateTime dt1(executionContext.getMemoryManager(), args[0]->str());
+		XalanXSDateTime::xsType type = dt1.getType();
+		
+		if (type == XalanXSDateTime::xs_dateTime || type == XalanXSDateTime::xs_date ||
+			type == XalanXSDateTime::xs_gYearMonth || type == XalanXSDateTime::xs_gYear)
+		{
+			XalanXSDuration du(executionContext.getMemoryManager(), args[1]->str());
+			XalanXSDateTime dt2 = dt1.add(du);
+			dt2.formatXS(theResult);
+		}
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: Warn?
+		theResult.clear();
+	}
+    return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionAdd::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAcceptsTwoArguments_1Param,
+                s_addFunctionName);
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionAddDuration::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+    if (args.size() != 2)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	try
+	{
+		// Construct an XS date time with the current offset & format it
+		XalanXSDuration du1(executionContext.getMemoryManager(), args[0]->str());
+		XalanXSDuration du2(executionContext.getMemoryManager(), args[1]->str());
+		XalanXSDuration	du3 = du1.add(du2);
+		du3.formatXS(theResult);
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: Warn?
+		theResult.clear();
+	}
+    return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionAddDuration::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAcceptsTwoArguments_1Param,
+                s_addDurationFunctionName);
+}
+
+
+
+void
+XalanEXSLTFunctionDate::doExecute(
+			XalanXSDateTime&		arg, 
+			XalanDOMString&			theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date ||
+		type == XalanXSDateTime::xs_dateTime)
+	{
+		arg.setType(XalanXSDateTime::xs_date);
+		arg.formatXS(theResult);
+	}
+	// (else empty string)
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionDate::getFunctionName() const
+{
+	return s_dateFunctionName;
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionDateTime::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+
+    if (args.size() != 0)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	// Construct an XS date time with the current local time & format it
+	try
+	{
+		XalanXSDateTime dt;
+		dt.formatXS(theResult);
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: Error?
+		theResult.clear();
+	}
+	return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionDateTime::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAcceptsNoArgument_1Param,
+                s_dateTimeFunctionName);
+}
+
+
+
+void
+XalanEXSLTFunctionDayAbbreviation::doExecute(
+			XalanXSDateTime&		arg, 
+			XalanDOMString&			theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date ||
+		type == XalanXSDateTime::xs_dateTime)
+	{
+		arg.getShortDayName(theResult);
+	}
+	// (else empty string on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionDayAbbreviation::getFunctionName() const
+{
+	return s_dayAbbreviationFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionDayInMonth::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date || type == XalanXSDateTime::xs_dateTime ||
+		type == XalanXSDateTime::xs_gMonthDay || type == XalanXSDateTime::xs_gDay)
+	{
+		theResult = arg.getDay();
+	}
+	// (else NaN on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionDayInMonth::getFunctionName() const
+{
+    return s_dayInMonthFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionDayInWeek::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date || type == XalanXSDateTime::xs_dateTime)
+	{
+		theResult = 1 + arg.getDayInWeek();
+	}
+	// (else NaN on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionDayInWeek::getFunctionName() const
+{
+    return s_dayInWeekFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionDayInYear::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date || type == XalanXSDateTime::xs_dateTime)
+	{
+		theResult = arg.getDayInYear();
+	}
+	// (else NaN on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionDayInYear::getFunctionName() const
+{
+    return s_dayInYearFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionDayName::doExecute(
+			XalanXSDateTime&		arg, 
+			XalanDOMString&			theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date ||
+		type == XalanXSDateTime::xs_dateTime)
+	{
+		arg.getDayName(theResult);
+	}
+	// (else empty string on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionDayName::getFunctionName() const
+{
+	return s_dayNameFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionDayOfWeekInMonth::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date || type == XalanXSDateTime::xs_dateTime)
+	{
+		theResult = arg.getDayOfWeekInMonth();
+	}
+	// (else NaN on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionDayOfWeekInMonth::getFunctionName() const
+{
+    return s_dayOfWeekInMonthFunctionName;
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionDateDifference::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+
+    if (args.size() != 2)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	try
+	{
+		// Construct an XS date time with the current offset & format it
+		XalanXSDateTime dt1(executionContext.getMemoryManager(), args[0]->str());
+		XalanXSDateTime dt2(executionContext.getMemoryManager(), args[1]->str());
+
+		// Check EXSLT type rules
+		bool firstOk = 
+			 (dt1.getType() == XalanXSDateTime::xs_date || dt1.getType() == XalanXSDateTime::xs_dateTime ||
+			  dt1.getType() == XalanXSDateTime::xs_gYearMonth || dt1.getType() == XalanXSDateTime::xs_gYear);
+		bool secondOk =
+			 (dt2.getType() == XalanXSDateTime::xs_date || dt2.getType() == XalanXSDateTime::xs_dateTime ||
+			  dt2.getType() == XalanXSDateTime::xs_gYearMonth || dt2.getType() == XalanXSDateTime::xs_gYear);
+
+		// Diff & format if possible, otherwise return an empty string
+		if (firstOk && secondOk)
+		{
+			XalanXSDuration du = dt2.difference(dt1);
+			du.formatXS(theResult);
+		}
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: warn?
+		theResult.clear();
+	}
+    return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionDateDifference::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAcceptsTwoArguments_1Param,
+                s_differenceFunctionName);
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionDuration::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+
+    if (args.size() != 1)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	try
+	{
+		double seconds = args[0]->num();
+
+		if (!DoubleSupport::isPositiveInfinity(seconds) &&
+			!DoubleSupport::isNegativeInfinity(seconds) &&
+			!DoubleSupport::isNaN(seconds))
+		{
+			XalanXSDuration du(seconds);
+			du.formatXS(theResult);
+		}
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: warn?
+		theResult.clear();
+	}
+	return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionDuration::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
+                s_durationFunctionName);
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionFormatDate::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+
+    if (args.size() != 2)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	// Parse the date & format it according to the JDK pattern
+	try
+	{
+		XalanXSDateTime dt(executionContext.getMemoryManager(), args[0]->str());
+		dt.formatJDK(args[1]->str(), theResult);
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: warn?
+		theResult.clear();
+	}
+    return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionFormatDate::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAcceptsTwoArguments_1Param,
+                s_formatDateFunctionName);
+}
+
+
+
+void
+XalanEXSLTFunctionHourInDay::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_time || type == XalanXSDateTime::xs_dateTime)
+	{
+		theResult = arg.getHour();
+	}
+	// (else NaN on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionHourInDay::getFunctionName() const
+{
+    return s_hourInDayFunctionName;
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionLeapYear::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XObjectArgVectorType::size_type theSize = args.size();
+    if (theSize != 0 && theSize != 1)
+    {
+		XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+		XalanDOMString &theResult = theResultData.get();
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	bool theResult = false;
+	bool haveResult = false;
+	try
+	{
+		if (theSize == 0)
+		{
+			XalanXSDateTime dt;
+			theResult = isLeap(dt.getYear());
+			haveResult = true;
+		}
+		else
+		{
+			XalanXSDateTime dt(executionContext.getMemoryManager(), args[0]->str());
+			XalanXSDateTime::xsType type = dt.getType();
+			if (type == XalanXSDateTime::xs_date || type == XalanXSDateTime::xs_dateTime ||
+				type == XalanXSDateTime::xs_gYearMonth || type == XalanXSDateTime::xs_gYear)
+			{
+				theResult = isLeap(dt.getYear());
+				haveResult = true;
+			}
+			// (else NaN on incorrect input date format)			
+		}
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: warn?
+	}
+	if (!haveResult)
+	{
+		return executionContext.getXObjectFactory().createNumber(DoubleSupport::getNaN());
+	}
+	else
+	{
+		return executionContext.getXObjectFactory().createBoolean(theResult);
+	}
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionLeapYear::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAccepts0Or1Arguments_1Param,
+                s_leapYearFunctionName);
+}
+
+
+
+void
+XalanEXSLTFunctionMinuteInHour::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_time || type == XalanXSDateTime::xs_dateTime)
+	{
+		theResult = arg.getMinute();
+	}
+	// (else NaN on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionMinuteInHour::getFunctionName() const
+{
+    return s_minuteInHourFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionMonthAbbreviation::doExecute(
+			XalanXSDateTime&		arg, 
+			XalanDOMString&			theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date ||	type == XalanXSDateTime::xs_dateTime ||
+		type == XalanXSDateTime::xs_gYearMonth || type == XalanXSDateTime::xs_gMonth ||
+		type == XalanXSDateTime::xs_gMonthDay) // I expect this was a cut & paste error in the spec
+	{
+		arg.getShortMonthName(theResult);
+	}
+	// (else empty string on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionMonthAbbreviation::getFunctionName() const
+{
+	return s_monthAbbreviationFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionMonthInYear::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date || type == XalanXSDateTime::xs_dateTime ||
+		type == XalanXSDateTime::xs_gYearMonth || type == XalanXSDateTime::xs_gMonth ||
+		type == XalanXSDateTime::xs_gMonthDay)
+	{
+		theResult = arg.getMonth();
+	}
+	// (else NaN on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionMonthInYear::getFunctionName() const
+{
+    return s_monthInYearFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionMonthName::doExecute(
+			XalanXSDateTime&		arg, 
+			XalanDOMString&			theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date ||	type == XalanXSDateTime::xs_dateTime ||
+		type == XalanXSDateTime::xs_gYearMonth || type == XalanXSDateTime::xs_gMonth ||
+		type == XalanXSDateTime::xs_gMonthDay) // I expect this was a cut & paste error in the spec
+	{
+		arg.getMonthName(theResult);
+	}
+	// (else empty string on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionMonthName::getFunctionName() const
+{
+	return s_monthNameFunctionName;
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionParseDate::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+
+    if (args.size() != 2)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	// Parse according to JDK
+	try
+	{
+		XalanXSDateTime dt(args[0]->str(), args[1]->str());
+		dt.formatXS(theResult);
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: warn?
+		theResult.clear();
+	}
+    return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionParseDate::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAcceptsTwoArguments_1Param,
+                s_parseDateFunctionName);
+}
+
+
+
+void
+XalanEXSLTFunctionSecondInMinute::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_time || type == XalanXSDateTime::xs_dateTime)
+	{
+		theResult = arg.getSecond();
+	}
+	// (else NaN on incorrect input date format)			
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionSecondInMinute::getFunctionName() const
+{
+    return s_secondInMinuteFunctionName;
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionSeconds::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XObjectArgVectorType::size_type theSize = args.size();
+    if (theSize != 0 && theSize != 1)
+    {
+		XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+		XalanDOMString &theResult = theResultData.get();
+
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	double theResult = DoubleSupport::getNaN();
+	try
+	{
+		if (theSize == 0)
+		{
+			XalanXSDateTime dtCurrent;
+			XalanXSDateTime dtEpoch(1970, 1, 1, 0, 0, 0.0, 0);
+			XalanXSDuration du = dtCurrent.difference(dtEpoch);
+			theResult = du.inSeconds();
+		}
+		else
+		{
+			const XalanDOMString &input = args[0]->str();
+			
+			// See if this is a duration
+			if ((input.length() > 0 && input[0] == XalanUnicode::charLetter_P) ||
+				(input.length() > 1 && input[1] == XalanUnicode::charLetter_P))
+			{
+				XalanXSDuration du(executionContext.getMemoryManager(), input);
+				theResult = du.inSeconds();
+			}
+			else
+			{
+				XalanXSDateTime dt(executionContext.getMemoryManager(), args[0]->str());
+				XalanXSDateTime::xsType type = dt.getType();
+				if (type == XalanXSDateTime::xs_dateTime || type == XalanXSDateTime::xs_date ||
+					type == XalanXSDateTime::xs_gYearMonth || type == XalanXSDateTime::xs_gYear)
+				{
+					XalanXSDateTime dtEpoch(1970, 1, 1, 0, 0, 0.0, 0);
+					dt.setType(XalanXSDateTime::xs_dateTime);
+					XalanXSDuration du = dt.difference(dtEpoch);
+					theResult = du.inSeconds();
+				}
+			}
+			// (else NaN on incorrect input date format)			
+		}
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: warn?
+	}
+    return executionContext.getXObjectFactory().createNumber(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionSeconds::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAccepts0Or1Arguments_1Param,
+                s_secondsFunctionName);
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionSum::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+
+    if (args.size() != 1)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+	// Input must be a nodeset
+	if (args[0]->getType() != XObject::eTypeNodeSet)
+	{
+		return executionContext.getXObjectFactory().createString(theResult);
+	}
+
+	try
+	{
+		XalanXSDuration theSum(0);
+
+		// Run for each node in the input set
+		const NodeRefListBase &theNodeSet = args[0]->nodeset();
+		if (theNodeSet.getLength() > 0)
+		{
+			for (unsigned int i = 0; i < theNodeSet.getLength(); ++i)
+			{
+				XalanNode *node = theNodeSet.item(i);
+				if (!node)
+					continue;
+
+				XPathExecutionContext::GetAndReleaseCachedString theNodeData(executionContext);
+				XalanDOMString &nodeData = theNodeData.get();
+				DOMServices::getNodeData(*node, nodeData);
+
+				XalanXSDuration thisDuration(executionContext.getMemoryManager(), nodeData);
+				theSum = theSum.add(thisDuration);
+			}
+			theSum.formatXS(theResult);
+		}
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: warn?
+		theResult.clear();
+	}
+    return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionSum::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAcceptsOneArgument_1Param,
+                s_sumFunctionName);
+}
+
+
+
+XObjectPtr
+XalanEXSLTFunctionTime::execute(
+            XPathExecutionContext&          executionContext,
+            XalanNode*                      context,
+            const XObjectArgVectorType&     args,
+            const LocatorType*              locator) const
+{
+	XPathExecutionContext::GetAndReleaseCachedString theResultData(executionContext);
+	XalanDOMString &theResult = theResultData.get();
+	XObjectArgVectorType::size_type theSize = args.size();
+    if (theSize != 0 && theSize != 1)
+    {
+        executionContext.error(getError(theResult), context, locator);
+    }
+
+	try
+	{
+		if (theSize == 0)
+		{
+			// Get current timestamp & truncate to time
+			XalanXSDateTime dt;
+			dt.setType(XalanXSDateTime::xs_time);
+			dt.formatXS(theResult);
+		}
+		else
+		{
+			const XalanDOMString &input = args[0]->str();
+			XalanXSDateTime dt(executionContext.getMemoryManager(), input);
+			XalanXSDateTime::xsType type = dt.getType();
+
+			if (type == XalanXSDateTime::xs_time || type == XalanXSDateTime::xs_dateTime)
+			{
+				// Check if the input string had a timezone
+				bool hasTZ = false;
+				if (0 < input.length() && input[input.length() - 1] == XalanUnicode::charLetter_Z)
+				{
+					hasTZ = true;
+				}
+				else if (7 < input.length())
+				{
+					// +/- are not allowed in intermediate fields so this is a good enough
+					// test
+					if (input[input.length() - 6] == XalanUnicode::charPlusSign ||
+						input[input.length() - 6] == XalanUnicode::charHyphenMinus)
+					{
+						hasTZ = true;
+					}
+				}
+
+				dt.setType(XalanXSDateTime::xs_time);
+				dt.formatXS(theResult);
+
+				// Input didn't have a timezone => offset is 0 so chop 'Z' off the end
+				// of the formatted string
+				if (!hasTZ && theResult.length() > 0)
+				{
+					theResult.resize(theResult.length() - 1);
+				}
+			}
+		}
+	}
+	catch (const XalanXSDateTimeException &)
+	{
+		// XXX: Warn?
+		theResult.clear();
+	}
+    return executionContext.getXObjectFactory().createString(theResult);
+}
+
+
+
+const XalanDOMString&
+XalanEXSLTFunctionTime::getError(XalanDOMString&    theResult) const
+{
+    return XalanMessageLoader::getMessage(
+                theResult,
+                XalanMessages::EXSLTFunctionAccepts0Or1Arguments_1Param,
+                s_timeFunctionName);
+}
+
+
+
+void
+XalanEXSLTFunctionWeekInMonth::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date || type == XalanXSDateTime::xs_dateTime)
+	{
+		theResult = arg.getWeekInMonth();
+	}
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionWeekInMonth::getFunctionName() const
+{
+	return s_weekInMonthFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionWeekInYear::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date || type == XalanXSDateTime::xs_dateTime)
+	{
+		theResult = arg.getWeekInYear();
+	}
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionWeekInYear::getFunctionName() const
+{
+	return s_weekInYearFunctionName;
+}
+
+
+
+void
+XalanEXSLTFunctionYear::doExecute(
+			XalanXSDateTime&				arg,
+			double&							theResult) const
+{
+	XalanXSDateTime::xsType type = arg.getType();
+	if (type == XalanXSDateTime::xs_date || type == XalanXSDateTime::xs_dateTime ||
+		type == XalanXSDateTime::xs_gYear || type == XalanXSDateTime::xs_gYearMonth)
+	{
+		theResult = arg.getYear();
+	}
+}
+
+
+
+const XalanDOMChar *
+XalanEXSLTFunctionYear::getFunctionName() const
+{
+	return s_yearFunctionName;
+}
+
+
+
+static const XalanEXSLTFunctionAdd		         s_addFunction;
+static const XalanEXSLTFunctionAddDuration       s_addDurationFunction;
+static const XalanEXSLTFunctionDate				 s_dateFunction;
+static const XalanEXSLTFunctionDateTime          s_dateTimeFunction;
+static const XalanEXSLTFunctionDayAbbreviation   s_dayAbbreviationFunction;
+static const XalanEXSLTFunctionDayInMonth        s_dayInMonthFunction;
+static const XalanEXSLTFunctionDayInWeek         s_dayInWeekFunction;
+static const XalanEXSLTFunctionDayInYear         s_dayInYearFunction;
+static const XalanEXSLTFunctionDayName			 s_dayNameFunction;
+static const XalanEXSLTFunctionDayOfWeekInMonth  s_dayOfWeekInMonthFunction;
+static const XalanEXSLTFunctionDateDifference    s_differenceFunction;
+static const XalanEXSLTFunctionDuration          s_durationFunction;
+static const XalanEXSLTFunctionFormatDate        s_formatDateFunction;
+static const XalanEXSLTFunctionHourInDay         s_hourInDayFunction;
+static const XalanEXSLTFunctionLeapYear          s_leapYearFunction;
+static const XalanEXSLTFunctionMinuteInHour      s_minuteInHourFunction;
+static const XalanEXSLTFunctionMonthAbbreviation s_monthAbbreviationFunction;
+static const XalanEXSLTFunctionMonthInYear       s_monthInYearFunction;
+static const XalanEXSLTFunctionMonthName         s_monthNameFunction;
+static const XalanEXSLTFunctionParseDate         s_parseDateFunction;
+static const XalanEXSLTFunctionSecondInMinute    s_secondInMinuteFunction;
+static const XalanEXSLTFunctionSeconds           s_secondsFunction;
+static const XalanEXSLTFunctionSum               s_sumFunction;
+static const XalanEXSLTFunctionTime              s_timeFunction;
+static const XalanEXSLTFunctionWeekInMonth       s_weekInMonthFunction;
+static const XalanEXSLTFunctionWeekInYear        s_weekInYearFunction;
+static const XalanEXSLTFunctionYear              s_yearFunction;
+
+
+
+static const XalanEXSLTDateTimeFunctionsInstaller::FunctionTableEntry   theFunctionTable[] =
+{
+    { s_addFunctionName,				&s_addFunction },
+    { s_addDurationFunctionName,		&s_addDurationFunction },
+    { s_dateFunctionName,				&s_dateFunction },
+    { s_dateTimeFunctionName,			&s_dateTimeFunction },
+    { s_dayAbbreviationFunctionName,	&s_dayAbbreviationFunction },
+    { s_dayInMonthFunctionName,			&s_dayInMonthFunction },
+    { s_dayInWeekFunctionName,			&s_dayInWeekFunction },
+    { s_dayInYearFunctionName,			&s_dayInYearFunction },
+    { s_dayNameFunctionName,			&s_dayNameFunction },
+    { s_dayInWeekFunctionName,			&s_dayInWeekFunction },
+    { s_dayOfWeekInMonthFunctionName,	&s_dayOfWeekInMonthFunction },
+    { s_differenceFunctionName,			&s_differenceFunction },
+    { s_durationFunctionName,			&s_durationFunction },
+    { s_formatDateFunctionName,			&s_formatDateFunction },
+    { s_hourInDayFunctionName,			&s_hourInDayFunction },
+    { s_leapYearFunctionName,			&s_leapYearFunction },
+    { s_minuteInHourFunctionName,		&s_minuteInHourFunction },
+    { s_monthAbbreviationFunctionName,	&s_monthAbbreviationFunction },
+    { s_monthInYearFunctionName,		&s_monthInYearFunction },
+    { s_monthNameFunctionName,			&s_monthNameFunction },
+    { s_parseDateFunctionName,			&s_parseDateFunction },
+    { s_secondInMinuteFunctionName,		&s_secondInMinuteFunction },
+    { s_secondsFunctionName,			&s_secondsFunction },
+    { s_sumFunctionName,				&s_sumFunction },
+    { s_timeFunctionName,				&s_timeFunction },
+    { s_weekInMonthFunctionName,		&s_weekInMonthFunction },
+	{ s_weekInYearFunctionName,			&s_weekInYearFunction },
+    { s_yearFunctionName,				&s_yearFunction },
+    { 0, 0 }
+};
 
 
 
Index: xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTime.cpp
===================================================================
--- /dev/null
+++ xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTime.cpp
@@ -0,0 +1,2289 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "XalanXSDateTime.hpp"
+#include "XalanXSDateTimeException.hpp"
+#include "XalanXSDateTimeHelper.hpp"
+
+
+#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
+#include <xalanc/PlatformSupport/XalanUnicode.hpp>
+
+
+
+#include <cmath>
+#include <ctime>
+
+
+
+#if defined(XALAN_STRICT_ANSI_HEADERS)
+XALAN_USING_STD(fmod);
+#endif
+
+
+
+XALAN_CPP_NAMESPACE_BEGIN
+
+
+
+#if defined(XALAN_STRICT_ANSI_HEADERS)
+using std::time;
+using std::time_t;
+using std::tm;
+#endif
+
+
+
+#if defined(XALAN_NO_REENTRANT_TIME_FUNCTIONS)
+
+#if defined(XALAN_STRICT_ANSI_HEADERS)
+using std::gmtime;
+using std::localtime;
+#endif
+
+static struct tm*
+localtime_r(const time_t *clock, struct tm *res)
+{
+    assert( res != 0 );
+
+    struct tm * tmpTime = localtime(clock);
+
+    if (tmpTime == 0 )
+    {
+        return 0;
+    }
+    else
+    {
+        *res = *tmpTime;
+
+        return res;
+    }
+    
+}
+
+static struct tm *
+gmtime_r(const time_t *clock, struct tm *res)
+{
+    assert( res != 0 );
+
+    struct tm * tmpTime = gmtime(clock);
+
+    if (tmpTime == 0 )
+    {
+        return 0;
+    }
+    else
+    {
+        *res = *tmpTime;
+
+        return res;
+    }
+    
+}
+
+#endif
+
+
+
+XalanXSDateTime::XalanXSDateTime()
+{
+	time_t long_time;
+    time( &long_time );
+
+	// Store the local time
+    struct tm localTime;
+    if (!localtime_r(&long_time, &localTime))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::Current);
+	m_year		= localTime.tm_year + 1900;
+	m_month		= localTime.tm_mon + 1;
+	m_day		= localTime.tm_mday;
+	m_hour		= localTime.tm_hour;
+	m_minute	= localTime.tm_min;
+	m_second	= (double)localTime.tm_sec;
+	m_offset	= 0;
+
+	// Get UTC for offset
+    struct tm gmTime;
+	if (!gmtime_r(&long_time, &gmTime))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::Current);
+	XalanXSDateTime utcXS(gmTime.tm_year, gmTime.tm_mon + 1, gmTime.tm_mday, 
+						  gmTime.tm_hour, gmTime.tm_min, (double)gmTime.tm_sec, 0);
+
+	// Work out the local offset from GMT
+	XalanXSDuration offset = difference(utcXS);
+
+	// Convert offset to minutes & store
+	m_offset = offset.getMinutes() + offset.getHours() * 60 + offset.getDays() * 1440;
+	if (offset.getNegative())
+	{
+		m_offset = -m_offset;
+	}
+
+	// We have a full date/time
+	m_type = xs_dateTime;
+}
+
+
+
+XalanXSDuration XalanXSDateTime::difference(const XalanXSDateTime &other) const
+{
+	XalanXSDateTime lhs(*this);
+	XalanXSDateTime rhs(other);
+
+	// Truncate to least specific date format
+	if (lhs.m_type < rhs.m_type)
+		rhs.setType(lhs.m_type);
+	else
+		lhs.setType(rhs.m_type);
+
+	if (lhs.m_type == xs_gDay)
+	{
+		return XalanXSDuration(0, 0, lhs.m_day - rhs.m_day);
+	}
+	// If years only, return a years duration
+	if (lhs.m_type == xs_gYear)
+	{
+		return XalanXSDuration(lhs.m_year - rhs.m_year);
+	}
+	// If months only, return a months duration
+	if (lhs.m_type == xs_gMonth)
+	{
+		return XalanXSDuration(0, lhs.m_month - rhs.m_month);
+	}
+	// If months/years only, return a months/years duration
+	if (lhs.m_type == xs_gYearMonth)
+	{
+		int years = lhs.m_year - rhs.m_year;
+		int months = lhs.m_month - rhs.m_month;
+
+		// If years & months have the same sign then we can 
+		// do this as a aYbM
+		if (years == 0)
+			return XalanXSDuration(years);
+		if (months == 0)
+			return XalanXSDuration(0, months);
+		if ((years < 0 && months < 0) || (years > 0 && months > 0))
+		{
+			return XalanXSDuration(years, months);
+		}
+
+		// Otherwise do it all in months (speculatively)
+		return XalanXSDuration(0, 12 * (lhs.m_year - rhs.m_year) + lhs.m_month - rhs.m_month);
+	}
+
+	// If month/day, we just have to diff those fields as without a year,
+	// we can't tell how long a month is
+	if (lhs.m_type == xs_gMonthDay)
+	{
+		return XalanXSDuration(0, lhs.m_month - rhs.m_month, lhs.m_day - rhs.m_day);
+	}
+
+	// Treat complete dates in d/h/m/s
+	int days = 0;
+	if (lhs.m_type == xs_date || lhs.m_type == xs_dateTime)
+	{
+		days = (daysFrom1AD(lhs.m_year, lhs.m_month) + lhs.m_day) - 
+			   (daysFrom1AD(rhs.m_year, rhs.m_month) + rhs.m_day);
+	}
+
+	// Do the time portion all in seconds
+	double t1 = lhs.m_hour * 3600.0 + lhs.m_minute * 60.0 + lhs.m_second - lhs.m_offset * 60.0;
+	double t2 = rhs.m_hour * 3600.0 + rhs.m_minute * 60.0 + rhs.m_second - rhs.m_offset * 60.0;
+	double seconds = t1 - t2;
+
+	// Adjust if days/seconds have different signs
+	// Might need to do more than once as timezone differences can throw seconds > 2 * 86400.0
+	for (;;)
+	{
+		if (days > 0 && seconds < 0)
+		{
+			--days;
+			seconds += 86400.0;
+		}
+		else if (days < 0 && seconds > 0)
+		{
+			++days;
+			seconds -= 86400.0;
+		}
+		else
+		{
+			break;
+		}
+	}
+
+
+
+	// Adjust days
+	days += (int)(seconds / 86400.0);
+
+	// Convert to a time with normal h/m/s ranges
+	seconds = fmod(seconds, 86400.0);
+	int hours = (int)(seconds / 3600.0);
+	seconds = fmod(seconds, 3600.0);
+	int minutes = (int)(seconds / 60.0);
+	seconds = fmod(seconds, 60.0);
+	return XalanXSDuration(0, 0, days, hours, minutes, seconds);
+}
+
+
+
+XalanXSDateTime XalanXSDateTime::add(const XalanXSDuration &duration) const
+{
+	/* Algorithm mostly from:
+
+		http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
+
+	   Modified to cope with missing year 0 as described by same document;
+	   and to account for the fractional part of seconds.
+	 */
+
+	// Months (may be modified additionally below)
+	double temp = m_month + duration.getMonths();
+	int eMonth = modulo(temp, 1, 13);
+	int carry = fQuotient(temp, 1, 13);
+
+	// Years (may be modified additionally below)
+	int eYear = m_year + duration.getYears() + carry;
+
+	// Fix for discontinuity at year 0
+	if (eYear == 0)
+	{
+		if (m_year > 0)
+			eYear--;
+		else
+			eYear++;
+	}
+	
+	// Zone
+	int eOffset = m_offset;
+
+	// Seconds
+	temp = m_second + duration.getSeconds();
+	double eSecond = fmod(temp, 60.0);
+	if (eSecond < 0)
+		eSecond += 60.0;
+	carry = fQuotient(temp, 60);
+
+	// Minutes
+	temp = m_minute + duration.getMinutes() + carry;
+	int eMinute = modulo(temp, 60);
+	carry = fQuotient(temp, 60);
+
+	// Hours 
+	temp = m_hour + duration.getHours() + carry;
+	int eHour = modulo(temp, 24);
+	carry = fQuotient(temp, 24);
+
+	// Days 
+	int tempDays = maximumDayInMonthFor(eYear, eMonth); 
+	if (m_day > tempDays)
+		;
+	else if (m_day < 1)
+		tempDays = 1;
+	else
+		tempDays = m_day;
+	int eDay = tempDays + duration.getDays() + carry;
+
+	for (;;)
+	{
+		if (eDay < 1)
+		{
+			eDay += maximumDayInMonthFor(eYear, eMonth - 1);
+			carry = -1;
+		}
+		else
+		{
+			int maxDays = maximumDayInMonthFor(eYear, eMonth);
+			if (eDay > maxDays)
+			{
+				eDay -= maxDays;
+				carry = 1;
+			}
+			else
+			{
+				break;
+			}
+		}
+		temp = eMonth + carry;
+		eMonth = modulo(temp, 1, 13);
+		eYear += fQuotient(temp, 1, 13);
+
+		// Adjust for discontinuity at year 0
+		if (eYear == 0)
+		{
+			if (temp < 1)
+				--eYear;
+			else
+				++eYear;
+		}
+	}
+
+	// Form up the result
+	XalanXSDateTime result(eYear, eMonth, eDay, eHour, eMinute, eSecond, eOffset);
+	result.setType(m_type);
+	return result;
+}
+
+
+
+void XalanXSDateTime::setType(xsType type)
+{
+	m_type = type;
+
+	// Clear unused fields (set to minimum)
+	switch (m_type)
+	{
+	case xs_time:
+		m_year = m_day = m_month = 1;
+		break;
+	case xs_gDay:
+		m_year = m_month = 1; // ?
+		m_hour = m_minute = 0;
+		m_second = 0.0;
+		break;
+	case xs_gMonth:
+		m_year = 1;
+		m_day = 1;
+		m_hour = m_minute = 0;
+		m_second = 0.0;
+		break;
+	case xs_gMonthDay:
+		m_year = 1;
+		m_hour = m_minute = 0;
+		m_second = 0.0;
+		break;
+	case xs_gYear:
+		m_day = 1;
+		m_month = 1;
+		m_hour = m_minute = 0;
+		m_second = 0.0;
+		break;
+	case xs_gYearMonth:
+		m_day = 1;
+		m_hour = m_minute = 0;
+		m_second = 0.0;
+		break;
+	case xs_date:
+		m_hour = m_minute = 0;
+		m_second = 0.0;
+		break;
+	case xs_dateTime:
+		break;
+	}
+}
+
+	
+	
+void XalanXSDateTime::parseTimeZone(const XalanDOMString &theTime, XalanDOMString::size_type offset)
+{
+	// Timezone is optional
+	if (offset >= theTime.length())
+		return;
+
+	// Zero
+	if ( theTime[offset] == XalanUnicode::charLetter_Z )
+	{
+		++offset;
+		if (offset != theTime.length())
+		{
+			throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+		}
+		return;
+	}
+
+	// -/+
+	bool negative = false;
+	if ( theTime[offset] == XalanUnicode::charHyphenMinus )
+	{
+		negative = true;
+	}
+	else if ( theTime[offset] != XalanUnicode::charPlusSign )
+	{
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+	}
+	++offset;
+
+	// hh
+	int hh = parse2DigitInt(theTime, offset);
+	offset += 2;
+	if (hh < 0 || hh > 14)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidTimeZone);
+
+	// :
+	if (offset >= theTime.length())
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	if (theTime[offset++] != XalanUnicode::charColon)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+
+	// mm
+	int mm = parse2DigitInt(theTime, offset);
+	offset += 2;
+	if ((mm < 0 || mm > 59) || (hh == 14 && mm != 0))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidTimeZone);
+
+	// Must be end of string
+	if (offset != theTime.length())
+	{
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+	}
+
+	m_offset = hh * 60 + mm;
+	if (negative)
+	{
+		m_offset = -m_offset;
+	}
+}
+
+
+
+void XalanXSDateTime::parseTime(
+	MemoryManagerType&			theMemoryManager,
+	const XalanDOMString&		theTime, 
+	XalanDOMString::size_type	offset)
+{
+	// hh
+	m_hour = parse2DigitInt(theTime, offset);
+	offset += 2;
+	if (offset >= theTime.length())
+	{
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	}
+
+	// :
+	if (theTime[offset] != XalanUnicode::charColon)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+	++offset;
+	if (offset >= theTime.length())
+	{
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	}
+
+	// mm
+	m_minute = parse2DigitInt(theTime, offset);
+	offset += 2;
+	if (offset >= theTime.length())
+	{
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+	}
+
+	// :
+	if (theTime[offset] != XalanUnicode::charColon)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+	++offset;
+	if (offset >= theTime.length())
+	{
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	}
+
+	// ss.ssss
+	m_second = parse2DigitInt(theTime, offset);
+	offset += 2;
+	if (offset >= theTime.length())
+	{
+		// No timezone, ok
+		return;
+	}
+
+	// Check for fractional part
+	if (theTime[offset] == XalanUnicode::charFullStop)
+	{
+		// Yes, find the end of it
+		XalanDOMString::size_type secondsStart = offset;
+		for (++offset;
+			 offset < theTime.length() &&
+					  theTime[offset] >= XalanUnicode::charDigit_0 && theTime[offset] <= XalanUnicode::charDigit_9;
+			 ++offset)
+		{
+		}
+
+		// Must not just have '.'
+		if (offset == secondsStart)
+			throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+
+		// Copy fractional part & parse as a double
+		XalanDOMString theSecondString(theMemoryManager);
+		theTime.substr(theSecondString, secondsStart, offset - secondsStart);
+		m_second += DOMStringToDouble(theSecondString, theSecondString.getMemoryManager());
+	}
+
+	// Timezone
+	parseTimeZone(theTime, offset);
+}
+
+
+
+void XalanXSDateTime::parse(MemoryManagerType &theMemoryManager, const XalanDOMString &theDate)
+{
+	// Default initialise everything to the minimum allowable for the type
+	m_month		= 1;
+	m_day		= 1;
+	m_year		= 1;
+	m_hour		= 0;
+	m_minute	= 0;
+	m_second	= 0.0;
+	m_offset	= 0;
+
+	XalanDOMString::size_type index = 0;
+
+	// Peek to determine format
+	if (0 < theDate.length() && theDate[0] == XalanUnicode::charHyphenMinus)
+	{
+		// datetime, date, time, gMonthDay, gDay, gMonth
+		if (1 < theDate.length() && theDate[1] == XalanUnicode::charHyphenMinus)
+		{
+			// gMonthDay, gDay, gMonth
+			if (5 == theDate.length() && theDate[2] == XalanUnicode::charHyphenMinus)
+			{
+				// gDay
+				m_day = parse2DigitInt(theDate, 3);
+				m_type = xs_gDay;
+				validate();
+				return;
+			}
+			else
+			{
+				// gMonthDay, gMonth
+				if (theDate.length() == 7 && theDate[4] == XalanUnicode::charHyphenMinus)
+				{
+					// gMonthDay
+					m_month = parse2DigitInt(theDate, 2);
+					m_day = parse2DigitInt(theDate, 5);
+					m_type = xs_gMonthDay;
+					validate();
+					return;
+				}
+				else if (theDate.length() == 6 && 
+						 (theDate[4] == XalanUnicode::charHyphenMinus ||
+						  theDate[5] == XalanUnicode::charHyphenMinus))
+				{
+					// gMonth
+					m_month = parse2DigitInt(theDate, 2);
+					m_type = xs_gMonth;
+					validate();
+					return;
+				}
+				else
+				{
+					throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+				}
+			}
+		}
+	}
+	
+	// datetime, date, time 
+	if (2 < theDate.length() && theDate[2] == XalanUnicode::charColon)
+	{
+		// time
+		parseTime(theMemoryManager, theDate, 0);
+		m_type = xs_time;
+		validate();
+		return;
+	}
+
+	// datetime, date
+	if (index >= theDate.length())
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+
+	// Year is a bit special: must be a minimum 4 digit integer (except 0000,
+	// handled separately by validate), and any larger integers may not have
+	// leading zeroes).  So we'll check the pattern then parse as a standard
+	// integer.
+	XalanDOMString::size_type yearStart = index;
+	
+	// May have -
+	if (theDate[yearStart] == XalanUnicode::charHyphenMinus)
+	{
+		++yearStart;
+		if (yearStart >= theDate.length())
+			throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	}
+	// Count leading zeroes
+	unsigned int yearLeadingZeroes = 0;
+	unsigned int yearDigits = 0;
+	for (; yearStart < theDate.length() && theDate[yearStart] == XalanUnicode::charDigit_0; ++yearStart)
+	{
+		++yearLeadingZeroes;
+		++yearDigits;
+	}
+
+	// Count rest of digits
+	for (; yearStart < theDate.length() && 
+			(theDate[yearStart] >= XalanUnicode::charDigit_0 && theDate[yearStart] <= XalanUnicode::charDigit_9);
+			++yearStart)
+	{
+		++yearDigits;
+	}
+
+	// Check at least 4 digits, if more that we have no leading zeroes
+	if (!(yearDigits == 4 || (yearDigits > 4 && yearLeadingZeroes == 0)))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidYear);
+
+	// Looks ok, parse as an integer
+	m_year = parseInt(theDate, index);
+	if (index >= theDate.length())
+	{
+		m_type = xs_gYear;
+		validate();
+		return;
+	}
+	
+	// month
+	if (theDate[index++] != XalanUnicode::charHyphenMinus)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+	m_month = parse2DigitInt(theDate, index);
+	index += 2;
+	if (index >= theDate.length())
+	{
+		m_type = xs_gYearMonth;
+		validate();
+		return;
+	}
+	
+	// day
+	if (theDate[index++] != XalanUnicode::charHyphenMinus)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+	m_day = parse2DigitInt(theDate, index);
+	index += 2;
+
+	if (index >= theDate.length())
+	{
+		// Date, no timezone
+		m_type = xs_date;
+		validate();
+		return;
+	}
+
+	// must be T to add a time
+	if (theDate[index] != XalanUnicode::charLetter_T)
+	{
+		parseTimeZone(theDate, index);
+		m_type = xs_date;
+		validate();
+		return;
+	}
+
+	// parse the time
+	parseTime(theMemoryManager, theDate, index + 1);
+	m_type = xs_dateTime;
+	validate();
+}
+
+
+
+void XalanXSDateTime::validateTime() const
+{
+	if (!(m_hour >= 0 && m_hour <= 23))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidHour);
+	if (!(m_minute >= 0 && m_minute <= 59))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMinute);
+	if (!(m_second >= 0.0 && m_second < 60.0))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidSecond);
+}
+
+
+
+void XalanXSDateTime::validateMonth() const
+{
+	if (!(m_month >= 1 && m_month <= 12))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMonth);
+}
+
+
+
+void XalanXSDateTime::validateDay() const
+{
+	if (!(m_day >= 1 && m_day <= 31))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDay);
+}
+
+		
+		
+void XalanXSDateTime::validateYear() const
+{
+	if (!(m_year != 0))
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDay);
+}
+
+
+
+void XalanXSDateTime::validate() const
+{
+	switch (m_type)
+	{
+	case xs_time:
+		validateTime();
+		return;
+
+	case xs_gDay:
+		validateDay();
+		break;
+
+	case xs_gMonth:
+		validateMonth();
+		break;
+
+	case xs_gMonthDay:
+		validateMonth();
+		validateDay();
+		break;
+
+	case xs_gYear:
+		validateYear();
+		break; 
+
+	case xs_gYearMonth:
+		validateMonth();
+		validateYear();
+		break;
+
+	case xs_date:
+	case xs_dateTime:
+		validateYear();
+		validateMonth();
+		
+		if (!(m_day >= 1 && m_day <= maximumDayInMonthFor(m_year, m_month)))
+			throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDay);
+
+		if (m_type == xs_dateTime)
+		{
+			validateTime();
+		}
+		break;
+
+	default:
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidType);
+	}
+}
+
+
+
+XalanDOMString &XalanXSDateTime::formatXS(XalanDOMString &theResult) const
+{
+	if (m_type == xs_gYearMonth || m_type == xs_gYear)
+	{
+		format4DigitInt(theResult, m_year);
+		if (m_type == xs_gYearMonth)
+		{
+			theResult += XalanUnicode::charHyphenMinus;
+			format2DigitInt(theResult, m_month);
+		}
+	}
+	else if (m_type == xs_gDay)
+	{
+		theResult += XalanUnicode::charHyphenMinus;
+		theResult += XalanUnicode::charHyphenMinus;
+		theResult += XalanUnicode::charHyphenMinus;
+		format2DigitInt(theResult, m_day);
+	}
+	else if (m_type == xs_gMonth)
+	{
+		theResult += XalanUnicode::charHyphenMinus;
+		theResult += XalanUnicode::charHyphenMinus;
+		format2DigitInt(theResult, m_month);
+		theResult += XalanUnicode::charHyphenMinus;
+		theResult += XalanUnicode::charHyphenMinus;
+	}
+	else if (m_type == xs_gMonthDay)
+	{
+		theResult += XalanUnicode::charHyphenMinus;
+		theResult += XalanUnicode::charHyphenMinus;
+		format2DigitInt(theResult, m_month);
+		theResult += XalanUnicode::charHyphenMinus;
+		format2DigitInt(theResult, m_day);
+	}
+	else if (m_type == xs_date || m_type == xs_dateTime || m_type == xs_time)
+	{
+		if (m_type == xs_date || m_type == xs_dateTime)
+		{
+			format4DigitInt(theResult, m_year);
+			theResult += XalanUnicode::charHyphenMinus;
+			format2DigitInt(theResult, m_month);
+			theResult += XalanUnicode::charHyphenMinus;
+			format2DigitInt(theResult, m_day);
+		}
+		if (m_type == xs_dateTime)
+		{
+			theResult += XalanUnicode::charLetter_T;
+		}
+		if (m_type == xs_time || m_type == xs_dateTime)
+		{
+			format2DigitInt(theResult, m_hour);
+			theResult += XalanUnicode::charColon;
+			format2DigitInt(theResult, m_minute);
+			theResult += XalanUnicode::charColon;
+
+			if (m_second < 10)
+			{
+				theResult += XalanUnicode::charDigit_0;
+			}
+			DoubleToDOMString(m_second, theResult);
+			if (m_offset == 0)
+			{
+				theResult += XalanUnicode::charLetter_Z;
+			}
+			else
+			{
+				int offset = m_offset;
+				if (offset > 0)
+				{
+					theResult += XalanUnicode::charPlusSign;
+				}
+				else
+				{
+					offset = -offset;
+					theResult += XalanUnicode::charHyphenMinus;
+				}
+				format2DigitInt(theResult, offset / 60);
+				theResult += XalanUnicode::charColon;
+				format2DigitInt(theResult, offset % 60);
+			}
+		}
+	}
+	else
+	{
+		assert(false);
+	}
+
+	return theResult;
+}
+
+
+
+static const XalanDOMChar s_eraBC[] =
+{
+	XalanUnicode::charLetter_B,
+	XalanUnicode::charLetter_C,
+	0
+};
+
+
+
+static const XalanDOMChar s_eraAD[] =
+{
+	XalanUnicode::charLetter_A,
+	XalanUnicode::charLetter_D,
+	0
+};
+
+
+
+static const XalanDOMChar s_am[] =
+{
+	XalanUnicode::charLetter_A,
+	XalanUnicode::charLetter_M,
+	0
+};
+
+
+
+static const XalanDOMChar s_pm[] =
+{
+	XalanUnicode::charLetter_P,
+	XalanUnicode::charLetter_M,
+	0
+};
+
+
+
+static const XalanDOMChar s_gmt[] =
+{
+	XalanUnicode::charLetter_G,
+	XalanUnicode::charLetter_M,
+	XalanUnicode::charLetter_T,
+	0
+};
+
+
+
+XalanDOMString &XalanXSDateTime::formatJDK(
+	const XalanDOMString&	theFormat, 
+	XalanDOMString&			theResult
+) const
+{
+	for (XalanDOMString::size_type i = 0; i < theFormat.length(); )
+	{
+		// Count duplicates of the current format character if A-Za-z
+		// This must be a pattern character
+		XalanDOMString::size_type	start = i;
+		XalanDOMChar				formatLetter = theFormat[i];
+		XalanDOMString::size_type	formatCount	= 1;
+
+		if ( (theFormat[i] >= XalanUnicode::charLetter_A && theFormat[i] <= XalanUnicode::charLetter_Z) ||
+			 (theFormat[i] >= XalanUnicode::charLetter_a && theFormat[i] <= XalanUnicode::charLetter_z) )
+		{
+			for (++i; i < theFormat.length() && formatLetter == theFormat[i]; ++i)
+				;
+			formatCount = i - start;
+		}
+
+		// Handle the formatting
+		switch (theFormat[start])
+		{
+		case XalanUnicode::charLetter_G: // Era (text)
+			if (m_year < 0)
+				theResult.append(s_eraBC);
+			else
+				theResult.append(s_eraAD);
+			break;
+
+		case XalanUnicode::charLetter_y: // Year (number)
+		{
+			// The JDK has year 0 = 1BC
+			int year = m_year;
+			if (year < 0) 
+				++year;
+
+			// 2 digit truncates to last 2 digit year format
+			if (formatCount == 2)
+			{
+				// Pretty silly, but whatever...
+				if (year < 0)
+					year = -year;
+				format2DigitInt(theResult, year % 100);
+			}
+			// Otherwise use the format as normal.  No further truncations
+			// seemed to be specified in the 1.1 JDK help page.
+			else
+			{
+				formatInt(theResult, year, formatCount);
+			}
+			break;
+		}
+
+		case XalanUnicode::charLetter_M: // Month (text & number)
+			// Use month names if formatCount >=3
+			if (formatCount >= 3)
+				getMonthName(theResult);
+			else
+				formatInt(theResult, m_month, formatCount);
+			break;
+
+		case XalanUnicode::charLetter_d: // Days (number)
+			formatInt(theResult, m_day, formatCount);
+			break;
+
+		case XalanUnicode::charLetter_h: // Hour (1-12) (number)
+			formatInt(theResult, (12 + m_hour - 1) % 12 + 1, formatCount);
+			break;
+
+		case XalanUnicode::charLetter_H: // Hour (number)
+			formatInt(theResult, m_hour, formatCount);
+			break;
+
+		case XalanUnicode::charLetter_m: // Minute (number)
+			formatInt(theResult, m_minute, formatCount);
+			break;
+
+		case XalanUnicode::charLetter_s: // Second (number)
+			formatInt(theResult, (int)m_second, formatCount);
+			break;
+
+		case XalanUnicode::charLetter_S: // Millisecond (number)
+			formatInt(theResult, (int)(fmod(m_second, 1.0) * 1000.0), formatCount);
+			break;
+
+		case XalanUnicode::charLetter_E: // Day name (text)
+			// < 4 digits => short form
+			if (formatCount < 4)
+				getShortDayName(theResult);
+			else
+				getDayName(theResult);
+			break;
+
+		case XalanUnicode::charLetter_D: // Day in year (number)
+			formatInt(theResult, getDayInYear(), formatCount);
+			break;
+
+		case XalanUnicode::charLetter_F: // Day of week in month (number)
+			formatInt(theResult, getDayOfWeekInMonth(), formatCount);
+			break;
+
+		case XalanUnicode::charLetter_w: // Week in year (number)
+			formatInt(theResult, getWeekInYear(), formatCount);
+			break;
+
+		case XalanUnicode::charLetter_W: // Week in month
+			formatInt(theResult, getWeekInMonth(), formatCount);
+			break;
+
+		case XalanUnicode::charLetter_a: // AM/PM
+			if (m_hour > 12)
+				theResult.append(s_pm);
+			else
+				theResult.append(s_am);
+			break;
+
+		case XalanUnicode::charLetter_k: // Hour (1-24) (number)
+			formatInt(theResult, m_hour + 1, formatCount);
+			break;
+
+		case XalanUnicode::charLetter_K: // Hour (0-11) (number)
+			formatInt(theResult, m_hour % 12, formatCount);
+			break;
+
+		case XalanUnicode::charLetter_z: // Time zone (text)
+		{
+			// Always use GMT+hh:mm/GMT-hh:mm since we don't know what
+			// names the JDK actually intends us to use, i.e. consider
+			// them all unnamed.
+			theResult.append(s_gmt);
+
+			int offset = m_offset;
+			if (offset < 0)
+			{
+				theResult += XalanUnicode::charHyphenMinus;
+				offset = -offset;
+			}
+			else
+			{
+				theResult += XalanUnicode::charPlusSign;
+			}
+			formatInt(theResult, offset / 60, 2);
+			theResult += XalanUnicode::charColon;
+			formatInt(theResult, offset % 60, 2);
+			break;
+		}
+
+		case XalanUnicode::charApostrophe: // Escaped text
+			// There's no clear grammar given for this, so '''' is ambiguous
+			// i.e. this can be interpreted as ' '' ' => '
+			// or '' '' => ''
+			// I've chosen the former so '''foo' does the expected thing
+			for (++i; i < theFormat.length(); ++i)
+			{
+				XalanDOMChar c = theFormat[i];
+				
+				if (c == XalanUnicode::charApostrophe)
+				{
+					// Need to peek at next character.  If this is also an
+					// apostrophe, this is a quoted apostrophe in an quoted string
+					if (i + 1 < theFormat.length() && theFormat[i + 1] == XalanUnicode::charApostrophe)
+					{
+						++i;
+						theResult += XalanUnicode::charApostrophe;
+					}
+					// Otherwise it's the end of the string
+					else
+					{
+						// Skip over the final apostrophe
+						++i;
+						break;
+					}
+				}
+				else
+				{
+					theResult += c;
+				}
+			}
+			// Check for mismatched quote
+			if (i > 0 && theFormat[i - 1] != XalanUnicode::charApostrophe)
+			{
+				throw XalanXSDateTimeException(XalanXSDateTimeException::JDKInvalidPattern);
+			}
+
+			// '' ?
+			if (i - start == 2)
+			{
+				theResult += XalanUnicode::charApostrophe;
+			}
+			break;
+
+		default: // Some other character
+			// Check A-Za-z and throw
+			if ( (theFormat[start] >= XalanUnicode::charLetter_A && theFormat[start] <= XalanUnicode::charLetter_Z) ||
+				 (theFormat[start] >= XalanUnicode::charLetter_a && theFormat[start] <= XalanUnicode::charLetter_z) )
+			{
+				throw XalanXSDateTimeException(XalanXSDateTimeException::JDKInvalidPattern);
+			}
+
+			// Any other character passes through
+			theResult += theFormat[i++];
+			break;
+		}
+	}
+	return theResult;
+}
+
+
+
+int XalanXSDateTime::getDayInWeek() const
+{
+	return dayInWeek(m_year, m_month, m_day);
+}
+
+
+
+int XalanXSDateTime::getDayOfWeekInMonth() const
+{
+	// Number of times that the day has occurred is the total elapsed
+	// whole weeks plus the final partial week
+	return (m_day - 1) / 7 + 1;
+}
+
+
+
+int XalanXSDateTime::getDayInYear() const
+{
+	// Days from the start of the year, 1 being the first day
+	return dayOffset(m_year, m_month) + m_day;
+}
+
+
+
+int XalanXSDateTime::getWeekInMonth() const
+{
+	// Compute the first day of the month
+	int firstDay = dayInWeek(m_year, m_month, 1);
+
+	// Adjust so monday is the first day in the week
+	firstDay = (firstDay + 6) % 7;
+
+	// Return elapsed weeks
+	return (m_day + firstDay - 1) / 7 + 1;
+}
+
+
+
+int XalanXSDateTime::getWeekInYear() const
+{
+	// Determine first day of year
+	int firstDay = dayInWeek(m_year, 1, 1);
+
+	// Adjust so monday, not sunday is the first day of the week
+	firstDay = (firstDay + 6) % 7;
+
+	// Figure elapsed weeks in the year
+	int elapsedWeeks = (dayOffset(m_year, m_month) + m_day) / 7;
+
+	// Adjust for the ISO 8601 thing where the first week of the year
+	// starts on Thursday.  I'm sure there's some logic behind it.
+	if (firstDay <= 3)
+		++elapsedWeeks;
+
+	return elapsedWeeks;
+}
+
+
+
+static const XalanDOMChar s_monthJan[] =
+{
+	XalanUnicode::charLetter_J,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_n,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_r,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthFeb[] =
+{
+	XalanUnicode::charLetter_F,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_b,
+	XalanUnicode::charLetter_r,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_r,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthMar[] =
+{
+	XalanUnicode::charLetter_M,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_r,
+	XalanUnicode::charLetter_c,
+	XalanUnicode::charLetter_h,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthApr[] =
+{
+	XalanUnicode::charLetter_A,
+	XalanUnicode::charLetter_p,
+	XalanUnicode::charLetter_r,
+	XalanUnicode::charLetter_i,
+	XalanUnicode::charLetter_l,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthMay[] =
+{
+	XalanUnicode::charLetter_M,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthJun[] =
+{
+	XalanUnicode::charLetter_J,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_n,
+	XalanUnicode::charLetter_e,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthJul[] =
+{
+	XalanUnicode::charLetter_J,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_l,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthAug[] =
+{
+	XalanUnicode::charLetter_A,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_g,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_s,
+	XalanUnicode::charLetter_t,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthSep[] =
+{
+	XalanUnicode::charLetter_S,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_p,
+	XalanUnicode::charLetter_t,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_m,
+	XalanUnicode::charLetter_b,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_r,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthOct[] =
+{
+	XalanUnicode::charLetter_O,
+	XalanUnicode::charLetter_c,
+	XalanUnicode::charLetter_t,
+	XalanUnicode::charLetter_o,
+	XalanUnicode::charLetter_b,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_r,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthNov[] =
+{
+	XalanUnicode::charLetter_N,
+	XalanUnicode::charLetter_o,
+	XalanUnicode::charLetter_v,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_m,
+	XalanUnicode::charLetter_b,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_r,
+	0
+};
+
+
+
+static const XalanDOMChar s_monthDec[] =
+{
+	XalanUnicode::charLetter_D,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_c,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_m,
+	XalanUnicode::charLetter_b,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_r,
+	0
+};
+
+
+
+static const XalanDOMChar *const s_monthNames[] =
+{
+	s_monthJan,
+	s_monthFeb,
+	s_monthMar,
+	s_monthApr,
+	s_monthMay,
+	s_monthJun,
+	s_monthJul,
+	s_monthAug,
+	s_monthSep,
+	s_monthOct,
+	s_monthNov,
+	s_monthDec
+};
+
+
+
+XalanDOMString &XalanXSDateTime::getMonthName(XalanDOMString &theResult) const
+{
+	assert(m_month >= 1 && m_month <= 12);
+	if (m_month < 1 || m_month > 12)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMonth);
+	theResult.append(s_monthNames[m_month - 1]);
+	return theResult;
+}
+
+
+
+static const XalanDOMChar s_shortMonthJan[] =
+{
+	XalanUnicode::charLetter_J,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_n,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthFeb[] =
+{
+	XalanUnicode::charLetter_F,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_b,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthMar[] =
+{
+	XalanUnicode::charLetter_M,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_r,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthApr[] =
+{
+	XalanUnicode::charLetter_A,
+	XalanUnicode::charLetter_p,
+	XalanUnicode::charLetter_r,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthMay[] =
+{
+	XalanUnicode::charLetter_M,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthJun[] =
+{
+	XalanUnicode::charLetter_J,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_n,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthJul[] =
+{
+	XalanUnicode::charLetter_J,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_l,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthAug[] =
+{
+	XalanUnicode::charLetter_A,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_g,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthSep[] =
+{
+	XalanUnicode::charLetter_S,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_p,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthOct[] =
+{
+	XalanUnicode::charLetter_O,
+	XalanUnicode::charLetter_c,
+	XalanUnicode::charLetter_t,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthNov[] =
+{
+	XalanUnicode::charLetter_N,
+	XalanUnicode::charLetter_o,
+	XalanUnicode::charLetter_v,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortMonthDec[] =
+{
+	XalanUnicode::charLetter_D,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_c,
+	0
+};
+
+
+
+static const XalanDOMChar *const s_shortMonthNames[] =
+{
+	s_shortMonthJan,
+	s_shortMonthFeb,
+	s_shortMonthMar,
+	s_shortMonthApr,
+	s_shortMonthMay,
+	s_shortMonthJun,
+	s_shortMonthJul,
+	s_shortMonthAug,
+	s_shortMonthSep,
+	s_shortMonthOct,
+	s_shortMonthNov,
+	s_shortMonthDec
+};
+
+
+
+XalanDOMString &XalanXSDateTime::getShortMonthName(XalanDOMString &theResult) const
+{
+	assert(m_month >= 1 && m_month <= 12);
+	if (m_month < 1 || m_month > 12)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMonth);
+	theResult.append(s_shortMonthNames[m_month - 1]);
+	return theResult;
+}
+
+
+
+static const XalanDOMChar s_shortDaySun[] =
+{
+	XalanUnicode::charLetter_S,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_n,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortDayMon[] =
+{
+	XalanUnicode::charLetter_M,
+	XalanUnicode::charLetter_o,
+	XalanUnicode::charLetter_n,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortDayTue[] =
+{
+	XalanUnicode::charLetter_T,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_e,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortDayWed[] =
+{
+	XalanUnicode::charLetter_W,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_d,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortDayThu[] =
+{
+	XalanUnicode::charLetter_T,
+	XalanUnicode::charLetter_h,
+	XalanUnicode::charLetter_u,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortDayFri[] =
+{
+	XalanUnicode::charLetter_F,
+	XalanUnicode::charLetter_r,
+	XalanUnicode::charLetter_i,
+	0
+};
+
+
+
+static const XalanDOMChar s_shortDaySat[] =
+{
+	XalanUnicode::charLetter_S,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_t,
+	0
+};
+
+
+
+static const XalanDOMChar *const s_shortDayNames[] =
+{
+	s_shortDaySun,
+	s_shortDayMon,
+	s_shortDayTue,
+	s_shortDayWed,
+	s_shortDayThu,
+	s_shortDayFri,
+	s_shortDaySat
+};
+
+
+
+XalanDOMString &XalanXSDateTime::getShortDayName(XalanDOMString &theResult) const
+{
+	int dayInWeek = getDayInWeek();
+	assert(dayInWeek >= 0 && dayInWeek <= 6);
+	theResult.append(s_shortDayNames[dayInWeek]);
+	return theResult;
+}
+
+
+
+static const XalanDOMChar s_daySun[] =
+{
+	XalanUnicode::charLetter_S,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_n,
+	XalanUnicode::charLetter_d,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_dayMon[] =
+{
+	XalanUnicode::charLetter_M,
+	XalanUnicode::charLetter_o,
+	XalanUnicode::charLetter_n,
+	XalanUnicode::charLetter_d,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_dayTue[] =
+{
+	XalanUnicode::charLetter_T,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_s,
+	XalanUnicode::charLetter_d,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_dayWed[] =
+{
+	XalanUnicode::charLetter_W,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_d,
+	XalanUnicode::charLetter_n,
+	XalanUnicode::charLetter_e,
+	XalanUnicode::charLetter_s,
+	XalanUnicode::charLetter_d,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_dayThu[] =
+{
+	XalanUnicode::charLetter_T,
+	XalanUnicode::charLetter_h,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_r,
+	XalanUnicode::charLetter_s,
+	XalanUnicode::charLetter_d,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_dayFri[] =
+{
+	XalanUnicode::charLetter_F,
+	XalanUnicode::charLetter_r,
+	XalanUnicode::charLetter_i,
+	XalanUnicode::charLetter_d,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar s_daySat[] =
+{
+	XalanUnicode::charLetter_S,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_t,
+	XalanUnicode::charLetter_u,
+	XalanUnicode::charLetter_r,
+	XalanUnicode::charLetter_d,
+	XalanUnicode::charLetter_a,
+	XalanUnicode::charLetter_y,
+	0
+};
+
+
+
+static const XalanDOMChar *const s_dayNames[] =
+{
+	s_daySun,
+	s_dayMon,
+	s_dayTue,
+	s_dayWed,
+	s_dayThu,
+	s_dayFri,
+	s_daySat
+};
+
+
+
+XalanDOMString &XalanXSDateTime::getDayName(XalanDOMString &theResult) const
+{
+	int dayInWeek = getDayInWeek();
+	assert(dayInWeek >= 0 && dayInWeek <= 6);
+	theResult.append(s_dayNames[dayInWeek]);
+	return theResult;
+}
+
+
+
+// See if s1 starts with s2, case insensitive
+static bool icaseStartsWith(const XalanDOMChar *s1, const XalanDOMChar *s2)
+{
+	while (*s1 != 0 && *s2 != 0)
+	{
+		XalanDOMChar c1 = toUpperASCII(*(s1++));
+		XalanDOMChar c2 = toUpperASCII(*(s2++));
+
+		if (c1 != c2)
+			return false;
+	}
+	return (*s2 == 0);
+}
+
+
+
+static XalanDOMString::size_type parseDayName(const XalanDOMChar *theString, int &theDayOfWeek)
+{
+	for (int i = 0; i < sizeof(s_dayNames) / sizeof(s_dayNames[0]); ++i)
+	{
+		if (icaseStartsWith(theString, s_dayNames[i]))
+		{
+			theDayOfWeek = i;
+			return length(s_dayNames[i]);
+		}
+	}
+	throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDay);
+}
+
+
+
+static XalanDOMString::size_type parseShortDayName(const XalanDOMChar *theString, int &theDayOfWeek)
+{
+	for (int i = 0; i < sizeof(s_shortDayNames) / sizeof(s_shortDayNames[0]); ++i)
+	{
+		if (icaseStartsWith(theString, s_shortDayNames[i]))
+		{
+			theDayOfWeek = i;
+			return length(s_shortDayNames[i]);
+		}
+	}
+	throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDay);
+}
+
+
+
+static XalanDOMString::size_type parseMonthName(const XalanDOMChar *theString, int &theMonth)
+{
+	for (int i = 0; i < sizeof(s_monthNames) / sizeof(s_monthNames[0]); ++i)
+	{
+		if (icaseStartsWith(theString, s_monthNames[i]))
+		{
+			theMonth = i + 1;
+			return length(s_monthNames[i]);
+		}
+	}
+	throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMonth);
+}
+
+
+
+void XalanXSDateTime::parseJDK(const XalanDOMString &theDate, const XalanDOMString &theFormat)
+{
+	// Default initialise everything to the minimum allowable for the type
+	m_year		= 1;
+	m_month		= 1;
+	m_day		= 1;
+	m_hour		= 0;
+	m_minute	= 0;
+	m_second	= 0.0;
+	m_offset	= 0;
+
+	// Era, if we see it
+	bool isBC = false;
+
+	// AM/PM, if we see it
+	bool isAM = true;
+
+	// Milliseconds, if we see them
+	int ms = 0;
+
+	// Random things that we could have to parse
+	int dayInYear = -1;
+	int dayOfWeekInMonth = -1;
+	int weekInYear = -1;
+	int weekInMonth = -1;
+	int dayOfWeek = -1;
+
+	// Offset in the string we are parsing
+	XalanDOMString::size_type parseIndex = 0;
+
+	// Record what bits we have seen in the format mask,
+	// so we can work out which xs:date format to use
+	bool seenYear = false, seenMonth = false, seenDay = false;
+	bool seenTime = false;
+
+	// Chop the input up according to the format string
+	for (XalanDOMString::size_type i = 0; i < theFormat.length(); )
+	{
+		// Count duplicates of the current format character if A-Za-z
+		// This must be a pattern character
+		XalanDOMString::size_type	start = i;
+		XalanDOMChar				formatLetter = theFormat[i];
+		XalanDOMString::size_type	formatCount	= 1;
+
+		if ( (theFormat[i] >= XalanUnicode::charLetter_A && theFormat[i] <= XalanUnicode::charLetter_Z) ||
+			 (theFormat[i] >= XalanUnicode::charLetter_a && theFormat[i] <= XalanUnicode::charLetter_z) )
+		{
+			for (++i; i < theFormat.length() && formatLetter == theFormat[i]; ++i)
+				;
+			formatCount = i - start;
+		}
+
+		// Handle the format directive
+		switch (formatLetter)
+		{
+		case XalanUnicode::charLetter_G: // Era (text)
+		{
+			seenYear = true;
+
+			if (parseIndex + 2 > theDate.length())
+				throw XalanXSDateTimeException(XalanXSDateTimeException::JDKParseFailed);
+
+			XalanDOMChar first = theDate[parseIndex++];
+			XalanDOMChar second = theDate[parseIndex++];
+
+			// AD
+			if ( (first  == XalanUnicode::charLetter_A || first  == XalanUnicode::charLetter_a) &&
+				 (second == XalanUnicode::charLetter_D || second == XalanUnicode::charLetter_d) )
+			{
+				isBC = false;
+			}
+			else if ( (first  == XalanUnicode::charLetter_B || first  == XalanUnicode::charLetter_b) &&
+					  (second == XalanUnicode::charLetter_C || second == XalanUnicode::charLetter_c) )
+			{
+				isBC = true;
+			}
+			else
+			{
+				throw XalanXSDateTimeException(XalanXSDateTimeException::JDKParseFailed);
+			}
+			break;
+		}
+
+		case XalanUnicode::charLetter_y: // Year (number)
+			seenYear = true;
+
+			// 2 digit => 2 digit year format
+			if (formatCount == 2)
+			{
+				m_year = parseInt(theDate, parseIndex, false);
+				if (m_year < 0 || m_year > 99)
+					throw XalanXSDateTimeException(XalanXSDateTimeException::JDKParseFailed);
+
+				// Get the current year
+				time_t long_time;
+				time( &long_time );
+
+				// Store the local time
+				struct tm gmTime;
+				if (!gmtime_r(&long_time, &gmTime))
+					throw XalanXSDateTimeException(XalanXSDateTimeException::Current);
+
+				// Window the date
+				int currentYear = gmTime.tm_year + 1900;
+				m_year += (currentYear / 100) * 100;
+				if (m_year >= currentYear + 20)
+				{
+					m_year -= 100;
+				}
+			}
+			else
+			{
+				m_year = parseInt(theDate, parseIndex);
+				// The JDK has year 0 = 1BC
+				if (m_year <= 0)
+					--m_year;
+			}
+			break;
+
+		case XalanUnicode::charLetter_M: // Month (text & number)
+			seenMonth = true;
+
+			// Use month names if formatCount >=3
+			if (formatCount >= 3)
+				parseIndex += parseMonthName(theDate.c_str() + parseIndex, m_month);
+			else
+				m_month = parseInt(theDate, parseIndex, false);
+			if (m_month < 1 || m_month > 12)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMonth);
+			break;
+
+		case XalanUnicode::charLetter_d: // Days (number)
+			seenDay = true;
+
+			m_day = parseInt(theDate, parseIndex, false);
+			if (m_day < 1 || m_day > 31)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDay);
+			break;
+
+		case XalanUnicode::charLetter_h: // Hour (1-12) (number)
+			seenTime = true;
+
+			m_hour = parseInt(theDate, parseIndex, false);
+			if (m_hour < 1 || m_hour > 12)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidHour);
+			m_hour = m_hour % 12;
+			break;
+
+		case XalanUnicode::charLetter_H: // Hour (number)
+			seenTime = true;
+
+			m_hour = parseInt(theDate, parseIndex, false);
+			isAM = true;
+			if (m_hour < 0 || m_hour > 23)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidHour);
+			break;
+
+		case XalanUnicode::charLetter_m: // Minute (number)
+			seenTime = true;
+
+			m_minute = parseInt(theDate, parseIndex, false);
+			if (m_minute < 0 || m_minute > 59)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMinute);
+			break;
+
+		case XalanUnicode::charLetter_s: // Second (number)
+			seenTime = true;
+
+			m_second = (double)parseInt(theDate, parseIndex, false);
+			if (m_second < 0 || m_second > 59)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidSecond);
+			break;
+
+		case XalanUnicode::charLetter_S: // Millisecond (number)
+			seenTime = true;
+
+			ms = parseInt(theDate, parseIndex, false);
+			break;
+
+		case XalanUnicode::charLetter_E: // Day name (text)
+			if (formatCount < 4)
+				parseIndex += parseShortDayName(theDate.c_str() + parseIndex, dayOfWeek);
+			else
+				parseIndex += parseDayName(theDate.c_str() + parseIndex, dayOfWeek);
+			break;
+
+		case XalanUnicode::charLetter_D: // Day in year (number)
+			dayInYear = parseInt(theDate, parseIndex, false);
+			break;
+
+		case XalanUnicode::charLetter_F: // Day of week in month (number)
+			dayOfWeekInMonth = parseInt(theDate, parseIndex, false);
+			break;
+
+		case XalanUnicode::charLetter_w: // Week in year (number)
+			weekInYear = parseInt(theDate, parseIndex, false);
+			break;
+
+		case XalanUnicode::charLetter_W: // Week in month
+			weekInMonth = parseInt(theDate, parseIndex, false);
+			break;
+
+		case XalanUnicode::charLetter_a: // AM/PM
+		{
+			seenTime = true;
+
+			if (parseIndex + 2 > theDate.length())
+				throw XalanXSDateTimeException(XalanXSDateTimeException::JDKParseFailed);
+
+			XalanDOMChar first = theDate[parseIndex++];
+			XalanDOMChar second = theDate[parseIndex++];
+
+			// AM
+			if ( (first  == XalanUnicode::charLetter_A || first  == XalanUnicode::charLetter_a) &&
+				 (second == XalanUnicode::charLetter_M || second == XalanUnicode::charLetter_m) )
+			{
+				isAM = true;
+			}
+			else if ( (first  == XalanUnicode::charLetter_P || first  == XalanUnicode::charLetter_p) &&
+					  (second == XalanUnicode::charLetter_M || second == XalanUnicode::charLetter_m) )
+			{
+				isAM = false;
+			}
+			else
+			{
+				throw XalanXSDateTimeException(XalanXSDateTimeException::JDKParseFailed);
+			}
+			break;
+		}
+
+		case XalanUnicode::charLetter_k: // Hour (1-24) (number)
+			seenTime = true;
+
+			m_hour = parseInt(theDate, parseIndex, false);
+			if (m_hour < 1 || m_hour > 24)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidHour);
+			--m_hour;
+			isAM = true;
+			break;
+
+		case XalanUnicode::charLetter_K: // Hour (0-11) (number)
+			seenTime = true;
+
+			m_hour = parseInt(theDate, parseIndex, false);
+			if (m_hour < 0 || m_hour > 11)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidHour);
+			break;
+
+		case XalanUnicode::charLetter_z: // Time zone (text)
+			seenTime = true;
+
+			// Just grok what we spat out and nothing else
+			// XXX: could be improved
+			if (!icaseStartsWith(theDate.c_str() + parseIndex, s_gmt))
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidTimeZone);
+			parseIndex += length(s_gmt);
+
+			// Parse timezone, but check that it starts with +/- to
+			// avoid the parser grokking 'Z'
+			if (parseIndex >= theDate.length())
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidTimeZone);
+			if (theDate[parseIndex] != XalanUnicode::charHyphenMinus &&
+				theDate[parseIndex] != XalanUnicode::charPlusSign)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidTimeZone);
+
+			parseTimeZone(theDate, parseIndex);
+			break;
+
+		case XalanUnicode::charApostrophe: // Escaped text
+			// There's no clear grammar given for this, so '''' is ambiguous
+			// i.e. this can be interpreted as ' '' ' => '
+			// or '' '' => ''
+			// I've chosen the former so '''foo' does the expected thing
+			for (++i; i < theFormat.length(); ++i)
+			{
+				XalanDOMChar c = theFormat[i];
+				
+				if (c == XalanUnicode::charApostrophe)
+				{
+					// Need to peek at next character.  If this is also an
+					// apostrophe, this is a quoted apostrophe in an quoted string
+					if (i + 1 < theFormat.length() && theFormat[i + 1] == XalanUnicode::charApostrophe)
+					{
+						++i;
+						// Compare with input string
+						if (parseIndex >= theDate.length() || theDate[parseIndex++] != c)
+							throw XalanXSDateTimeException(XalanXSDateTimeException::JDKParseFailed);
+					}
+					// Otherwise it's the end of the string
+					else
+					{
+						// Skip over the final apostrophe
+						++i;
+						break;
+					}
+				}
+				else
+				{
+					// Compare with input string
+					if (parseIndex >= theDate.length() || theDate[parseIndex++] != c)
+						throw XalanXSDateTimeException(XalanXSDateTimeException::JDKParseFailed);
+				}
+			}
+			// Check for mismatched quote
+			if (i > 0 && theFormat[i - 1] != XalanUnicode::charApostrophe)
+			{
+				throw XalanXSDateTimeException(XalanXSDateTimeException::JDKInvalidPattern);
+			}
+
+			// '' ?
+			if (i - start == 2)
+			{
+				if (parseIndex >= theDate.length() || theDate[parseIndex++] != XalanUnicode::charApostrophe)
+					throw XalanXSDateTimeException(XalanXSDateTimeException::JDKParseFailed);
+			}
+			break;
+
+		default: // Some other character
+			// Check A-Za-z and throw
+			if ( (theFormat[start] >= XalanUnicode::charLetter_A && theFormat[start] <= XalanUnicode::charLetter_Z) ||
+				 (theFormat[start] >= XalanUnicode::charLetter_a && theFormat[start] <= XalanUnicode::charLetter_z) )
+			{
+				throw XalanXSDateTimeException(XalanXSDateTimeException::JDKInvalidPattern);
+			}
+
+			// Any other character passes through so match against the input string
+			if (parseIndex >= theDate.length() || theDate[parseIndex++] != theFormat[i++])
+				throw XalanXSDateTimeException(XalanXSDateTimeException::JDKParseFailed);
+			break;
+		}
+	}
+
+	// Do some final fixups that can't be done inline
+	if (isBC && m_year > 0)
+		m_year = -m_year;
+	
+	// AM/PM, if we see it
+	if (!isAM)
+		m_hour += 12;
+
+	// Add ms in
+	m_second += ((double)ms) / 1000.0;
+
+	// Try and set the date from wacky things like day of year, etc
+	// where possible
+	if (seenYear && (!seenMonth || !seenDay) && dayInYear != -1)
+	{
+		// Day of year is good if we know the year -- we can compute
+		// month/day from this information
+		int days = 1; // dayOfYear starts from 1
+
+		for (m_month = 1; m_month <= 12; ++m_month)
+		{
+			int daysInMonth = maximumDayInMonthFor(m_year, m_month);
+			if (days + daysInMonth >= dayInYear)
+				break;
+			days += daysInMonth;
+		}
+
+		// Check if dayInYear is wrong
+		if (m_month > 12)
+			throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMonth);
+
+		// The day is the residual, then 1 based
+		m_day = dayInYear - days + 1;
+
+		// We now have both month & day
+		seenMonth = seenDay = true;
+	}
+	else if (seenYear && (!seenMonth || !seenDay) && weekInYear != -1 && dayOfWeek != -1)
+	{
+		// We can compute the month & day from the numbered week of the 
+		// year if we know the day name
+
+		// Determine first day of year
+		int firstDay = dayInWeek(m_year, 1, 1);
+
+		// Adjust so monday, not sunday is the first day of the week
+		firstDay = (firstDay + 6) % 7;
+
+		// Unadjust for the ISO 8601 thing where the first week of the year
+		// starts on Thursday.  I'm sure there's some logic behind it.
+		if (firstDay <= 3)
+			--weekInYear;
+
+		// Unfigure elapsed weeks in the year
+		int elapsedDays = 7 * weekInYear;
+
+		// Figure month
+		int daysSoFar = 0;
+		for (m_month = 1; m_month <= 12; ++m_month)
+		{
+			int daysInMonth = maximumDayInMonthFor(m_year, m_month);
+			if (daysSoFar + daysInMonth >= elapsedDays)
+				break;
+			daysSoFar += daysInMonth;
+		}
+
+		// Check if weekInYear is wrong
+		if (m_month > 12)
+			throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMonth);
+
+		// XXX: check this
+		// Compute whole weeks in month
+		m_day = (elapsedDays - daysSoFar) / 7;
+
+		// Compute residual days
+		int residualDays = (elapsedDays - daysSoFar) % 7;
+
+		// Get first day of month
+		int firstDayOfMonth = dayInWeek(m_year, m_month, 1);
+
+		// Compute distance of day of week from start of week and adjust by that
+		m_day += (7 + residualDays - firstDayOfMonth) % 7;
+	}
+	else if (seenYear && seenMonth && dayOfWeekInMonth != -1 && dayOfWeek != -1)
+	{
+		// We can compute the day from the number of occurrences of the
+		// day in a given month/year
+		m_day = (dayOfWeekInMonth - 1) * 7 + 1;
+
+		if (m_day < 0 || m_day > maximumDayInMonthFor(m_year, m_month))
+			throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDay);
+	}
+	else if (seenYear && seenMonth && weekInMonth != -1 && dayOfWeek != -1)
+	{
+		// We can compute the day from the named day and the week of the month
+		// in which it occurs given a month/year
+		// XXX: implement this, doubt it's all that useful
+
+		// Compute the first day of the month
+		int firstDay = dayInWeek(m_year, m_month, 1);
+
+		// Adjust so monday is the first day in the week
+		firstDay = (firstDay + 6) % 7;
+
+		// Hmm, does this work?
+		// weekInMonth = (m_day + firstDay - 1) / 7 + 1;
+		m_day = (weekInMonth - 1) * 7 + 1 - firstDay;
+ 	}
+
+	// Work out the appropriate xs format (the least specific one is used)
+	if (seenTime)
+	{
+		// must be xs:time or xs:datetime
+		if (seenYear || seenMonth || seenDay)
+		{
+			m_type = xs_dateTime;
+		}
+		else
+		{
+			m_type = xs_time;
+		}
+	}
+	else
+	{
+		// Some date format
+		if (seenYear)
+		{
+			// date, gYearMonth, gYear
+			if (seenDay)
+			{
+				m_type = xs_date;
+			}
+			else if (seenMonth)
+			{
+				m_type = xs_gYearMonth;
+			}
+			else
+			{
+				m_type = xs_gYear;
+			}
+		}
+		else
+		{
+			// gMonthDay, gMonth, gDay
+			if (seenMonth)
+			{
+				if (seenDay)
+				{
+					m_type = xs_gMonthDay;
+				}
+				else
+				{
+					m_type = xs_gMonth;
+				}
+			}
+			else
+			{
+				m_type = xs_gDay;
+			}
+		}
+	}
+}
+
+	
+
+XALAN_CPP_NAMESPACE_END
Index: xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTime.hpp
===================================================================
--- /dev/null
+++ xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTime.hpp
@@ -0,0 +1,525 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if !defined(EXSLT_XSDATETIME_HEADER_GUARD_1357924680)
+#define EXSLT_XSDATETIME_HEADER_GUARD_1357924680
+
+
+
+#include "XalanXSDuration.hpp"
+
+
+
+XALAN_CPP_NAMESPACE_BEGIN
+
+
+
+/**
+ * An XS date
+ */
+class XALAN_EXSLT_EXPORT XalanXSDateTime
+{
+public:
+	/**
+	 * Default constructor that sets the date/time/offset
+	 * of the current time
+	 */
+	XalanXSDateTime();
+
+
+
+	/**
+	 * Construct a date/time with the given values
+	 *
+	 * @param year		The year
+	 * @param month		The month
+	 * @param day		The day
+	 * @param hour		The hour
+	 * @param minute	The minute
+	 * @param second	The second + fraction
+	 * @param offset	The UTC offset in minutes
+	 */
+	XalanXSDateTime(
+		int		year, 
+		int		month, 
+		int		day,
+		int		hour,
+		int		minute,
+		double	second,
+		int		offset) :
+		m_year(year),
+		m_month(month),
+		m_day(day),
+		m_hour(hour),
+		m_minute(minute),
+		m_second(second),
+		m_offset(offset),
+		m_type(xs_dateTime)
+	{
+	}
+
+	
+
+	/**
+	 * Construct a date/time from the given XS date string
+	 *
+	 * @param theMemoryManager	Memory manager (used for a temporary string during parsing)
+	 * @param theDate			Date/time string formatted according to the XS standard
+	 */
+	XalanXSDateTime(MemoryManagerType &theMemoryManager, const XalanDOMString &theDate)
+	{
+		parse(theMemoryManager, theDate);
+	}
+
+
+	/**
+	 * Construct a date/time from the given JDK format string
+	 *
+	 * @param theDate	Date string
+	 * @param theFormat	JDK 1.1 SimpleDateFormat string describing the format 
+	 * of the given date string
+	 */
+	XalanXSDateTime(const XalanDOMString &theDate, const XalanDOMString &theFormat)
+	{
+		parseJDK(theDate, theFormat);
+	}
+
+
+
+	/**
+	 * Possible type for the date/time object
+	 */
+	enum xsType
+	{
+		/**
+		 * Time portion only (hours, minutes, seconds + fraction)
+		 */
+		xs_time,
+
+		/**
+		 * Day only
+		 */
+		xs_gDay,
+
+		/**
+		 * Month only
+		 */
+		xs_gMonth,
+
+		/**
+		 * Month & year only
+		 */
+		xs_gMonthDay,
+
+		/**
+		 * Year only
+		 */
+		xs_gYear,
+
+		/**
+		 * Year & month only
+		 */
+		xs_gYearMonth,
+
+		/**
+		 * Year, month, day only
+		 */
+		xs_date,
+
+		/**
+		 * Year, month, day, hours, minutes, seconds + fraction
+		 */
+		xs_dateTime,
+	};
+
+
+
+	/**
+	 * Parse the given XS formatted date string
+	 *
+	 * @param theMemoryManager	Memory manager (used for a temporary string during parsing)
+	 * @param theDate			The date string
+	 */
+	void parse(MemoryManagerType &theMemoryManager, const XalanDOMString &theDate);
+
+
+
+	/**
+	 * Parse the given JDK date string
+	 *
+	 * @param theDate		The date string
+	 * @param theFormat		A JDK 1.1 SimpleDateFormatString describing the format of theDAte
+	 */
+	void parseJDK(const XalanDOMString &theDate, const XalanDOMString &theFormat);
+
+
+
+	/**
+	 * Add a given ISO duration to the date/time
+	 *
+	 * @param duration		The duration to add
+	 * @return				The result of adding the duration to the date
+	 */
+	XalanXSDateTime add(const XalanXSDuration &duration) const;
+
+
+
+	/**
+	 * Subtract another date, returning a duration
+	 *
+	 * @param other			The other date
+	 * @return				A duration which when added to this date will given the other date
+	 */
+	XalanXSDuration difference(const XalanXSDateTime &other) const;
+
+
+	/**
+	 * Format the date according to the XS standard
+	 *
+	 * @param theResult		The output string
+	 * @return				A reference to theResult
+	 */
+	XalanDOMString &formatXS(XalanDOMString &theResult) const;
+
+
+	/**
+	 * Format the date according to the given format string
+	 *
+	 * @param theFormat		A JDK 1.1 SimpleDateFormat string describing how to format the result
+	 * @param theResult		The output string
+	 * @return				A reference to theResult
+	 */
+	XalanDOMString &formatJDK(const XalanDOMString &theFormat, XalanDOMString &theResult) const;
+
+
+
+	/**
+	 * Get the XS date type
+	 *
+	 * @return				The XS date type
+	 */
+	xsType getType() const
+	{
+		return m_type;
+	}
+
+
+
+	/**
+	 * Set the type of encapsulated date.
+	 * Any fields left unspecified by the conversion are set to the minimum
+	 * allowed value.
+	 *
+	 * @param type			The type to truncate/upgrade to
+	 */
+	void setType(xsType type);
+
+
+
+	/**
+	 * Get the week day of the current date
+	 *
+	 * @return				Day in week where Sunday = 0, etc
+	 */
+	int getDayInWeek() const;
+
+
+
+	/**
+	 * Get the number of occurrences of the current week day in
+	 * the current month
+	 *
+	 * @return				e.g. 2 for 2nd Thursday in the month
+	 */
+	int getDayOfWeekInMonth() const;
+
+
+	
+	/**
+	 * Get the day of the year, where 1 = 1st day, 2 = 2nd day, etc.
+	 *
+	 * @return				e.g. 5 for 5th day of the year
+	 */
+	int getDayInYear() const;
+
+
+	/**
+	 * Get the week in the given month where monday is the first
+	 * day of the week
+	 *
+	 * @return				e.g. 2 for the second week of the month
+	 */
+	int getWeekInMonth() const;
+
+
+	/**
+	 * Get the elapsed weeks from the start of the year.  Follows wacky
+	 * ISO8601 rule where Thursday is the start of the first week of the
+	 * year.
+	 *
+	 * @return				e.g. 4 for the 4th week of the year
+	 */
+	int getWeekInYear() const;
+
+
+
+	/**
+	 * Get the (English) name of the month
+	 *
+	 * @return				Name of the month (January, February, ...)
+	 */
+	XalanDOMString &getMonthName(XalanDOMString &theResult) const;
+
+
+
+	/**
+	 * Get the three letter (English) name of the month
+	 *
+	 * @return				Name of the month (Jan, Feb, ...)
+	 */
+	XalanDOMString &getShortMonthName(XalanDOMString &theResult) const;
+
+
+
+	/**
+	 * Get the (English) name of the current day
+	 *
+	 * @return				Name of the day (Monday, Tuesday, ...)
+	 */
+	XalanDOMString &getDayName(XalanDOMString &theResult) const;
+
+
+
+	/**
+	 * Get the three letter (English) name of the current day
+	 *
+	 * @return				Name of the day (Mon, Tue, ...)
+	 */
+	XalanDOMString &getShortDayName(XalanDOMString &theResult) const;
+
+
+
+	/**
+	 * Accessor function to set the year
+	 *
+	 * @param year	The year
+	 */
+	void setYear(int year)
+	{
+		m_year = year;
+	}
+
+	/**
+	 * Accessor function to get the year
+	 *
+	 * @return The year
+	 */
+	int getYear() const
+	{
+		return m_year;
+	}
+
+	/**
+	 * Accessor function to set the month
+	 *
+	 * @param month The month
+	 */
+	void setMonth(int month)
+	{
+		m_month = month;
+	}
+
+	/**
+	 * Accessor function to get the month
+	 *
+	 * @return The month
+	 */
+	int getMonth() const
+	{
+		return m_month;
+	}
+
+	/**
+	 * Accessor function to set the day (1-31)
+	 *
+	 * @param day The day
+	 */
+	void setDay(int day)
+	{
+		m_day = day;
+	}
+
+	/**
+	 * Accessor function to get the day (1-31)
+	 *
+	 * @return The day
+	 */
+	int getDay() const
+	{
+		return m_day;
+	}
+
+	/**
+	 * Accessor function to set the hour (0-23)
+	 *
+	 * @param hour The hour
+	 */
+	void setHour(int hour)
+	{
+		m_hour = hour;
+	}
+
+	/**
+	 * Accessor function to get the hour (0-23)
+	 *
+	 * @return The hour
+	 */
+	int getHour() const 
+	{
+		return m_hour;
+	}
+
+	/**
+	 * Accessor function to set the minute (0-59)
+	 *
+	 * @param minute The minute
+	 */
+	void setMinute(int minute)
+	{
+		m_minute = minute;
+	}
+
+	/**
+	 * Accessor function to get the minute (0-59)
+	 *
+	 * @return The minute
+	 */
+	int getMinute() const
+	{
+		return m_minute;
+	}
+
+	/**
+	 * Accessor function to set the second (0-59) with fraction
+	 *
+	 * @param second The second
+	 */
+	void setSecond(double second)
+	{
+		m_second = second;
+	}
+
+	/**
+	 * Accessor function to get the second (0-59) with fraction
+	 *
+	 * @return The second
+	 */
+	double getSecond() const
+	{
+		return m_second;
+	}
+
+	/**
+	 * Accessor function to set the UTC offset (+/- minutes from UTC)
+	 *
+	 * @param offset The offset
+	 */
+	void setOffset(int offset)
+	{
+		m_offset = offset;
+	}
+
+	/**
+	 * Accessor function to get the UTC offset (+/- minutes from UTC)
+	 *
+	 * @return The offset
+	 */
+	int getOffset() const
+	{
+		return m_offset;
+	}
+
+private:
+	/**
+	 * Helper to parse a timezone string
+	 *
+	 * @param theTimeZone	The string containing time zone
+	 * @param offset		The offset within the string to begin parsing at
+	 */
+	void parseTimeZone(const XalanDOMString &theTimeZone, XalanDOMString::size_type offset);
+
+	/**
+	 * Helper to parse a time string
+	 *
+	 * @param theMemoryManager	Memory manager (used for a temporary string)
+	 * @param theTimeZone		The string containing time zone
+	 * @param offset			The offset within the string to begin parsing at
+	 */
+	void parseTime(
+		MemoryManagerType			&theMemoryManager, 
+		const XalanDOMString		&theTime, 
+		XalanDOMString::size_type	offset);
+
+	/**
+	 * Validate h/m/s
+	 */
+	void validateTime() const;
+
+	/**
+	 * Validate months
+	 */
+	void validateMonth() const;
+
+	/**
+	 * Validate days (1-31, loose)
+	 */
+	void validateDay() const;
+
+	/**
+	 * Validate years
+	 */
+	void validateYear() const;
+
+	/**
+	 * Validate the entire date/time
+	 */
+	void validate() const;
+
+
+	/** The date type */
+	xsType	m_type;
+	/** The year */
+	int		m_year;
+	/** The month (1-12) */
+	int		m_month;
+	/** The day (1-31) */
+	int		m_day;
+	/** The hour (0-23) */
+	int		m_hour;
+	/** The minute (0-59) */
+	int		m_minute;
+	/** The second (0-59) with fraction */
+	double	m_second;
+	/** The offset from GMT (minutes, may be negative) */
+	int		m_offset;
+};
+
+
+
+XALAN_CPP_NAMESPACE_END
+
+
+
+#endif // EXSLT_XSDATETIME_HEADER_GUARD_1357924680
Index: xml-xalan/c/src/xalanc/NLS/en_US/XalanMsg_en_US.xlf
===================================================================
--- xml-xalan.orig/c/src/xalanc/NLS/en_US/XalanMsg_en_US.xlf
+++ xml-xalan/c/src/xalanc/NLS/en_US/XalanMsg_en_US.xlf
@@ -762,6 +762,11 @@ On<trans-unit id="FunctionDoesNotAcceptA
 		<target>The EXSLT function '{0}' does not accept any arguments.</target>
 </trans-unit>
 
+<trans-unit id="EXSLTFunctionAccepts0Or1Arguments_1Param">
+		<source>The EXSLT function '{0}' accepts zero or one arguments.</source>
+		<target>The EXSLT function '{0}' accepts zero or one arguments.</target>
+</trans-unit>
+
 <trans-unit id="EXSLTFunctionAccepts0Or1Or2Arguments_1Param">
 	<source>The EXSLT function '{0}' accepts zero, one or two arguments.</source>
 	<target>The EXSLT function '{0}' accepts zero, one or two arguments.</target>
Index: xml-xalan/c/src/xalanc/XalanEXSLT/XalanEXSLTDateTimeImpl.hpp
===================================================================
--- xml-xalan.orig/c/src/xalanc/XalanEXSLT/XalanEXSLTDateTimeImpl.hpp
+++ xml-xalan/c/src/xalanc/XalanEXSLT/XalanEXSLTDateTimeImpl.hpp
@@ -30,18 +30,203 @@ XALAN_CPP_NAMESPACE_BEGIN
 
 
 
-class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDateTime : public Function
+class XalanXSDateTime;
+
+
+
+/**
+ * A date function taking zero or one arguments
+ */
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDate01 : public Function
 {
 public:
 
-	typedef Function	ParentType;
+	XalanEXSLTFunctionDate01()
+	{
+	}
 
-	XalanEXSLTFunctionDateTime()
+	virtual
+	~XalanEXSLTFunctionDate01()
+	{
+	}
+
+protected:
+	/**
+	 * Get the name of the function
+	 */
+	virtual const XalanDOMChar *
+	getFunctionName() const = 0;
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDate01&
+	operator=(const XalanEXSLTFunctionDate01&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDate01&) const;
+};
+
+
+
+
+/**
+ * A date function returning a number, taking zero or one arguments.
+ *
+ * The current date/time is used if zero arguments are provided.
+ */
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDate01Number : public XalanEXSLTFunctionDate01
+{
+public:
+
+	XalanEXSLTFunctionDate01Number()
 	{
 	}
 
 	virtual
-	~XalanEXSLTFunctionDateTime()
+	~XalanEXSLTFunctionDate01Number()
+	{
+	}
+
+	// These methods are inherited from Function ...
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+protected:
+	/**
+	 * Execute the function with the single, possibly defaulted argument
+	 *
+	 * Returns NaN if any date/time exception is caught
+	 */
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const = 0;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDate01Number&
+	operator=(const XalanEXSLTFunctionDate01Number&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDate01Number&) const;
+};
+
+
+
+
+/**
+ * A date function returning a number, taking zero or one arguments.
+ *
+ * The current date/time is used if zero arguments are provided.
+ */
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDate01String : public XalanEXSLTFunctionDate01
+{
+public:
+
+	XalanEXSLTFunctionDate01String()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionDate01String()
+	{
+	}
+
+	// These methods are inherited from Function ...
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+protected:
+	/**
+	 * Execute the function with the single, possibly defaulted argument
+	 *
+	 * Returns '' if any date/time exception is caught
+	 */
+	virtual void
+	doExecute(XalanXSDateTime &arg, XalanDOMString &theResult) const = 0;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDate01String&
+	operator=(const XalanEXSLTFunctionDate01String&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDate01String&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionAdd : public Function
+{
+public:
+	XalanEXSLTFunctionAdd()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionAdd()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionAdd*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionAdd&
+	operator=(const XalanEXSLTFunctionAdd&);
+
+	bool
+	operator==(const XalanEXSLTFunctionAdd&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionAddDuration : public Function
+{
+public:
+	XalanEXSLTFunctionAddDuration()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionAddDuration()
 	{
 	}
 
@@ -54,9 +239,87 @@ public:
 			const XObjectArgVectorType&		args,
 			const LocatorType*				locator) const;
 
-#if !defined(XALAN_NO_USING_DECLARATION)
-	using ParentType::execute;
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionAddDuration*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionAddDuration&
+	operator=(const XalanEXSLTFunctionAddDuration&);
+
+	bool
+	operator==(const XalanEXSLTFunctionAddDuration&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDate : public XalanEXSLTFunctionDate01String
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionDate*
 #endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, XalanDOMString& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDate&
+	operator=(const XalanEXSLTFunctionDate&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDate&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDateTime : public Function
+{
+public:
+	XalanEXSLTFunctionDateTime()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionDateTime()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
 
 #if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
 	virtual Function*
@@ -86,6 +349,884 @@ private:
 
 
 
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDayAbbreviation : public XalanEXSLTFunctionDate01String
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionDayAbbreviation*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, XalanDOMString& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDayAbbreviation&
+	operator=(const XalanEXSLTFunctionDayAbbreviation&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDayAbbreviation&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDayInMonth : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionDayInMonth*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDayInMonth&
+	operator=(const XalanEXSLTFunctionDayInMonth&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDayInMonth&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDayInWeek : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionDayInWeek*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDayInWeek&
+	operator=(const XalanEXSLTFunctionDayInWeek&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDayInWeek&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDayInYear : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionDayInYear*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDayInYear&
+	operator=(const XalanEXSLTFunctionDayInYear&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDayInYear&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDayName : public XalanEXSLTFunctionDate01String
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionDayName*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, XalanDOMString& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDayName&
+	operator=(const XalanEXSLTFunctionDayName&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDayName&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDayOfWeekInMonth : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionDayOfWeekInMonth*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDayOfWeekInMonth&
+	operator=(const XalanEXSLTFunctionDayOfWeekInMonth&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDayOfWeekInMonth&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDateDifference : public Function
+{
+public:
+	XalanEXSLTFunctionDateDifference()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionDateDifference()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionDateDifference*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDateDifference&
+	operator=(const XalanEXSLTFunctionDateDifference&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDateDifference&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionDuration : public Function
+{
+public:
+	XalanEXSLTFunctionDuration()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionDuration()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionDuration*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionDuration&
+	operator=(const XalanEXSLTFunctionDuration&);
+
+	bool
+	operator==(const XalanEXSLTFunctionDuration&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionFormatDate : public Function
+{
+public:
+	XalanEXSLTFunctionFormatDate()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionFormatDate()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionFormatDate*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionFormatDate&
+	operator=(const XalanEXSLTFunctionFormatDate&);
+
+	bool
+	operator==(const XalanEXSLTFunctionFormatDate&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionHourInDay : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionHourInDay*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionHourInDay&
+	operator=(const XalanEXSLTFunctionHourInDay&);
+
+	bool
+	operator==(const XalanEXSLTFunctionHourInDay&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionLeapYear : public Function
+{
+public:
+	XalanEXSLTFunctionLeapYear()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionLeapYear()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionLeapYear*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionLeapYear&
+	operator=(const XalanEXSLTFunctionLeapYear&);
+
+	bool
+	operator==(const XalanEXSLTFunctionLeapYear&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionMinuteInHour : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionMinuteInHour*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionMinuteInHour&
+	operator=(const XalanEXSLTFunctionMinuteInHour&);
+
+	bool
+	operator==(const XalanEXSLTFunctionMinuteInHour&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionMonthAbbreviation : public XalanEXSLTFunctionDate01String
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionMonthAbbreviation*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, XalanDOMString& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionMonthAbbreviation&
+	operator=(const XalanEXSLTFunctionMonthAbbreviation&);
+
+	bool
+	operator==(const XalanEXSLTFunctionMonthAbbreviation&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionMonthInYear : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionMonthInYear*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionMonthInYear&
+	operator=(const XalanEXSLTFunctionMonthInYear&);
+
+	bool
+	operator==(const XalanEXSLTFunctionMonthInYear&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionMonthName : public XalanEXSLTFunctionDate01String
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionMonthName*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, XalanDOMString& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionMonthName&
+	operator=(const XalanEXSLTFunctionMonthName&);
+
+	bool
+	operator==(const XalanEXSLTFunctionMonthName&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionParseDate : public Function
+{
+public:
+	XalanEXSLTFunctionParseDate()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionParseDate()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionParseDate*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionParseDate&
+	operator=(const XalanEXSLTFunctionParseDate&);
+
+	bool
+	operator==(const XalanEXSLTFunctionParseDate&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionSecondInMinute : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionSecondInMinute*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionSecondInMinute&
+	operator=(const XalanEXSLTFunctionSecondInMinute&);
+
+	bool
+	operator==(const XalanEXSLTFunctionSecondInMinute&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionSeconds : public Function
+{
+public:
+	XalanEXSLTFunctionSeconds()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionSeconds()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionSeconds*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionSeconds&
+	operator=(const XalanEXSLTFunctionSeconds&);
+
+	bool
+	operator==(const XalanEXSLTFunctionSeconds&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionSum : public Function
+{
+public:
+	XalanEXSLTFunctionSum()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionSum()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionSum*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionSum&
+	operator=(const XalanEXSLTFunctionSum&);
+
+	bool
+	operator==(const XalanEXSLTFunctionSum&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionTime : public Function
+{
+public:
+	XalanEXSLTFunctionTime()
+	{
+	}
+
+	virtual
+	~XalanEXSLTFunctionTime()
+	{
+	}
+
+	// These methods are inherited from Function ...
+
+	virtual XObjectPtr
+	execute(
+			XPathExecutionContext&			executionContext,
+			XalanNode*						context,
+			const XObjectArgVectorType&		args,
+			const LocatorType*				locator) const;
+
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionTime*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+
+	virtual const XalanDOMString&
+	getError(XalanDOMString& theResult) const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionTime&
+	operator=(const XalanEXSLTFunctionTime&);
+
+	bool
+	operator==(const XalanEXSLTFunctionTime&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionWeekInMonth : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionWeekInMonth*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionWeekInMonth&
+	operator=(const XalanEXSLTFunctionWeekInMonth&);
+
+	bool
+	operator==(const XalanEXSLTFunctionWeekInMonth&) const;
+};
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionWeekInYear : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionWeekInYear*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionWeekInYear&
+	operator=(const XalanEXSLTFunctionWeekInYear&);
+
+	bool
+	operator==(const XalanEXSLTFunctionWeekInYear&) const;
+};
+
+
+
+
+class XALAN_EXSLT_EXPORT XalanEXSLTFunctionYear : public XalanEXSLTFunctionDate01Number
+{
+public:
+#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
+	virtual Function*
+#else
+	virtual XalanEXSLTFunctionYear*
+#endif
+	clone(MemoryManagerType& theManager) const
+	{
+	    return XalanCopyConstruct(theManager, *this);
+	}
+
+protected:
+	virtual void
+	doExecute(XalanXSDateTime& arg, double& theResult) const;
+
+	virtual const XalanDOMChar *
+	getFunctionName() const;
+
+private:
+
+	// Not implemented...
+	XalanEXSLTFunctionYear&
+	operator=(const XalanEXSLTFunctionYear&);
+
+	bool
+	operator==(const XalanEXSLTFunctionYear&) const;
+};
+
+
+
+
 XALAN_CPP_NAMESPACE_END
 
 
Index: xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTimeException.hpp
===================================================================
--- /dev/null
+++ xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTimeException.hpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if !defined(EXSLT_XSDATETIMEEXCEPTION_HEADER_GUARD_1357924680)
+#define EXSLT_XSDATETIMEEXCEPTION_HEADER_GUARD_1357924680
+
+
+
+#include <xalanc/XalanEXSLT/XalanEXSLTDefinitions.hpp>
+
+
+
+XALAN_CPP_NAMESPACE_BEGIN
+
+
+
+/**
+ * The exceptions thrown by date/time functions
+ */
+class XALAN_EXSLT_EXPORT XalanXSDateTimeException
+{
+public:
+	/**
+	 * Possible exception reasons
+	 */
+	enum Code
+	{
+		/**
+		 * Getting the current time/date failed
+		 */
+		Current,
+
+		/**
+		 * Numeric overflow
+		 */
+		Overflow,
+
+		/**
+		 * Unexpected character in input
+		 */
+		UnexpectedChar,
+
+		/**
+		 * Unexpected end of input
+		 */
+		UnexpectedEOF,
+
+		/**
+		 * Invalid xs date type
+		 */
+		InvalidType,
+
+		/**
+		 * Invalid year
+		 */
+		InvalidYear,
+
+		/**
+		 * Invalid month
+		 */
+		InvalidMonth,
+
+		/**
+		 * Invalid day
+		 */
+		InvalidDay,
+
+		/**
+		 * Invalid hour
+		 */
+		InvalidHour,
+
+		/**
+		 * Invalid minute
+		 */
+		InvalidMinute,
+
+		/**
+		 * Invalid second
+		 */
+		InvalidSecond,
+
+		/**
+		 * Invalid timezone
+		 */
+		InvalidTimeZone,
+
+		/**
+		 * Invalid duration (different signs)
+		 */
+		InvalidDuration,
+
+		/**
+		 * Invalid JDK date format
+		 */
+		JDKInvalidPattern,
+
+		/**
+		 * Parsing a string according to a JDK date format failed
+		 * for some reason or other
+		 */
+		JDKParseFailed
+	};
+
+	/**
+	 * Construct a new exception
+	 *
+	 * @param code The reason for the exception
+	 */
+	XalanXSDateTimeException(Code code) :
+		m_code(code)
+	{
+	}
+
+	/**
+	 * Get the exception reason
+	 *
+	 * @return The exception reason
+	 */
+	Code getCode() const
+	{
+		return m_code;
+	}
+
+private:
+	/** The exception reason */
+	Code	m_code;
+};
+
+
+
+XALAN_CPP_NAMESPACE_END
+
+
+
+#endif // EXSLT_XSDATETIMEEXCEPTION_HEADER_GUARD_1357924680
Index: xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTimeHelper.cpp
===================================================================
--- /dev/null
+++ xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTimeHelper.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "XalanXSDateTimeHelper.hpp"
+
+
+
+#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
+#include <xalanc/PlatformSupport/XalanUnicode.hpp>
+
+
+
+#if !defined(XALAN_NO_STD_NUMERIC_LIMITS)
+#include <limits>
+#endif
+
+
+
+XALAN_CPP_NAMESPACE_BEGIN
+
+
+
+#if !defined(XALAN_NO_STD_NUMERIC_LIMITS)
+static const int s_minInt	= XALAN_STD_QUALIFIER numeric_limits<int>::min();
+static const int s_maxInt	= XALAN_STD_QUALIFIER numeric_limits<int>::max();
+#else
+// Hmm, assume 32-bit int?
+static const int s_maxInt	= 2147483647;
+static const int s_minInt	= -2147483648;
+#endif
+
+
+
+//jan feb mar apr may jun jul aug sep oct nov dec
+//31  28  31  30  31  30  31  31  30  31  30  31
+extern const int s_dayOffset[12] =
+	{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+
+
+//jan feb mar apr may jun jul aug sep oct nov dec
+//31  29  31  30  31  30  31  31  30  31  30  31
+extern const int s_leapDayOffset[12] =
+	{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
+
+
+
+int parseInt(const XalanDOMString &theString, XalanDOMString::size_type &offset, bool allowNegative)
+{
+	int							number		= 0;
+	bool						negative	= false;
+	bool						digitFound	= false;
+	bool						firstChar	= true;
+
+	// Max value before multiply by 10 overflows
+    int							cutoff = s_maxInt / 10;
+	// Max value of final digit if multiple doesn't overflow
+    int							cutoff_digit = s_maxInt - cutoff * 10;
+
+	for ( ; offset < theString.length(); ++offset)
+	{
+		XalanDOMChar c = theString[offset];
+
+		if ( allowNegative && firstChar && 
+				(c == XalanUnicode::charHyphenMinus || 
+				 c == XalanUnicode::charPlusSign) )
+		{
+			if ( c == XalanUnicode::charHyphenMinus )
+			{
+				// Adjust cutoff for negative values
+				cutoff			= s_minInt / 10;
+				cutoff_digit	= s_minInt - cutoff * 10;
+				negative		= true;
+			}
+		}
+		else if ( c >= XalanUnicode::charDigit_0 && c <= XalanUnicode::charDigit_9 )
+		{
+			int digit = (int)(c - XalanUnicode::charDigit_0);
+
+			// Check for overflow
+			if (negative)
+			{
+				if (number < cutoff || (number == cutoff && digit < cutoff_digit))
+				{
+					throw XalanXSDateTimeException(XalanXSDateTimeException::Overflow);
+				}
+				number = number * 10 - digit;
+			}
+			else
+			{
+				if (number > cutoff || (number == cutoff && digit > cutoff_digit))
+				{
+					throw XalanXSDateTimeException(XalanXSDateTimeException::Overflow);
+				}
+				number = number * 10 + digit;
+			}
+
+			digitFound = true;
+		}
+		else
+			break;
+
+		firstChar = false;
+	}
+	
+	// Need at least one digit
+	if (!digitFound)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+
+	return number;
+}
+
+
+
+int parse2DigitInt(const XalanDOMString &theString, XalanDOMString::size_type offset)
+{
+	if (offset >= theString.size())
+	{
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	}
+
+	XalanDOMChar c1 = theString[offset++];
+
+	if (offset >= theString.size())
+	{
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	}
+
+	XalanDOMChar c2 = theString[offset];
+
+	if ( !((c1 >= XalanUnicode::charDigit_0 && c1 <= XalanUnicode::charDigit_9) &&
+		   (c2 >= XalanUnicode::charDigit_0 && c2 <= XalanUnicode::charDigit_9)) )
+	{
+		 throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+	}
+
+	return (c1 - XalanUnicode::charDigit_0) * 10 + (c2 - XalanUnicode::charDigit_0);
+}
+
+
+
+void formatInt(XalanDOMString &theResult, int num, XalanDOMString::size_type padCount)
+{
+	// Compute number of digits num will come out with
+	int digits	= 0;
+	int tempNum = num;
+	do
+	{
+		++digits;
+		tempNum = tempNum / 10;
+	}
+	while (tempNum != 0);
+
+	// Get number portion as unsigned, and deal with the - sign if any
+	unsigned long unum;
+	if (num < 0)
+	{
+		theResult += XalanUnicode::charHyphenMinus;
+		unum = ((unsigned long)-(num+1)) + 1;
+	}
+	else
+	{
+		unum = (unsigned long)num;
+	}
+
+	// Pad as required
+	for (XalanDOMString::size_type i = digits; i < padCount; ++i)
+		theResult += XalanUnicode::charDigit_0;
+
+	// Format the rest of the number up
+	UnsignedLongToDOMString(unum, theResult);
+}
+
+
+
+void findNumberEnd(
+	const XalanDOMString		&theString, 
+	XalanDOMString::size_type	&offset,
+	bool						&seenDot)
+{
+	bool seenDigit = false;
+	seenDot = false;
+	for (; offset < theString.size(); ++offset)
+	{
+		XalanDOMChar c = theString[offset];
+
+		if ( c >= XalanUnicode::charDigit_0 && c <= XalanUnicode::charDigit_9 )
+		{
+			seenDigit = true;
+
+			// check 'ss'
+			if (!seenDot && offset - offset + 1 > 2)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+			// after ., ssss is ok
+		}
+		else if ( c == XalanUnicode::charFullStop && !seenDot )
+		{
+			if ( !seenDigit )
+				throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+			seenDot = true;
+		}
+		else
+			break;
+	}
+	// num. is not ok
+	if (seenDot && offset > 0 && theString[offset - 1] == XalanUnicode::charFullStop)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+	// no number is not a number
+	if (!seenDigit)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+}
+
+
+
+XALAN_CPP_NAMESPACE_END
Index: xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTimeHelper.hpp
===================================================================
--- /dev/null
+++ xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDateTimeHelper.hpp
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if !defined(EXSLT_XSDATETIMEHELPER_HEADER_GUARD_1357924680)
+#define EXSLT_XSDATETIMEHELPER_HEADER_GUARD_1357924680
+
+
+
+#include "XalanXSDateTimeException.hpp"
+
+
+#include <xalanc/XalanDOM/XalanDOMString.hpp>
+
+
+
+#include <xalanc/PlatformSupport/DoubleSupport.hpp>
+
+
+
+XALAN_CPP_NAMESPACE_BEGIN
+
+
+
+/** 
+ * Quotient of a/b
+ *
+ * @param a		Dividend
+ * @param b		Divisor
+ * @return		Quotient
+ */
+static inline int fQuotient(double a, double b)
+{
+	return (int)DoubleSupport::floor(a / b);
+}
+
+
+
+/**
+ * Quotient of a/b within a range
+ *
+ * @param a		Dividend
+ * @param low	Start of range
+ * @param high	End of range
+ * @return		Quotient of (a - low) / (high - low)
+ */
+static inline int fQuotient(double a, double low, double high)
+{
+	return fQuotient(a - low, high - low);
+}
+
+
+
+/** 
+ * Remainder of a/b
+ *
+ * @param a		Dividend
+ * @param b		Divisor
+ * @return		Remainder
+ */
+static inline int modulo(double a, double b)
+{
+	return (int)(a - fQuotient(a, b) * b);
+}
+
+
+
+/** 
+ * Remainder of a/b within a range
+ *
+ * @param a		Dividend
+ * @param low	Start of range
+ * @param high	End of range
+ * @return		low + (Remainder of (a - low) / (high - low))
+ */
+static inline int modulo(double a, double low, double high)
+{
+	return (int)(modulo(a - low, high - low) + low);
+}
+
+
+
+/**
+ * See if the given year is a leap year
+ *
+ * @param year	The year to test
+ * @return		true if so, false if not
+ */
+static inline bool isLeap(int year)
+{
+	return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
+}
+
+
+
+/**
+ * Offset of each month from the start of a non-leap year
+ */
+extern const int s_dayOffset[12];
+
+
+
+/**
+ * Offset of each month from the start of a leap year
+ */
+extern const int s_leapDayOffset[12];
+
+
+
+/**
+ * Compute the offset of the given day from the start of the year,
+ * taking account of leap years
+ *
+ * @param year		The year
+ * @param month		The month
+ * @return			The offset of the given day from the start of the year
+ */
+static inline int dayOffset(int year, int month)
+{
+	assert(month >= 1 && month <= 12);
+	if (month < 1 || month > 12)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidMonth);
+	return isLeap(year) ? s_leapDayOffset[month - 1] : s_dayOffset[month - 1];
+}
+
+
+
+/**
+ * Compute the number of days from 1 AD
+ *
+ * @param year		The year
+ * @param month		The month
+ * @return			Number of days of 1/month/year from 1AD
+ */
+static inline int daysFrom1AD(int year, int month)
+{
+	int days;
+
+	// There is no zero year in the xs:date family
+	assert(year != 0);
+	if (year < 0)
+	{
+		// 1 BC or less.  1 AD - 1 BC = -365, basically, in order to
+		// give a correct duration.
+
+		// Add complete years + adjust for leap years
+		days = year * 365 + (year + 1) / 4 - (year + 1) / 100 + (year + 1) / 400;
+
+		// Add complete months from start of year
+		days += dayOffset(year, month);
+	}
+	else
+	{
+		// 1AD or more
+
+		// Add complete years + adjust for leap years
+		days = (year - 1) * 365 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
+
+		// Add complete months from start of year, accounting for the fact that this
+		// year may be a leap year
+		days += dayOffset(year, month);
+	}
+
+	return days;
+}
+
+
+
+/**
+ * Return the maximum day in the month (1 based) for the given year & month
+ *
+ * @param year		The year
+ * @param month		The month
+ * @return			Maximum day in month
+ */
+static inline int maximumDayInMonthFor(int year, int month)
+{
+	year += fQuotient(month, 1, 13);
+	month = modulo(month, 1, 13);
+
+	switch (month)
+	{
+	case 1: case 3: case 5: case 7: case 8: case 10: case 12:
+		return 31;
+	case 2:
+		return 28 + (isLeap(year) ? 1 : 0);
+	case 4: case 6: case 9: case 11:
+		return 30;
+	default:
+		assert(false);
+		return 30; // Satisfy compiler
+	}
+}
+
+
+
+/**
+ * Return the day of the week of the given date
+ *
+ * @param year		Year of the date
+ * @param month		Month of the date
+ * @param day		Day of the date
+ * @return			0 = Sunday, 1 = Monday, ...
+ */
+static inline int dayInWeek(int year, int month, int day)
+{
+	// Compute days from 1AD
+	int days = daysFrom1AD(year, month) + day;
+
+	// 1-1-1 was a Monday, so this => 0 = Sunday
+	days %= 7;
+	if (days < 0)
+		days += 7;
+	return days;
+}
+
+
+
+/**
+ * Parse an integer
+ *
+ * @param theString		String to parse
+ * @param offset		On input, the offset with in the string to start parsing
+ *						On output, the offset at which parsing stopped
+ * @param allowNegative	true to allow negative integers
+ */
+int parseInt(const XalanDOMString &theString, XalanDOMString::size_type &offset, bool allowNegative = true);
+
+
+
+/**
+ * Parse a two digit integer
+ *
+ * @param theString		String to parse
+ * @param offset		On input, the offset with in the string to start parsing
+ *						On output, the offset at which parsing stopped
+ */
+int parse2DigitInt(const XalanDOMString &theString, XalanDOMString::size_type offset);
+
+
+
+/**
+ * Format an integer
+ *
+ * @param theResult		Output string (appended to)
+ * @param num			The integer to format
+ * @param padCount		The minimum number of digits to pad to
+ */
+void formatInt(XalanDOMString &theResult, int num, XalanDOMString::size_type padCount);
+
+
+
+/**
+ * Format a 4 digit integer
+ *
+ * @param theResult		Output string (appended to)
+ * @param num			The integer to format
+ */
+static inline void format4DigitInt(XalanDOMString &theResult, int num)
+{
+	formatInt(theResult, num, 4);
+}
+
+
+
+/**
+ * Format a 2 digit integer (allows negatives)
+ *
+ * @param theResult		Output string (appended to)
+ * @param num			The integer to format
+ */
+static inline void format2DigitInt(XalanDOMString &theResult, int num)
+{
+	formatInt(theResult, num, 2);
+}
+
+
+
+/**
+ * Find the end of a number, allowing a fractional portion
+ *
+ * @param theString		The number to find the end of
+ * @param offset		On input, the offset with in the string to start parsing
+ *						On output, the offset at which parsing stopped
+ * @param seenDot		On output, true if a dot was present in the number
+ */
+void findNumberEnd(
+	const XalanDOMString		&theString, 
+	XalanDOMString::size_type	&offset,
+	bool						&seenDot);
+
+
+
+XALAN_CPP_NAMESPACE_END
+
+
+
+#endif // EXSLT_XSDATETIMEHELPER_HEADER_GUARD_1357924680
+
Index: xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDuration.cpp
===================================================================
--- /dev/null
+++ xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDuration.cpp
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "XalanXSDuration.hpp"
+#include "XalanXSDateTimeHelper.hpp"
+#include "XalanXSDateTimeException.hpp"
+
+
+
+#include <xalanc/PlatformSupport/DOMStringHelper.hpp>
+#include <xalanc/PlatformSupport/XalanUnicode.hpp>
+
+
+
+XALAN_CPP_NAMESPACE_BEGIN
+
+
+
+static XalanDOMChar s_durationPartsDate[] =
+{
+	XalanUnicode::charLetter_Y,
+	XalanUnicode::charLetter_M,
+	XalanUnicode::charLetter_D,
+};
+
+
+
+static XalanDOMChar s_durationPartsTime[] =
+{
+	XalanUnicode::charLetter_H,
+	XalanUnicode::charLetter_M,
+	XalanUnicode::charLetter_S,
+};
+
+
+
+XalanXSDuration::XalanXSDuration(
+		int		years, 
+		int		months, 
+		int		days, 
+		int		hours, 
+		int		minutes, 
+		double	seconds) :
+	m_years(years),
+	m_months(months),
+	m_days(days),
+	m_hours(hours),
+	m_minutes(minutes),
+	m_seconds(seconds)
+{
+	// Check for negative/mismatched signs
+	m_negative = validateSigns();
+}
+
+		
+		
+XalanXSDuration::XalanXSDuration(MemoryManagerType &theMemoryManager, const XalanDOMString &theDuration)
+{
+	// Zero all components by default
+	m_years = m_months = m_days = 0;
+	m_hours = m_minutes = 0;
+	m_seconds = 0.0;
+
+	// Check for a leading '-'
+	bool negative = false;
+	XalanDOMString::size_type offset = 0;
+	if (offset >= theDuration.length())
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	if (theDuration[offset] == XalanUnicode::charHyphenMinus)
+	{
+		negative = true;
+		if (++offset >= theDuration.length())
+			throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	}
+
+	// Check for the leading 'P'
+	if (theDuration[offset++] != XalanUnicode::charLetter_P)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+
+	// Current expected duration portion (as they must be in order)
+	unsigned int currentDuration = 0;
+
+	// Need to see at least one component in the string for it to be valid
+	bool seenOne = false;
+
+	// Flag set if parsing the time, after 'T'
+	bool inTime = false;
+
+	// Check 'T'
+	for (; offset < theDuration.length(); )
+	{
+		// If the char is T, then skip onto the time portion
+		if (theDuration[offset] == XalanUnicode::charLetter_T)
+		{
+			// double 'T'
+			if (inTime)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+			inTime = true;
+			currentDuration = 0;
+			++offset;
+
+			// need at least something after T
+			if (offset >= theDuration.length())
+				throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+			continue;
+		}
+
+		// Find the end of the number
+		bool						seenDot = false;
+		XalanDOMString::size_type	numberStart = offset;
+		findNumberEnd(theDuration, offset, seenDot);
+
+		// Must have a letter indicating what it is after the number
+		if (offset >= theDuration.length())
+			throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+
+		// Find the duration in the appropriate table
+		XalanDOMChar durationChar = theDuration[offset++];
+		if (!inTime)
+		{
+			for (; currentDuration < 3 && durationChar != s_durationPartsDate[currentDuration]; ++currentDuration)
+				;
+		}
+		else
+		{
+			for (; currentDuration < 3 && durationChar != s_durationPartsTime[currentDuration]; ++currentDuration)
+				;
+		}
+		if (currentDuration >= 3)
+			throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+
+		// Have seen a component
+		seenOne = true;
+
+		// Handle seconds as a double
+		if (inTime && currentDuration == 2)
+		{
+			XalanDOMString theSecondString(theMemoryManager);
+			theDuration.substr(theSecondString, numberStart, offset - numberStart - 1);
+			m_seconds = DOMStringToDouble(theSecondString, theSecondString.getMemoryManager());
+		}
+		// Handle everything else as an integer
+		else
+		{
+			// Only seconds may a fractional portion
+			if (seenDot)
+				throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedChar);
+
+			int num = parseInt(theDuration, numberStart, false);
+			if (!inTime)
+			{
+				switch (currentDuration)
+				{
+				case 0:
+					m_years = num;
+					break;
+				case 1:
+					m_months = num;
+					break;
+				case 2:
+					m_days = num;
+					break;
+				}
+			}
+			else
+			{
+				switch (currentDuration)
+				{
+				case 0:
+					m_hours = num;
+					break;
+				case 1:
+					m_minutes = num;
+					break;
+				}
+			}
+		}
+		++currentDuration;
+	}
+
+	// Check we've seen at least one component of the duration
+	if (!seenOne)
+	{
+		throw XalanXSDateTimeException(XalanXSDateTimeException::UnexpectedEOF);
+	}
+
+	if (negative)
+	{
+		m_years		= -m_years;
+		m_months	= -m_months;
+		m_days		= -m_days;
+		m_hours		= -m_hours;
+		m_minutes	= -m_minutes;
+		m_seconds	= -m_seconds;
+	}
+}
+
+
+
+XalanDOMString &XalanXSDuration::formatXS(XalanDOMString &theResult) const
+{
+	int		years	= m_years;
+	int		months	= m_months;
+	int		days	= m_days;
+	int		hours	= m_hours;
+	int		minutes	= m_minutes;
+	double	seconds = m_seconds;
+
+	// Check for zero -- we must output at least one component
+	if (years == 0 && months == 0 && days == 0 && hours == 0 && minutes == 0 && seconds == 0.0)
+	{
+		theResult += XalanUnicode::charLetter_P;
+		theResult += XalanUnicode::charDigit_0;
+		theResult += XalanUnicode::charLetter_D;
+		return theResult;
+	}
+
+	// Check for negative
+	bool negative = years < 0 || months < 0 || days < 0 || hours < 0 || minutes < 0 || seconds < 0;
+	if (negative)
+	{
+		years	= -years;
+		months	= -months;
+		days	= -days;
+		hours	= -hours;
+		minutes	= -minutes;
+		seconds	= -seconds;
+
+		theResult += XalanUnicode::charHyphenMinus;
+	}
+	theResult += XalanUnicode::charLetter_P;
+
+	// Append each non-zero component
+	if (years != 0)
+	{
+		LongToDOMString(years, theResult);
+		theResult += XalanUnicode::charLetter_Y;
+	}
+	if (months != 0)
+	{
+		LongToDOMString(months, theResult);
+		theResult += XalanUnicode::charLetter_M;
+	}
+	if (days != 0)
+	{
+		LongToDOMString(days, theResult);
+		theResult += XalanUnicode::charLetter_D;
+	}
+	if (hours != 0 || minutes != 0 || seconds != 0.0)
+	{
+		theResult += XalanUnicode::charLetter_T;
+	}
+	if (hours != 0)
+	{
+		LongToDOMString(hours, theResult);
+		theResult += XalanUnicode::charLetter_H;
+	}
+	if (minutes != 0)
+	{
+		LongToDOMString(minutes, theResult);
+		theResult += XalanUnicode::charLetter_M;
+	}
+	if (seconds != 0.0)
+	{
+		DoubleToDOMString(seconds, theResult);
+		theResult += XalanUnicode::charLetter_S;
+	}
+	return theResult;
+}
+
+
+
+bool XalanXSDuration::validateSigns() const
+{
+	bool anyNegative = 
+		(m_years < 0) || (m_months < 0) || (m_days < 0) ||
+		(m_hours < 0) || (m_minutes < 0) || (m_seconds < 0.0);
+	bool anyPositive = 
+		(m_years > 0) || (m_months > 0) || (m_days > 0) ||
+		(m_hours > 0) || (m_minutes > 0) || (m_seconds > 0.0);
+	if (anyNegative && anyPositive)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDuration);
+	return anyNegative;
+}
+
+
+
+XalanXSDuration XalanXSDuration::add(const XalanXSDuration &other) const
+{
+	XalanXSDuration	result(0);
+
+	// Do years/months addition in months
+	int totalMonths		= (m_years + other.m_years) * 12 + m_months + other.m_months;
+	result.m_years		= totalMonths / 12;
+	result.m_months		= totalMonths % 12;
+
+	// Do the d/h/m/s addition in seconds
+	result.m_seconds	= m_days * 86400.0 + m_hours * 3600.0 + m_minutes * 60.0 + m_seconds +
+							other.m_days * 86400.0 + other.m_hours * 3600.0 + other.m_minutes * 60.0 + other.m_seconds;
+	result.m_days		= (int)(result.m_seconds / 86400.0);
+	result.m_seconds	= fmod(result.m_seconds, 86400.0);
+	result.m_hours		= (int)(result.m_seconds / 3600.0);
+	result.m_seconds	= fmod(result.m_seconds, 3600.0);
+	result.m_minutes	= (int)(result.m_seconds / 60.0);
+	result.m_seconds	= fmod(result.m_seconds, 60.0);
+
+	// See if we've got different signs in any components -- can't be a valid duration if so
+	result.m_negative = result.validateSigns();
+	return result;
+}
+
+
+
+XalanXSDuration::XalanXSDuration(
+		double	seconds)
+{
+	// Convert seconds to d/h/m/s form
+	if (seconds < 0)
+	{
+		m_negative = true;
+	}
+	m_years = m_months = 0;
+	m_days = (int)(seconds / 86400.0);
+	seconds = fmod(seconds, 86400.0);
+	m_hours = (int)(seconds / 3600.0);
+	seconds = fmod(seconds, 3600.0);
+	m_minutes = (int)(seconds / 60.0);
+	m_seconds = fmod(seconds, 60.0);
+}
+
+	
+
+double XalanXSDuration::inSeconds() const
+{
+	if (m_years != 0)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDuration);
+	if (m_months != 0)
+		throw XalanXSDateTimeException(XalanXSDateTimeException::InvalidDuration);
+	return m_days * 86400.0 + m_hours * 3600.0 + m_minutes * 60.0 + m_seconds;
+}
+
+
+
+XALAN_CPP_NAMESPACE_END
\ No newline at end of file
Index: xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDuration.hpp
===================================================================
--- /dev/null
+++ xml-xalan/c/src/xalanc/XalanEXSLT/XalanXSDuration.hpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if !defined(EXSLT_XSDURATION_HEADER_GUARD_1357924680)
+#define EXSLT_XSDURATION_HEADER_GUARD_1357924680
+
+
+
+#include <xalanc/XalanEXSLT/XalanEXSLTDefinitions.hpp>
+
+
+
+#include <xalanc/XalanDOM/XalanDOMString.hpp>
+
+
+
+XALAN_CPP_NAMESPACE_BEGIN
+
+
+
+/**
+ * An XS duration
+ */
+class XALAN_EXSLT_EXPORT XalanXSDuration
+{
+public:
+	/**
+	 * Construct a duration
+	 *
+	 * @param years		Years in duration
+	 * @param months	Months in duration
+	 * @param days		Days in duration
+	 * @param hours		Hours in duration
+	 * @param minutes	Minutes in duration
+	 * @param seconds	Seconds & fractional part in duration
+	 */
+	explicit XalanXSDuration(
+		int		years, 
+		int		months = 0, 
+		int		days = 0, 
+		int		hours = 0, 
+		int		minutes = 0, 
+		double	seconds = 0.0);
+
+
+
+	/**
+	 * Construct a duration, breaking down seconds into
+	 * d/h/m/s form
+	 *
+	 * @param seconds	Seconds in duration
+	 */
+	explicit XalanXSDuration(
+		double	seconds);
+
+
+
+	/**
+	 * Construction a duration from an XS formatted string
+	 *
+	 * @param theMemoryManager	Memory manager (used for a temporary string during parsing)
+	 * @param theDuration		The XS formatted duration
+	 */
+	XalanXSDuration(MemoryManagerType &theMemoryManager, const XalanDOMString &theDuration);
+
+
+
+	/**
+	 * Format the duration as a string
+	 *
+	 * @param theResult		The string to format to
+	 * @return				string passed in as theResult 
+	 */
+	XalanDOMString &formatXS(XalanDOMString &theResult) const;
+
+
+
+	/**
+	 * Add another duration to this one
+	 *
+	 * @param theDuration	The duration to add
+	 * @return				A new duration containing the sum of durations
+	 */
+	XalanXSDuration add(const XalanXSDuration &other) const;
+
+	/**
+	 * Set the number of years in the duration
+	 *
+	 * @param years			Number of years
+	 */
+	void setYears(int years)
+	{
+		m_years = years;
+	}
+
+
+
+	/**
+	 * Get the number of years in the duration
+	 *
+	 * @return				Number of years
+	 */
+	int getYears() const
+	{
+		return m_years;
+	}
+
+	/**
+	 * Set the number of months in the duration
+	 *
+	 * @param months		Number of months
+	 */
+	void setMonths(int months)
+	{
+		m_months = months;
+	}
+
+
+
+	/**
+	 * Get the number of months in the duration
+	 *
+	 * @return				Number of months
+	 */
+	int getMonths() const
+	{
+		return m_months;
+	}
+
+
+	/**
+	 * Set the number of days in the duration
+	 *
+	 * @param days			Number of days
+	 */
+	void setDays(int days)
+	{
+		m_days = days;
+	}
+
+
+	/**
+	 * Get the number of days in the duration
+	 *
+	 * @return				Number of days
+	 */
+	int getDays() const
+	{
+		return m_days;
+	}
+
+
+
+	/**
+	 * Set the number of hours in the duration
+	 *
+	 * @param hours			Number of hours
+	 */
+	void setHours(int hours)
+	{
+		m_hours = hours;
+	}
+
+
+
+	/**
+	 * Get the number of hours in the duration
+	 *
+	 * @return				Number of hours
+	 */
+	int getHours() const
+	{
+		return m_hours;
+	}
+
+
+
+	/**
+	 * Set the number of minutes in the duration
+	 *
+	 * @param minutes			Number of minutes
+	 */
+	void setMinutes(int minutes)
+	{
+		m_minutes = minutes;
+	}
+
+
+
+	/**
+	 * Get the number of minutes in the duration
+	 *
+	 * @return					Number of minutes
+	 */
+	int getMinutes() const
+	{
+		return m_minutes;
+	}
+
+
+
+	/**
+	 * Set the number of seconds+fraction in the duration
+	 *
+	 * @param seconds			Number of seconds
+	 */
+	void setSeconds(double seconds)
+	{
+		m_seconds = seconds;
+	}
+
+
+	/**
+	 * Get the number of seconds in the duration
+	 *
+	 * @return					Number of seconds
+	 */
+	double getSeconds() const
+	{
+		return m_seconds;
+	}
+
+
+
+	/**
+	 * Set the sign of the duration
+	 *
+	 * @param negative			true if negative, false if positive
+	 */
+	void setNegative(bool negative)
+	{
+		m_negative = negative;
+	}
+
+
+	/**
+	 * See if the duration is negative
+	 *
+	 * @return					True if so, false if not
+	 */
+	bool getNegative() const
+	{
+		return m_negative;
+	}
+
+
+
+	/**
+	 * Get the length of the duration in seconds, only
+	 * valid if years/months are zero
+	 *
+	 * @return Number of seconds
+	 */
+	double inSeconds() const;
+
+
+
+	/**
+	 * Helper to validate that the duration is valid (all signs
+	 * are the same).
+	 *
+	 * @return	true if negative, false if not.
+	 *
+	 * Throws an exception if the duration is invalid.
+	 */
+	bool validateSigns() const;
+
+
+
+private:
+	/** Flag set if negative */
+	bool			m_negative;
+	/** Number of years */
+	int				m_years;
+	/** Number of months */
+	int				m_months;
+	/** Number of days */
+	int				m_days;
+	/** Number of hours */
+	int				m_hours;
+	/** Number of minutes */
+	int				m_minutes;
+	/** Number of seconds+fraction */
+	double			m_seconds;
+};
+
+
+
+XALAN_CPP_NAMESPACE_END
+
+
+
+#endif // EXSLT_XSDURATION_HEADER_GUARD_1357924680

