15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date.c: Implementation of the EXSLT -- Dates and Times module
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * References:
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   http://www.exslt.org/date/date.html
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See Copyright for the status of this software.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Authors:
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Charlie Bozeman <cbozeman@HiWAAY.net>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Thomas Broyer <tbroyer@ltgt.net>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TODO:
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * elements:
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   date-format
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * functions:
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   format-date
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   parse-date
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   sum
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IN_LIBEXSLT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "libexslt/libexslt.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <win32config.h>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if HAVE_LOCALTIME_R	/* _POSIX_SOURCE required by gnu libc */
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef _AIX51		/* but on AIX we're not using gnu libc */
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _POSIX_SOURCE
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/tree.h>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xpath.h>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xpathInternals.h>
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxslt/xsltconfig.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxslt/xsltutils.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxslt/xsltInternals.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxslt/extensions.h>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "exslt.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_MATH_H
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h>
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* needed to get localtime_r on Solaris */
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __sun
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __EXTENSIONS__
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define __EXTENSIONS__
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_TIME_H
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h>
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * types of date and/or time (from schema datatypes)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   somewhat ordered from least specific to most specific (i.e.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   most truncated to least truncated).
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef enum {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXSLT_UNKNOWN  =    0,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XS_TIME        =    1,       /* time is left-truncated */
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XS_GDAY        = (XS_TIME   << 1),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XS_GMONTH      = (XS_GDAY   << 1),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XS_GMONTHDAY   = (XS_GMONTH | XS_GDAY),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XS_GYEAR       = (XS_GMONTH << 1),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XS_GYEARMONTH  = (XS_GYEAR  | XS_GMONTH),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XS_DATE        = (XS_GYEAR  | XS_GMONTH | XS_GDAY),
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XS_DATETIME    = (XS_DATE   | XS_TIME),
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    XS_DURATION    = (XS_GYEAR  << 1)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} exsltDateType;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Date value */
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct _exsltDateValDate exsltDateValDate;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef exsltDateValDate *exsltDateValDatePtr;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct _exsltDateValDate {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long		year;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int	mon	:4;	/* 1 <=  mon    <= 12   */
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int	day	:5;	/* 1 <=  day    <= 31   */
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int	hour	:5;	/* 0 <=  hour   <= 23   */
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int	min	:6;	/* 0 <=  min    <= 59	*/
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double		sec;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int	tz_flag	:1;	/* is tzo explicitely set? */
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    signed int		tzo	:12;	/* -1440 <= tzo <= 1440 currently only -840 to +840 are needed */
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Duration value */
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct _exsltDateValDuration exsltDateValDuration;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef exsltDateValDuration *exsltDateValDurationPtr;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct _exsltDateValDuration {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long	        mon;		/* mon stores years also */
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long        	day;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double		sec;            /* sec stores min and hour also */
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct _exsltDateVal exsltDateVal;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef exsltDateVal *exsltDateValPtr;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct _exsltDateVal {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateType       type;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    union {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exsltDateValDate        date;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exsltDateValDuration    dur;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } value;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/****************************************************************
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *			Compat./Port. macros			*
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ****************************************************************/
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_TIME_H) 					\
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    && (defined(HAVE_LOCALTIME) || defined(HAVE_LOCALTIME_R))	\
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    && (defined(HAVE_GMTIME) || defined(HAVE_GMTIME_R))		\
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    && defined(HAVE_TIME)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WITH_TIME
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/****************************************************************
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *		Convenience macros and functions		*
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ****************************************************************/
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IS_TZO_CHAR(c)						\
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_ALWAYS(num)	(num >= 0)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_YEAR(yr)          (yr != 0)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_MONTH(mon)        ((mon >= 1) && (mon <= 12))
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* VALID_DAY should only be used when month is unknown */
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_DAY(day)          ((day >= 1) && (day <= 31))
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_HOUR(hr)          ((hr >= 0) && (hr <= 23))
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_MIN(min)          ((min >= 0) && (min <= 59))
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_SEC(sec)          ((sec >= 0) && (sec < 60))
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_TZO(tzo)          ((tzo > -1440) && (tzo < 1440))
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IS_LEAP(y)						\
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const unsigned long daysInMonth[12] =
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const unsigned long daysInMonthLeap[12] =
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_DAYINMONTH(yr,mon)                                  \
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_MDAY(dt)						\
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(IS_LEAP(dt->year) ?				        \
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (dt->day <= daysInMonthLeap[dt->mon - 1]) :	        \
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (dt->day <= daysInMonth[dt->mon - 1]))
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_DATE(dt)						\
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hour and min structure vals are unsigned, so normal macros give
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    warnings on some compilers.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_TIME(dt)						\
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	((dt->hour <=23 ) && (dt->min <= 59) &&			\
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 VALID_SEC(dt->sec) && VALID_TZO(dt->tzo))
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VALID_DATETIME(dt)					\
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(VALID_DATE(dt) && VALID_TIME(dt))
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SECS_PER_MIN            (60)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SECS_PER_HOUR           (60 * SECS_PER_MIN)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SECS_PER_DAY            (24 * SECS_PER_HOUR)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const unsigned long dayInYearByMonth[12] =
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const unsigned long dayInLeapYearByMonth[12] =
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DAY_IN_YEAR(day, month, year)				\
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ((IS_LEAP(year) ?					\
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dayInLeapYearByMonth[month - 1] :		\
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                dayInYearByMonth[month - 1]) + day)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateParseGYear:
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  pointer to a date structure
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @str: pointer to the string to analyze
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a xs:gYear without time zone and fills in the appropriate
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * field of the @dt structure. @str is updated to point just after the
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:gYear. It is supposed that @dt->year is big enough to contain
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the year.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 0 or the error code
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateParseGYear (exsltDateValDatePtr dt, const xmlChar **str)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *cur = *str, *firstChar;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int isneg = 0, digcnt = 0;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (((*cur < '0') || (*cur > '9')) &&
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(*cur != '-') && (*cur != '+'))
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return -1;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*cur == '-') {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	isneg = 1;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    firstChar = cur;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while ((*cur >= '0') && (*cur <= '9')) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt->year = dt->year * 10 + (*cur - '0');
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	digcnt++;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* year must be at least 4 digits (CCYY); over 4
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * digits cannot have a leading zero. */
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 1;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (isneg)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt->year = - dt->year;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!VALID_YEAR(dt->year))
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 2;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *str = cur;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_EXSLT_DATE
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltGenericDebug(xsltGenericDebugContext,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "Parsed year %04i\n", dt->year);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FORMAT_GYEAR:
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @yr:  the year to format
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur: a pointer to an allocated buffer
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @yr in xsl:gYear format. Result is appended to @cur and
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur is updated to point after the xsl:gYear.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FORMAT_GYEAR(yr, cur)					\
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (yr < 0) {					        \
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *cur = '-';						\
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur++;						\
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}							\
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{							\
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    long year = (yr < 0) ? - yr : yr;                   \
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlChar tmp_buf[100], *tmp = tmp_buf;		\
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* result is in reverse-order */			\
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    while (year > 0) {					\
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*tmp = '0' + (xmlChar)(year % 10);		\
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		year /= 10;					\
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tmp++;						\
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }							\
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* virtually adds leading zeros */			\
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    while ((tmp - tmp_buf) < 4)				\
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*tmp++ = '0';					\
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* restore the correct order */			\
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    while (tmp > tmp_buf) {				\
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		tmp--;						\
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		*cur = *tmp;					\
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		cur++;						\
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }							\
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PARSE_2_DIGITS:
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @num:  the integer to fill in
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur:  an #xmlChar *
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @func: validation function for the number
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @invalid: an integer
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a 2-digits integer and updates @num with the value. @cur is
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * updated to point just after the integer.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In case of error, @invalid is set to %TRUE, values of @num and
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur are undefined.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PARSE_2_DIGITS(num, cur, func, invalid)			\
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((cur[0] < '0') || (cur[0] > '9') ||			\
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (cur[1] < '0') || (cur[1] > '9'))			\
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    invalid = 1;					\
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else {							\
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    int val;						\
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    val = (cur[0] - '0') * 10 + (cur[1] - '0');		\
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (!func(val))					\
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        invalid = 2;					\
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    else						\
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        num = val;					\
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}							\
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur += 2;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FORMAT_2_DIGITS:
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @num:  the integer to format
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur: a pointer to an allocated buffer
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats a 2-digits integer. Result is appended to @cur and
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur is updated to point after the integer.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FORMAT_2_DIGITS(num, cur)				\
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*cur = '0' + ((num / 10) % 10);				\
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;							\
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*cur = '0' + (num % 10);				\
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PARSE_FLOAT:
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @num:  the double to fill in
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur:  an #xmlChar *
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @invalid: an integer
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a float and updates @num with the value. @cur is
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * updated to point just after the float. The float must have a
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2-digits integer part and may or may not have a decimal part.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In case of error, @invalid is set to %TRUE, values of @num and
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur are undefined.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PARSE_FLOAT(num, cur, invalid)				\
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PARSE_2_DIGITS(num, cur, VALID_ALWAYS, invalid);	\
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!invalid && (*cur == '.')) {			\
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    double mult = 1;				        \
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur++;						\
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((*cur < '0') || (*cur > '9'))			\
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		invalid = 1;					\
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    while ((*cur >= '0') && (*cur <= '9')) {		\
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		mult /= 10;					\
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		num += (*cur - '0') * mult;			\
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		cur++;						\
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }							\
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FORMAT_FLOAT:
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @num:  the double to format
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur: a pointer to an allocated buffer
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @pad: a flag for padding to 2 integer digits
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats a float. Result is appended to @cur and @cur is updated to
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * point after the integer. If the @pad flag is non-zero, then the
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * float representation has a minimum 2-digits integer part. The
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * fractional part is formatted if @num has a fractional value.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FORMAT_FLOAT(num, cur, pad)				\
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{							\
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xmlChar *sav, *str;                                 \
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((pad) && (num < 10.0))                          \
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *cur++ = '0';                                   \
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            str = xmlXPathCastNumberToString(num);              \
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sav = str;                                          \
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            while (*str != 0)                                   \
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *cur++ = *str++;                                \
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            xmlFree(sav);                                       \
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateParseGMonth:
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  pointer to a date structure
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @str: pointer to the string to analyze
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a xs:gMonth without time zone and fills in the appropriate
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * field of the @dt structure. @str is updated to point just after the
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:gMonth.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 0 or the error code
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateParseGMonth (exsltDateValDatePtr dt, const xmlChar **str)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *cur = *str;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = 0;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PARSE_2_DIGITS(dt->mon, cur, VALID_MONTH, ret);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret != 0)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return ret;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *str = cur;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_EXSLT_DATE
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltGenericDebug(xsltGenericDebugContext,
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "Parsed month %02i\n", dt->mon);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FORMAT_GMONTH:
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @mon:  the month to format
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur: a pointer to an allocated buffer
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @mon in xsl:gMonth format. Result is appended to @cur and
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur is updated to point after the xsl:gMonth.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FORMAT_GMONTH(mon, cur)					\
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_2_DIGITS(mon, cur)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateParseGDay:
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  pointer to a date structure
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @str: pointer to the string to analyze
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a xs:gDay without time zone and fills in the appropriate
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * field of the @dt structure. @str is updated to point just after the
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:gDay.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 0 or the error code
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateParseGDay (exsltDateValDatePtr dt, const xmlChar **str)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *cur = *str;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = 0;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PARSE_2_DIGITS(dt->day, cur, VALID_DAY, ret);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret != 0)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return ret;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *str = cur;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_EXSLT_DATE
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltGenericDebug(xsltGenericDebugContext,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "Parsed day %02i\n", dt->day);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FORMAT_GDAY:
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  the #exsltDateValDate to format
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur: a pointer to an allocated buffer
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @dt in xsl:gDay format. Result is appended to @cur and
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur is updated to point after the xsl:gDay.
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FORMAT_GDAY(dt, cur)					\
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_2_DIGITS(dt->day, cur)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FORMAT_DATE:
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  the #exsltDateValDate to format
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur: a pointer to an allocated buffer
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @dt in xsl:date format. Result is appended to @cur and
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur is updated to point after the xsl:date.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FORMAT_DATE(dt, cur)					\
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_GYEAR(dt->year, cur);				\
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*cur = '-';						\
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;							\
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_GMONTH(dt->mon, cur);				\
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*cur = '-';						\
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;							\
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_GDAY(dt, cur);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateParseTime:
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  pointer to a date structure
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @str: pointer to the string to analyze
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a xs:time without time zone and fills in the appropriate
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * fields of the @dt structure. @str is updated to point just after the
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:time.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In case of error, values of @dt fields are undefined.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 0 or the error code
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateParseTime (exsltDateValDatePtr dt, const xmlChar **str)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *cur = *str;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int hour = 0; /* use temp var in case str is not xs:time */
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = 0;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PARSE_2_DIGITS(hour, cur, VALID_HOUR, ret);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret != 0)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return ret;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*cur != ':')
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 1;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur++;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* the ':' insures this string is xs:time */
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dt->hour = hour;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PARSE_2_DIGITS(dt->min, cur, VALID_MIN, ret);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret != 0)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return ret;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*cur != ':')
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 1;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur++;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PARSE_FLOAT(dt->sec, cur, ret);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret != 0)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return ret;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!VALID_TIME(dt))
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 2;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *str = cur;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_EXSLT_DATE
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltGenericDebug(xsltGenericDebugContext,
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "Parsed time %02i:%02i:%02.f\n",
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     dt->hour, dt->min, dt->sec);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FORMAT_TIME:
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  the #exsltDateValDate to format
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur: a pointer to an allocated buffer
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @dt in xsl:time format. Result is appended to @cur and
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur is updated to point after the xsl:time.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FORMAT_TIME(dt, cur)					\
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_2_DIGITS(dt->hour, cur);				\
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*cur = ':';						\
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;							\
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_2_DIGITS(dt->min, cur);				\
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*cur = ':';						\
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;							\
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_FLOAT(dt->sec, cur, 1);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateParseTimeZone:
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  pointer to a date structure
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @str: pointer to the string to analyze
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a time zone without time zone and fills in the appropriate
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * field of the @dt structure. @str is updated to point just after the
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * time zone.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 0 or the error code
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateParseTimeZone (exsltDateValDatePtr dt, const xmlChar **str)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *cur;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = 0;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (str == NULL)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return -1;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur = *str;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (*cur) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0:
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt->tz_flag = 0;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt->tzo = 0;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	break;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 'Z':
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt->tz_flag = 1;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt->tzo = 0;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	break;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '+':
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '-': {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int isneg = 0, tmp = 0;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	isneg = (*cur == '-');
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PARSE_2_DIGITS(tmp, cur, VALID_HOUR, ret);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ret != 0)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return ret;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (*cur != ':')
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return 1;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt->tzo = tmp * 60;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PARSE_2_DIGITS(tmp, cur, VALID_MIN, ret);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ret != 0)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return ret;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt->tzo += tmp;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (isneg)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    dt->tzo = - dt->tzo;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!VALID_TZO(dt->tzo))
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return 2;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	break;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 1;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *str = cur;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_EXSLT_DATE
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltGenericDebug(xsltGenericDebugContext,
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "Parsed time zone offset (%s) %i\n",
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     dt->tz_flag ? "explicit" : "implicit", dt->tzo);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FORMAT_TZ:
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @tzo:  the timezone offset to format
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur: a pointer to an allocated buffer
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @tzo timezone. Result is appended to @cur and
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur is updated to point after the timezone.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FORMAT_TZ(tzo, cur)					\
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tzo == 0) {					        \
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *cur = 'Z';						\
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur++;						\
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {						\
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    int aTzo = (tzo < 0) ? - tzo : tzo;                 \
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    int tzHh = aTzo / 60, tzMm = aTzo % 60;		\
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *cur = (tzo < 0) ? '-' : '+' ;			\
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur++;						\
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    FORMAT_2_DIGITS(tzHh, cur);				\
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *cur = ':';						\
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur++;						\
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    FORMAT_2_DIGITS(tzMm, cur);				\
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/****************************************************************
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *	XML Schema Dates/Times Datatypes Handling		*
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ****************************************************************/
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateCreateDate:
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type:       type to create
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates a new #exsltDateVal, uninitialized.
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the #exsltDateValPtr
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static exsltDateValPtr
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateCreateDate (exsltDateType type)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr ret;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = (exsltDateValPtr) xmlMalloc(sizeof(exsltDateVal));
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL) {
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltGenericError(xsltGenericErrorContext,
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 "exsltDateCreateDate: out of memory\n");
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return (NULL);
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset (ret, 0, sizeof(exsltDateVal));
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (type != EXSLT_UNKNOWN)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret->type = type;
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateFreeDate:
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @date: an #exsltDateValPtr
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Frees up the @date
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateFreeDate (exsltDateValPtr date) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (date == NULL)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(date);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PARSE_DIGITS:
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @num:  the integer to fill in
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur:  an #xmlChar *
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @num_type: an integer flag
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a digits integer and updates @num with the value. @cur is
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * updated to point just after the integer.
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In case of error, @num_type is set to -1, values of @num and
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur are undefined.
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PARSE_DIGITS(num, cur, num_type)	                \
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((*cur < '0') || (*cur > '9'))			\
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    num_type = -1;					\
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else                                                    \
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    while ((*cur >= '0') && (*cur <= '9')) {		\
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        num = num * 10 + (*cur - '0');		        \
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        cur++;                                          \
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PARSE_NUM:
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @num:  the double to fill in
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur:  an #xmlChar *
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @num_type: an integer flag
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a float or integer and updates @num with the value. @cur is
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * updated to point just after the number. If the number is a float,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * then it must have an integer part and a decimal part; @num_type will
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * be set to 1. If there is no decimal part, @num_type is set to zero.
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In case of error, @num_type is set to -1, values of @num and
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur are undefined.
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PARSE_NUM(num, cur, num_type)				\
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num = 0;                                                \
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PARSE_DIGITS(num, cur, num_type);	                \
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!num_type && (*cur == '.')) {			\
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    double mult = 1;				        \
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur++;						\
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if ((*cur < '0') || (*cur > '9'))			\
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		num_type = -1;					\
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else                                                \
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                num_type = 1;                                   \
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    while ((*cur >= '0') && (*cur <= '9')) {		\
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		mult /= 10;					\
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		num += (*cur - '0') * mult;			\
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		cur++;						\
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }							\
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateCurrent:
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the current date and time.
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static exsltDateValPtr
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateCurrent (void)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct tm localTm, gmTm;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    time_t secs;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int local_s, gm_s;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr ret;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateCreateDate(XS_DATETIME);
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* get current time */
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    secs    = time(NULL);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if HAVE_LOCALTIME_R
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    localtime_r(&secs, &localTm);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    localTm = *localtime(&secs);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* get real year, not years since 1900 */
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.date.year = localTm.tm_year + 1900;
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.date.mon  = localTm.tm_mon + 1;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.date.day  = localTm.tm_mday;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.date.hour = localTm.tm_hour;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.date.min  = localTm.tm_min;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* floating point seconds */
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.date.sec  = (double) localTm.tm_sec;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* determine the time zone offset from local to gm time */
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if HAVE_GMTIME_R
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gmtime_r(&secs, &gmTm);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gmTm = *gmtime(&secs);
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.date.tz_flag = 0;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.date.tzo = (((ret->value.date.day * 1440) +
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            (ret->value.date.hour * 60) +
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ret->value.date.min) -
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ((gmTm.tm_mday * 1440) + (gmTm.tm_hour * 60) +
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             gmTm.tm_min));
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    local_s = localTm.tm_hour * SECS_PER_HOUR +
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        localTm.tm_min * SECS_PER_MIN +
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        localTm.tm_sec;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gm_s = gmTm.tm_hour * SECS_PER_HOUR +
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gmTm.tm_min * SECS_PER_MIN +
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gmTm.tm_sec;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (localTm.tm_year < gmTm.tm_year) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 	ret->value.date.tzo = -((SECS_PER_DAY - local_s) + gm_s)/60;
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (localTm.tm_year > gmTm.tm_year) {
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 	ret->value.date.tzo = ((SECS_PER_DAY - gm_s) + local_s)/60;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (localTm.tm_mon < gmTm.tm_mon) {
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 	ret->value.date.tzo = -((SECS_PER_DAY - local_s) + gm_s)/60;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (localTm.tm_mon > gmTm.tm_mon) {
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 	ret->value.date.tzo = ((SECS_PER_DAY - gm_s) + local_s)/60;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (localTm.tm_mday < gmTm.tm_mday) {
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 	ret->value.date.tzo = -((SECS_PER_DAY - local_s) + gm_s)/60;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (localTm.tm_mday > gmTm.tm_mday) {
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 	ret->value.date.tzo = ((SECS_PER_DAY - gm_s) + local_s)/60;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else  {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 	ret->value.date.tzo = (local_s - gm_s)/60;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateParse:
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime:  string to analyze
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a date/time string
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a newly built #exsltDateValPtr of NULL in case of error
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static exsltDateValPtr
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateParse (const xmlChar *dateTime)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *cur = dateTime;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RETURN_TYPE_IF_VALID(t)					\
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IS_TZO_CHAR(*cur)) {					\
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = _exsltDateParseTimeZone(&(dt->value.date), &cur);	\
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ret == 0) {						\
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (*cur != 0)					\
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto error;					\
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    dt->type = t;					\
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return dt;						\
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}							\
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dt = exsltDateCreateDate(EXSLT_UNKNOWN);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt == NULL)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((cur[0] == '-') && (cur[1] == '-')) {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * xs:gDay)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur += 2;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* is it an xs:gDay? */
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (*cur == '-') {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  ++cur;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ret = _exsltDateParseGDay(&(dt->value.date), &cur);
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (ret != 0)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto error;
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    RETURN_TYPE_IF_VALID(XS_GDAY);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * it should be an xs:gMonthDay or xs:gMonth
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = _exsltDateParseGMonth(&(dt->value.date), &cur);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ret != 0)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (*cur != '-')
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* is it an xs:gMonth? */
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (*cur == '-') {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur++;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    RETURN_TYPE_IF_VALID(XS_GMONTH);
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* it should be an xs:gMonthDay */
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = _exsltDateParseGDay(&(dt->value.date), &cur);
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ret != 0)
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto error;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	RETURN_TYPE_IF_VALID(XS_GMONTHDAY);
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * It's a right-truncated date or an xs:time.
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Try to parse an xs:time then fallback on right-truncated dates.
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*cur >= '0') && (*cur <= '9')) {
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = _exsltDateParseTime(&(dt->value.date), &cur);
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ret == 0) {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* it's an xs:time */
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    RETURN_TYPE_IF_VALID(XS_TIME);
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* fallback on date parsing */
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur = dateTime;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = _exsltDateParseGYear(&(dt->value.date), &cur);
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret != 0)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* is it an xs:gYear? */
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RETURN_TYPE_IF_VALID(XS_GYEAR);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*cur != '-')
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur++;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = _exsltDateParseGMonth(&(dt->value.date), &cur);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret != 0)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* is it an xs:gYearMonth? */
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RETURN_TYPE_IF_VALID(XS_GYEARMONTH);
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*cur != '-')
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur++;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = _exsltDateParseGDay(&(dt->value.date), &cur);
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error;
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* is it an xs:date? */
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RETURN_TYPE_IF_VALID(XS_DATE);
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*cur != 'T')
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur++;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* it should be an xs:dateTime */
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = _exsltDateParseTime(&(dt->value.date), &cur);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret != 0)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = _exsltDateParseTimeZone(&(dt->value.date), &cur);
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ret != 0) || (*cur != 0) || !VALID_DATETIME((&(dt->value.date))))
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto error;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dt->type = XS_DATETIME;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dt;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error:
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	exsltDateFreeDate(dt);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateParseDuration:
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @duration:  string to analyze
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses a duration string
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a newly built #exsltDateValPtr of NULL in case of error
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static exsltDateValPtr
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateParseDuration (const xmlChar *duration)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar  *cur = duration;
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dur;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int isneg = 0;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int seq = 0;
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (duration == NULL)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*cur == '-') {
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        isneg = 1;
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cur++;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* duration must start with 'P' (after sign) */
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*cur++ != 'P')
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dur = exsltDateCreateDate(XS_DURATION);
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dur == NULL)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (*cur != 0) {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double         num;
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int            num_type = 0;  /* -1 = invalid, 0 = int, 1 = floating */
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const xmlChar  desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const double   multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* input string should be empty or invalid date/time item */
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (seq >= sizeof(desig))
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto error;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* T designator must be present for time items */
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (*cur == 'T') {
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (seq <= 3) {
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                seq = 3;
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                cur++;
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            } else
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return NULL;
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (seq == 3)
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto error;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* parse the number portion of the item */
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PARSE_NUM(num, cur, num_type);
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((num_type == -1) || (*cur == 0))
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto error;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* update duration based on item type */
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (seq < sizeof(desig)) {
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (*cur == desig[seq]) {
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* verify numeric type; only seconds can be float */
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if ((num_type != 0) && (seq < (sizeof(desig)-1)))
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    goto error;
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                switch (seq) {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    case 0:
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dur->value.dur.mon = (long)num * 12;
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    case 1:
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dur->value.dur.mon += (long)num;
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    default:
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        /* convert to seconds using multiplier */
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        dur->value.dur.sec += num * multi[seq];
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        seq++;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;          /* exit loop */
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* no date designators found? */
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (++seq == 3)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                goto error;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cur++;
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (isneg) {
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dur->value.dur.mon = -dur->value.dur.mon;
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dur->value.dur.day = -dur->value.dur.day;
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dur->value.dur.sec = -dur->value.dur.sec;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_EXSLT_DATE
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltGenericDebug(xsltGenericDebugContext,
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     "Parsed duration %f\n", dur->value.dur.sec);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dur;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error:
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dur != NULL)
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	exsltDateFreeDate(dur);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FORMAT_ITEM:
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @num:        number to format
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @cur:        current location to convert number
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @limit:      max value
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @item:       char designator
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FORMAT_ITEM(num, cur, limit, item)                      \
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (num != 0) {                                         \
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            long comp = (long)num / limit;                      \
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (comp != 0) {                                    \
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                FORMAT_FLOAT((double)comp, cur, 0);             \
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                *cur++ = item;                                  \
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                num -= (double)(comp * limit);                  \
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }                                                   \
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateFormatDuration:
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt: an #exsltDateValDurationPtr
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @dt in xs:duration format.
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a newly allocated string, or NULL in case of error
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateFormatDuration (const exsltDateValDurationPtr dt)
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar buf[100], *cur = buf;
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double secs, days;
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double years, months;
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt == NULL)
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* quick and dirty check */
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dt->sec == 0.0) && (dt->day == 0) && (dt->mon == 0))
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return xmlStrdup((xmlChar*)"P0D");
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    secs   = dt->sec;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    days   = (double)dt->day;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    years  = (double)(dt->mon / 12);
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    months = (double)(dt->mon % 12);
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *cur = '\0';
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (secs < 0.0) {
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        secs = -secs;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *cur = '-';
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (days < 0) {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        days = -days;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *cur = '-';
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (years < 0) {
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        years = -years;
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *cur = '-';
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (months < 0) {
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        months = -months;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *cur = '-';
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*cur == '-')
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur++;
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *cur++ = 'P';
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (years != 0.0) {
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FORMAT_ITEM(years, cur, 1, 'Y');
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (months != 0.0) {
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FORMAT_ITEM(months, cur, 1, 'M');
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (secs >= SECS_PER_DAY) {
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double tmp = floor(secs / SECS_PER_DAY);
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        days += tmp;
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        secs -= (tmp * SECS_PER_DAY);
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMAT_ITEM(days, cur, 1, 'D');
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (secs > 0.0) {
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *cur++ = 'T';
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMAT_ITEM(secs, cur, SECS_PER_HOUR, 'H');
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMAT_ITEM(secs, cur, SECS_PER_MIN, 'M');
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (secs > 0.0) {
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FORMAT_FLOAT(secs, cur, 0);
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *cur++ = 'S';
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *cur = 0;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return xmlStrdup(buf);
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateFormatDateTime:
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt: an #exsltDateValDatePtr
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @dt in xs:dateTime format.
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a newly allocated string, or NULL in case of error
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateFormatDateTime (const exsltDateValDatePtr dt)
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar buf[100], *cur = buf;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dt == NULL) ||	!VALID_DATETIME(dt))
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMAT_DATE(dt, cur);
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *cur = 'T';
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur++;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMAT_TIME(dt, cur);
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMAT_TZ(dt->tzo, cur);
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *cur = 0;
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return xmlStrdup(buf);
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateFormatDate:
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt: an #exsltDateValDatePtr
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @dt in xs:date format.
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a newly allocated string, or NULL in case of error
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateFormatDate (const exsltDateValDatePtr dt)
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar buf[100], *cur = buf;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dt == NULL) || !VALID_DATETIME(dt))
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMAT_DATE(dt, cur);
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt->tz_flag || (dt->tzo != 0)) {
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_TZ(dt->tzo, cur);
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *cur = 0;
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return xmlStrdup(buf);
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateFormatTime:
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt: an #exsltDateValDatePtr
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @dt in xs:time format.
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a newly allocated string, or NULL in case of error
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateFormatTime (const exsltDateValDatePtr dt)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar buf[100], *cur = buf;
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dt == NULL) || !VALID_TIME(dt))
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FORMAT_TIME(dt, cur);
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt->tz_flag || (dt->tzo != 0)) {
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	FORMAT_TZ(dt->tzo, cur);
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *cur = 0;
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return xmlStrdup(buf);
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateFormat:
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt: an #exsltDateValPtr
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Formats @dt in the proper format.
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note: xs:gmonth and xs:gday are not formatted as there are no
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * routines that output them.
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns a newly allocated string, or NULL in case of error
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateFormat (const exsltDateValPtr dt)
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt == NULL)
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (dt->type) {
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case XS_DURATION:
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return exsltDateFormatDuration(&(dt->value.dur));
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case XS_DATETIME:
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return exsltDateFormatDateTime(&(dt->value.date));
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case XS_DATE:
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return exsltDateFormatDate(&(dt->value.date));
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case XS_TIME:
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return exsltDateFormatTime(&(dt->value.date));
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt->type & XS_GYEAR) {
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlChar buf[20], *cur = buf;
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FORMAT_GYEAR(dt->value.date.year, cur);
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (dt->type == XS_GYEARMONTH) {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    *cur = '-';
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cur++;
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    FORMAT_GMONTH(dt->value.date.mon, cur);
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (dt->value.date.tz_flag || (dt->value.date.tzo != 0)) {
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    FORMAT_TZ(dt->value.date.tzo, cur);
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *cur = 0;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return xmlStrdup(buf);
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateCastYMToDays:
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt: an #exsltDateValPtr
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Convert mon and year of @dt to total number of days. Take the
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * number of years since (or before) 1 AD and add the number of leap
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * years. This is a function  because negative
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * years must be handled a little differently and there is no zero year.
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns number of days.
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static long
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateCastYMToDays (const exsltDateValPtr dt)
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long ret;
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt->value.date.year < 0)
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret = (dt->value.date.year * 365) +
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((dt->value.date.year+1)/400)) +
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              DAY_IN_YEAR(0, dt->value.date.mon, dt->value.date.year);
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret = ((dt->value.date.year-1) * 365) +
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               ((dt->value.date.year-1)/400)) +
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              DAY_IN_YEAR(0, dt->value.date.mon, dt->value.date.year);
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TIME_TO_NUMBER:
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  an #exsltDateValPtr
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculates the number of seconds in the time portion of @dt.
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns seconds.
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TIME_TO_NUMBER(dt)                              \
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (dt->value.date.min * SECS_PER_MIN)) + dt->value.date.sec)
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateCastDateToNumber:
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt:  an #exsltDateValPtr
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculates the number of seconds from year zero.
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns seconds from zero year.
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateCastDateToNumber (const exsltDateValPtr dt)
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret = 0.0;
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt == NULL)
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0.0;
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dt->type & XS_GYEAR) == XS_GYEAR) {
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret = (double)_exsltDateCastYMToDays(dt) * SECS_PER_DAY;
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* add in days */
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt->type == XS_DURATION) {
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret += (double)dt->value.dur.day * SECS_PER_DAY;
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret += dt->value.dur.sec;
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret += (double)dt->value.date.day * SECS_PER_DAY;
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* add in time */
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret += TIME_TO_NUMBER(dt);
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateTruncateDate:
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt: an #exsltDateValPtr
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type: dateTime type to set to
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Set @dt to truncated @type.
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 0 success, non-zero otherwise.
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateTruncateDate (exsltDateValPtr dt, exsltDateType type)
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt == NULL)
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 1;
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((type & XS_TIME) != XS_TIME) {
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dt->value.date.hour = 0;
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dt->value.date.min  = 0;
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dt->value.date.sec  = 0.0;
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((type & XS_GDAY) != XS_GDAY)
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dt->value.date.day = 0;
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((type & XS_GMONTH) != XS_GMONTH)
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dt->value.date.mon = 0;
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((type & XS_GYEAR) != XS_GYEAR)
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dt->value.date.year = 0;
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dt->type = type;
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDayInWeek:
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @yday: year day (1-366)
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @yr: year
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Determine the day-in-week from @yday and @yr. 0001-01-01 was
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a Monday so all other days are calculated from there. Take the
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * number of years since (or before) add the number of leap years and
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the day-in-year and mod by 7. This is a function  because negative
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * years must be handled a little differently and there is no zero year.
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns day in week (Sunday = 0).
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static long
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateDayInWeek(long yday, long yr)
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long ret;
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (yr < 0) {
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret = ((yr + (((yr+1)/4)-((yr+1)/100)+((yr+1)/400)) + yday) % 7);
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (ret < 0)
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ret += 7;
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret = (((yr-1) + (((yr-1)/4)-((yr-1)/100)+((yr-1)/400)) + yday) % 7);
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * macros for adding date/times and durations
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FQUOTIENT(a,b)                  ((floor(((double)a/(double)b))))
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODULO(a,b)                     ((a - FQUOTIENT(a,b) * b))
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateAdd:
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt: an #exsltDateValPtr
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dur: an #exsltDateValPtr of type #XS_DURATION
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Compute a new date/time from @dt and @dur. This function assumes @dt
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is either #XS_DATETIME, #XS_DATE, #XS_GYEARMONTH, or #XS_GYEAR.
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns date/time pointer or NULL.
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static exsltDateValPtr
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateAdd (exsltDateValPtr dt, exsltDateValPtr dur)
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr ret;
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long carry, tempdays, temp;
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValDatePtr r, d;
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValDurationPtr u;
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dt == NULL) || (dur == NULL))
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateCreateDate(dt->type);
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r = &(ret->value.date);
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    d = &(dt->value.date);
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u = &(dur->value.dur);
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* normalization */
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (d->mon == 0)
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        d->mon = 1;
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* normalize for time zone offset */
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u->sec -= (d->tzo * 60);	/* changed from + to - (bug 153000) */
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    d->tzo = 0;
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* normalization */
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (d->day == 0)
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        d->day = 1;
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* month */
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    carry  = d->mon + u->mon;
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r->mon = (unsigned int)MODULO_RANGE(carry, 1, 13);
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    carry  = (long)FQUOTIENT_RANGE(carry, 1, 13);
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* year (may be modified later) */
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r->year = d->year + carry;
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (r->year == 0) {
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (d->year > 0)
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            r->year--;
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            r->year++;
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* time zone */
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r->tzo     = d->tzo;
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r->tz_flag = d->tz_flag;
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* seconds */
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r->sec = d->sec + u->sec;
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    carry  = (long)FQUOTIENT((long)r->sec, 60);
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (r->sec != 0.0) {
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        r->sec = MODULO(r->sec, 60.0);
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* minute */
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    carry += d->min;
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r->min = (unsigned int)MODULO(carry, 60);
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    carry  = (long)FQUOTIENT(carry, 60);
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* hours */
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    carry  += d->hour;
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r->hour = (unsigned int)MODULO(carry, 24);
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    carry   = (long)FQUOTIENT(carry, 24);
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * days
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Note we use tempdays because the temporary values may need more
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * than 5 bits
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (d->day > MAX_DAYINMONTH(r->year, r->mon)))
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tempdays = MAX_DAYINMONTH(r->year, r->mon);
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (d->day < 1)
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tempdays = 1;
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tempdays = d->day;
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tempdays += u->day + carry;
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (1) {
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (tempdays < 1) {
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            long tmon = (long)MODULO_RANGE((int)r->mon-1, 1, 13);
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            long tyr  = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (tyr == 0)
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                tyr--;
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /*
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * Coverity detected an overrun in daysInMonth
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * of size 12 at position 12 with index variable "((r)->mon - 1)"
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     */
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (tmon < 0)
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        tmon = 0;
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (tmon > 12)
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        tmon = 12;
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tempdays += MAX_DAYINMONTH(tyr, tmon);
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            carry = -1;
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (tempdays > (long)MAX_DAYINMONTH(r->year, r->mon)) {
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            carry = 1;
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        temp = r->mon + carry;
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        r->mon = (unsigned int)MODULO_RANGE(temp, 1, 13);
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        r->year = r->year + (long)FQUOTIENT_RANGE(temp, 1, 13);
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (r->year == 0) {
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (temp < 1)
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                r->year--;
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                r->year++;
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    r->day = tempdays;
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * adjust the date/time type to the date values
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret->type != XS_DATETIME) {
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((r->hour) || (r->min) || (r->sec))
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ret->type = XS_DATETIME;
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else if (ret->type != XS_DATE) {
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((r->mon != 1) && (r->day != 1))
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ret->type = XS_DATE;
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if ((ret->type != XS_GYEARMONTH) && (r->mon != 1))
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ret->type = XS_GYEARMONTH;
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateNormalize:
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dt: an #exsltDateValPtr
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Normalize @dt to GMT time.
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateNormalize (exsltDateValPtr dt)
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dur, tmp;
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt == NULL)
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (((dt->type & XS_TIME) != XS_TIME) || (dt->value.date.tzo == 0))
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dur = exsltDateCreateDate(XS_DURATION);
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dur == NULL)
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tmp = _exsltDateAdd(dt, dur);
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tmp == NULL)
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(dt, tmp, sizeof(exsltDateVal));
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(tmp);
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dur);
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dt->value.date.tzo = 0;
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateDifference:
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @x: an #exsltDateValPtr
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @y: an #exsltDateValPtr
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @flag: force difference in days
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Calculate the difference between @x and @y as a duration
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (i.e. y - x). If the @flag is set then even if the least specific
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * format of @x or @y is xs:gYear or xs:gYearMonth.
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns date/time pointer or NULL.
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static exsltDateValPtr
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateDifference (exsltDateValPtr x, exsltDateValPtr y, int flag)
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr ret;
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((x == NULL) || (y == NULL))
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (((x->type < XS_GYEAR) || (x->type > XS_DATETIME)) ||
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ((y->type < XS_GYEAR) || (y->type > XS_DATETIME)))
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateNormalize(x);
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateNormalize(y);
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * the operand with the most specific format must be converted to
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * the same type as the operand with the least specific format.
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (x->type != y->type) {
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (x->type < y->type) {
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            _exsltDateTruncateDate(y, x->type);
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            _exsltDateTruncateDate(x, y->type);
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateCreateDate(XS_DURATION);
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (((x->type == XS_GYEAR) || (x->type == XS_GYEARMONTH)) && (!flag)) {
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* compute the difference in months */
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret->value.dur.mon = ((y->value.date.year * 12) + y->value.date.mon) -
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ((x->value.date.year * 12) + x->value.date.mon);
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* The above will give a wrong result if x and y are on different sides
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 of the September 1752. Resolution is welcome :-) */
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret->value.dur.day  = _exsltDateCastYMToDays(y) -
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              _exsltDateCastYMToDays(x);
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret->value.dur.day += y->value.date.day - x->value.date.day;
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret->value.dur.sec  = TIME_TO_NUMBER(y) - TIME_TO_NUMBER(x);
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ret->value.dur.day > 0.0 && ret->value.dur.sec < 0.0) {
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ret->value.dur.day -= 1;
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ret->value.dur.sec = ret->value.dur.sec + SECS_PER_DAY;
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else if (ret->value.dur.day < 0.0 && ret->value.dur.sec > 0.0) {
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ret->value.dur.day += 1;
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ret->value.dur.sec = ret->value.dur.sec - SECS_PER_DAY;
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateAddDurCalc
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ret: an exsltDateValPtr for the return value:
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @x: an exsltDateValPtr for the first operand
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @y: an exsltDateValPtr for the second operand
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Add two durations, catering for possible negative values.
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The sum is placed in @ret.
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 1 for success, 0 if error detected.
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateAddDurCalc (exsltDateValPtr ret, exsltDateValPtr x,
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      exsltDateValPtr y)
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long carry;
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* months */
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.dur.mon = x->value.dur.mon + y->value.dur.mon;
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* seconds */
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.dur.sec = x->value.dur.sec + y->value.dur.sec;
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    carry = (long)FQUOTIENT(ret->value.dur.sec, SECS_PER_DAY);
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret->value.dur.sec != 0.0) {
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret->value.dur.sec = MODULO(ret->value.dur.sec, SECS_PER_DAY);
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/*
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * Our function MODULO always gives us a positive value, so
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * if we end up with a "-ve" carry we need to adjust it
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * appropriately (bug 154021)
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((carry < 0) && (ret->value.dur.sec != 0)) {
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* change seconds to equiv negative modulus */
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ret->value.dur.sec = ret->value.dur.sec - SECS_PER_DAY;
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    carry++;
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* days */
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret->value.dur.day = x->value.dur.day + y->value.dur.day + carry;
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * are the results indeterminate? i.e. how do you subtract days from
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * months or years?
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((((ret->value.dur.day > 0) || (ret->value.dur.sec > 0)) &&
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (ret->value.dur.mon < 0)) ||
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (((ret->value.dur.day < 0) || (ret->value.dur.sec < 0)) &&
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (ret->value.dur.mon > 0))) {
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0;
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * _exsltDateAddDuration:
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @x: an #exsltDateValPtr of type #XS_DURATION
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @y: an #exsltDateValPtr of type #XS_DURATION
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Compute a new duration from @x and @y.
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns date/time pointer or NULL.
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static exsltDateValPtr
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_exsltDateAddDuration (exsltDateValPtr x, exsltDateValPtr y)
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr ret;
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((x == NULL) || (y == NULL))
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateCreateDate(XS_DURATION);
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (_exsltDateAddDurCalc(ret, x, y))
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ret;
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(ret);
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/****************************************************************
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *		EXSLT - Dates and Times functions		*
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ****************************************************************/
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDateTime:
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times date-time() function:
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     string date:date-time()
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the current date and time as a date/time string.
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDateTime (void)
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret = NULL;
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr cur;
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur = exsltDateCurrent();
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur != NULL) {
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ret = exsltDateFormatDateTime(&(cur->value.date));
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	exsltDateFreeDate(cur);
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDate:
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times date() function:
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     string date:date (string?)
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the date specified in the date/time string given as the
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument.  If no argument is given, then the current local
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date/time, as returned by date:date-time is used as a default
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument.
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as an argument must be a string in
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the format defined as the lexical representation of either
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:dateTime or xs:date.  If the argument is not in either of these
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * formats, returns NULL.
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDate (const xmlChar *dateTime)
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt = NULL;
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret = NULL;
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return NULL;
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return NULL;
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return NULL;
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateFormatDate(&(dt->value.date));
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateTime:
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times time() function:
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     string date:time (string?)
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the time specified in the date/time string given as the
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument.  If no argument is given, then the current local
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date/time, as returned by date:date-time is used as a default
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument.
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as an argument must be a string in
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the format defined as the lexical representation of either
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:dateTime or xs:time.  If the argument is not in either of these
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * formats, returns NULL.
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateTime (const xmlChar *dateTime)
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt = NULL;
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret = NULL;
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return NULL;
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return NULL;
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_TIME)) {
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return NULL;
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateFormatTime(&(dt->value.date));
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateYear:
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times year() function
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:year (string?)
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the year of a date as a number.  If no argument is given,
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * then the current local date/time, as returned by date:date-time is
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * used as a default argument.
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the first argument must be a
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYearMonth (CCYY-MM)
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYear (CCYY)
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateYear (const xmlChar *dateTime)
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret;
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE) &&
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (dt->type != XS_GYEARMONTH) && (dt->type != XS_GYEAR)) {
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = (double) dt->value.date.year;
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateLeapYear:
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times leap-year() function:
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    boolean date:leap-yea (string?)
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns true if the year given in a date is a leap year.  If no
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument is given, then the current local date/time, as returned by
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used as a default argument.
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the first argument must be a
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYearMonth (CCYY-MM)
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYear (CCYY)
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlXPathObjectPtr
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateLeapYear (const xmlChar *dateTime)
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double year;
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    year = exsltDateYear(dateTime);
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlXPathIsNaN(year))
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return xmlXPathNewFloat(xmlXPathNAN);
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IS_LEAP((long)year))
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return xmlXPathNewBoolean(1);
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return xmlXPathNewBoolean(0);
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateMonthInYear:
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times month-in-year() function:
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:month-in-year (string?)
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the month of a date as a number.  If no argument is given,
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * then the current local date/time, as returned by date:date-time is
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * used the default argument.
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYearMonth (CCYY-MM)
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gMonth (--MM--)
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gMonthDay (--MM-DD)
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateMonthInYear (const xmlChar *dateTime)
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret;
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE) &&
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (dt->type != XS_GYEARMONTH) && (dt->type != XS_GMONTH) &&
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (dt->type != XS_GMONTHDAY)) {
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = (double) dt->value.date.mon;
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateMonthName:
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Time month-name() function
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    string date:month-name (string?)
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the full name of the month of a date.  If no argument is
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given, then the current local date/time, as returned by
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used the default argument.
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYearMonth (CCYY-MM)
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gMonth (--MM--)
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then an
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * empty string ('') is returned.
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The result is an English month name: one of 'January', 'February',
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 'March', 'April', 'May', 'June', 'July', 'August', 'September',
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 'October', 'November' or 'December'.
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const xmlChar *
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateMonthName (const xmlChar *dateTime)
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const xmlChar monthNames[13][10] = {
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { 0 },
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 },
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 },
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'M', 'a', 'r', 'c', 'h', 0 },
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'A', 'p', 'r', 'i', 'l', 0 },
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'M', 'a', 'y', 0 },
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'J', 'u', 'n', 'e', 0 },
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'J', 'u', 'l', 'y', 0 },
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'A', 'u', 'g', 'u', 's', 't', 0 },
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 },
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 },
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 },
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int month;
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    month = (int) exsltDateMonthInYear(dateTime);
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!VALID_MONTH(month))
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      month = 0;
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return monthNames[month];
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateMonthAbbreviation:
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Time month-abbreviation() function
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    string date:month-abbreviation (string?)
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the abbreviation of the month of a date.  If no argument is
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given, then the current local date/time, as returned by
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used the default argument.
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYearMonth (CCYY-MM)
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gMonth (--MM--)
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then an
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * empty string ('') is returned.
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The result is an English month abbreviation: one of 'Jan', 'Feb',
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov' or
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 'Dec'.
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const xmlChar *
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateMonthAbbreviation (const xmlChar *dateTime)
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const xmlChar monthAbbreviations[13][4] = {
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { 0 },
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'J', 'a', 'n', 0 },
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'F', 'e', 'b', 0 },
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'M', 'a', 'r', 0 },
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'A', 'p', 'r', 0 },
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'M', 'a', 'y', 0 },
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'J', 'u', 'n', 0 },
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'J', 'u', 'l', 0 },
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'A', 'u', 'g', 0 },
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'S', 'e', 'p', 0 },
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'O', 'c', 't', 0 },
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'N', 'o', 'v', 0 },
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'D', 'e', 'c', 0 }
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int month;
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    month = (int) exsltDateMonthInYear(dateTime);
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(!VALID_MONTH(month))
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      month = 0;
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return monthAbbreviations[month];
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateWeekInYear:
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times week-in-year() function
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:week-in-year (string?)
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the week of the year as a number.  If no argument is given,
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * then the current local date/time, as returned by date:date-time is
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * used as the default argument.  For the purposes of numbering,
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * counting follows ISO 8601: week 1 in a year is the week containing
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the first Thursday of the year, with new weeks beginning on a
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Monday.
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a right-truncated
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * string in the format defined as the lexical representation of
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:dateTime in one of the formats defined in [XML Schema Part 2:
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Datatypes].  The permitted formats are as follows:
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateWeekInYear (const xmlChar *dateTime)
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long diy, diw, year, ret;
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    diy = DAY_IN_YEAR(dt->value.date.day, dt->value.date.mon,
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      dt->value.date.year);
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Determine day-in-week (0=Sun, 1=Mon, etc.) then adjust so Monday
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * is the first day-in-week
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    diw = (_exsltDateDayInWeek(diy, dt->value.date.year) + 6) % 7;
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* ISO 8601 adjustment, 3 is Thu */
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    diy += (3 - diw);
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if(diy < 1) {
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	year = dt->value.date.year - 1;
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if(year == 0) year--;
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	diy = DAY_IN_YEAR(31, 12, year) + diy;
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (diy > (long)DAY_IN_YEAR(31, 12, dt->value.date.year)) {
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	diy -= DAY_IN_YEAR(31, 12, dt->value.date.year);
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = ((diy - 1) / 7) + 1;
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (double) ret;
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateWeekInMonth:
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times week-in-month() function
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:week-in-month (string?)
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date:week-in-month function returns the week in a month of a
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date as a number. If no argument is given, then the current local
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date/time, as returned by date:date-time is used the default
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument. For the purposes of numbering, the first day of the month
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is in week 1 and new weeks begin on a Monday (so the first and last
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * weeks in a month will often have less than 7 days in them).
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a right-truncated
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * string in the format defined as the lexical representation of
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:dateTime in one of the formats defined in [XML Schema Part 2:
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Datatypes].  The permitted formats are as follows:
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateWeekInMonth (const xmlChar *dateTime)
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long fdiy, fdiw, ret;
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fdiy = DAY_IN_YEAR(1, dt->value.date.mon, dt->value.date.year);
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Determine day-in-week (0=Sun, 1=Mon, etc.) then adjust so Monday
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * is the first day-in-week
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fdiw = (_exsltDateDayInWeek(fdiy, dt->value.date.year) + 6) % 7;
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = ((dt->value.date.day + fdiw - 1) / 7) + 1;
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (double) ret;
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayInYear:
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times day-in-year() function
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:day-in-year (string?)
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the day of a date in a year as a number.  If no argument is
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given, then the current local date/time, as returned by
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used the default argument.
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a right-truncated
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * string in the format defined as the lexical representation of
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:dateTime in one of the formats defined in [XML Schema Part 2:
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Datatypes].  The permitted formats are as follows:
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDayInYear (const xmlChar *dateTime)
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long ret;
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = DAY_IN_YEAR(dt->value.date.day, dt->value.date.mon,
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      dt->value.date.year);
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (double) ret;
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayInMonth:
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times day-in-month() function:
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:day-in-month (string?)
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the day of a date as a number.  If no argument is given,
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * then the current local date/time, as returned by date:date-time is
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * used the default argument.
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gMonthDay (--MM-DD)
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gDay (---DD)
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDayInMonth (const xmlChar *dateTime)
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret;
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE) &&
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (dt->type != XS_GMONTHDAY) && (dt->type != XS_GDAY)) {
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = (double) dt->value.date.day;
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayOfWeekInMonth:
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times day-of-week-in-month() function:
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:day-of-week-in-month (string?)
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the day-of-the-week in a month of a date as a number
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (e.g. 3 for the 3rd Tuesday in May).  If no argument is
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given, then the current local date/time, as returned by
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used the default argument.
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a right-truncated
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * string in the format defined as the lexical representation of
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:dateTime in one of the formats defined in [XML Schema Part 2:
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Datatypes].  The permitted formats are as follows:
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDayOfWeekInMonth (const xmlChar *dateTime)
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long ret;
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = ((dt->value.date.day -1) / 7) + 1;
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (double) ret;
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayInWeek:
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times day-in-week() function:
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:day-in-week (string?)
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the day of the week given in a date as a number.  If no
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument is given, then the current local date/time, as returned by
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used the default argument.
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The numbering of days of the week starts at 1 for Sunday, 2 for
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Monday and so on up to 7 for Saturday.
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDayInWeek (const xmlChar *dateTime)
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    long diy, ret;
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    diy = DAY_IN_YEAR(dt->value.date.day, dt->value.date.mon,
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      dt->value.date.year);
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = _exsltDateDayInWeek(diy, dt->value.date.year) + 1;
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (double) ret;
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayName:
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Time day-name() function
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    string date:day-name (string?)
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the full name of the day of the week of a date.  If no
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument is given, then the current local date/time, as returned by
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used the default argument.
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then an
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * empty string ('') is returned.
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The result is an English day name: one of 'Sunday', 'Monday',
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 'Tuesday', 'Wednesday', 'Thursday' or 'Friday'.
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const xmlChar *
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDayName (const xmlChar *dateTime)
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const xmlChar dayNames[8][10] = {
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { 0 },
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'S', 'u', 'n', 'd', 'a', 'y', 0 },
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'M', 'o', 'n', 'd', 'a', 'y', 0 },
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 },
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 },
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 },
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'F', 'r', 'i', 'd', 'a', 'y', 0 },
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int day;
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    day = (int) exsltDateDayInWeek(dateTime);
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if((day < 1) || (day > 7))
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      day = 0;
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dayNames[day];
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayAbbreviation:
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Time day-abbreviation() function
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    string date:day-abbreviation (string?)
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the abbreviation of the day of the week of a date.  If no
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument is given, then the current local date/time, as returned by
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used the default argument.
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then an
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * empty string ('') is returned.
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The result is a three-letter English day abbreviation: one of
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 'Sun', 'Mon', 'Tue', 'Wed', 'Thu' or 'Fri'.
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const xmlChar *
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDayAbbreviation (const xmlChar *dateTime)
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const xmlChar dayAbbreviations[8][4] = {
25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        { 0 },
25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'S', 'u', 'n', 0 },
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'M', 'o', 'n', 0 },
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'T', 'u', 'e', 0 },
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'W', 'e', 'd', 0 },
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'T', 'h', 'u', 0 },
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'F', 'r', 'i', 0 },
25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	{ 'S', 'a', 't', 0 }
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int day;
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    day = (int) exsltDateDayInWeek(dateTime);
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if((day < 1) || (day > 7))
25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      day = 0;
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dayAbbreviations[day];
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateHourInDay:
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times day-in-month() function:
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:day-in-month (string?)
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the hour of the day as a number.  If no argument is given,
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * then the current local date/time, as returned by date:date-time is
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * used the default argument.
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:time (hh:mm:ss)
25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateHourInDay (const xmlChar *dateTime)
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret;
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_TIME)) {
25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = (double) dt->value.date.hour;
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateMinuteInHour:
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times day-in-month() function:
25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:day-in-month (string?)
25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the minute of the hour as a number.  If no argument is
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given, then the current local date/time, as returned by
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used the default argument.
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:time (hh:mm:ss)
25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateMinuteInHour (const xmlChar *dateTime)
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret;
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_TIME)) {
26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = (double) dt->value.date.min;
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateSecondInMinute:
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times second-in-minute() function:
26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:day-in-month (string?)
26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the second of the minute as a number.  If no argument is
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given, then the current local date/time, as returned by
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:date-time is used the default argument.
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date/time string specified as the argument is a left or
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * right-truncated string in the format defined as the lexical
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representation of xs:dateTime in one of the formats defined in [XML
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Schema Part 2: Datatypes].  The permitted formats are as follows:
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:time (hh:mm:ss)
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string is not in one of these formats, then NaN is
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returned.
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the second or NaN.
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateSecondInMinute (const xmlChar *dateTime)
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret;
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateParse(dateTime);
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((dt->type != XS_DATETIME) && (dt->type != XS_TIME)) {
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate(dt);
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = dt->value.date.sec;
26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateAdd:
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @xstr: date/time string
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ystr: date/time string
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the date:add (string,string) function which returns the
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date/time * resulting from adding a duration to a date/time.
26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The first argument (@xstr) must be right-truncated date/time
26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * strings in one of the formats defined in [XML Schema Part 2:
26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Datatypes]. The permitted formats are as follows:
26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYearMonth (CCYY-MM)
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYear (CCYY)
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The second argument (@ystr) is a string in the format defined for
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:duration in [3.2.6 duration] of [XML Schema Part 2: Datatypes].
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The return value is a right-truncated date/time strings in one of
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the formats defined in [XML Schema Part 2: Datatypes] and listed
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above. This value is calculated using the algorithm described in
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [Appendix E Adding durations to dateTimes] of [XML Schema Part 2:
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Datatypes].
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns date/time string or NULL.
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateAdd (const xmlChar *xstr, const xmlChar *ystr)
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt, dur, res;
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar     *ret;
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((xstr == NULL) || (ystr == NULL))
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dt = exsltDateParse(xstr);
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt == NULL)
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if ((dt->type < XS_GYEAR) || (dt->type > XS_DATETIME)) {
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exsltDateFreeDate(dt);
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dur = exsltDateParseDuration(ystr);
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dur == NULL) {
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exsltDateFreeDate(dt);
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = _exsltDateAdd(dt, dur);
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dur);
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (res == NULL)
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateFormat(res);
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(res);
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateAddDuration:
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @xstr:      first duration string
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ystr:      second duration string
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the date:add-duration (string,string) function which returns
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the duration resulting from adding two durations together.
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Both arguments are strings in the format defined for xs:duration
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in [3.2.6 duration] of [XML Schema Part 2: Datatypes]. If either
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * argument is not in this format, the function returns an empty string
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ('').
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The return value is a string in the format defined for xs:duration
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in [3.2.6 duration] of [XML Schema Part 2: Datatypes].
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The durations can usually be added by summing the numbers given for
27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * each of the components in the durations. However, if the durations
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are differently signed, then this sometimes results in durations
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that are impossible to express in this syntax (e.g. 'P1M' + '-P1D').
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In these cases, the function returns an empty string ('').
27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns duration string or NULL.
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateAddDuration (const xmlChar *xstr, const xmlChar *ystr)
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr x, y, res;
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar     *ret;
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((xstr == NULL) || (ystr == NULL))
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x = exsltDateParseDuration(xstr);
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (x == NULL)
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y = exsltDateParseDuration(ystr);
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (y == NULL) {
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exsltDateFreeDate(x);
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = _exsltDateAddDuration(x, y);
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(x);
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(y);
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (res == NULL)
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateFormatDuration(&(res->value.dur));
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(res);
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateSumFunction:
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ns:      a node set of duration strings
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date:sum function adds a set of durations together.
27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The string values of the nodes in the node set passed as an argument
27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are interpreted as durations and added together as if using the
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:add-duration function. (from exslt.org)
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The return value is a string in the format defined for xs:duration
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in [3.2.6 duration] of [XML Schema Part 2: Datatypes].
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The durations can usually be added by summing the numbers given for
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * each of the components in the durations. However, if the durations
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are differently signed, then this sometimes results in durations
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that are impossible to express in this syntax (e.g. 'P1M' + '-P1D').
27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In these cases, the function returns an empty string ('').
27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns duration string or NULL.
27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateSumFunction (xmlXPathParserContextPtr ctxt, int nargs)
28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlNodeSetPtr ns;
28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *user = NULL;
28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *tmp;
28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr x, total;
28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret;
28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 1) {
28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError (ctxt);
28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* We need to delay the freeing of value->user */
28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ctxt->value != NULL) && ctxt->value->boolval != 0) {
28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	user = ctxt->value->user;
28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->value->boolval = 0;
28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ctxt->value->user = NULL;
28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ns = xmlXPathPopNodeSet (ctxt);
28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlXPathCheckError (ctxt))
28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((ns == NULL) || (ns->nodeNr == 0)) {
28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnEmptyString (ctxt);
28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ns != NULL)
28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathFreeNodeSet (ns);
28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    total = exsltDateCreateDate (XS_DURATION);
28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (total == NULL) {
28335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathFreeNodeSet (ns);
28345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
28355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < ns->nodeNr; i++) {
28385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	int result;
28395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	tmp = xmlXPathCastNodeToString (ns->nodeTab[i]);
28405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (tmp == NULL) {
28415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathFreeNodeSet (ns);
28425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate (total);
28435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
28445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
28455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	x = exsltDateParseDuration (tmp);
28475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (x == NULL) {
28485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlFree (tmp);
28495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate (total);
28505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathFreeNodeSet (ns);
28515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathReturnEmptyString (ctxt);
28525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
28535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
28545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	result = _exsltDateAddDurCalc(total, total, x);
28565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	exsltDateFreeDate (x);
28585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree (tmp);
28595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!result) {
28605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    exsltDateFreeDate (total);
28615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathFreeNodeSet (ns);
28625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathReturnEmptyString (ctxt);
28635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
28645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
28655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
28665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateFormatDuration (&(total->value.dur));
28685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate (total);
28695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathFreeNodeSet (ns);
28715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (user != NULL)
28725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFreeNodeList ((xmlNodePtr) user);
28735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
28755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnEmptyString (ctxt);
28765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
28775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString (ctxt, ret);
28785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
28795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
28815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateSeconds:
28825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @dateTime: a date/time string
28835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
28845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the EXSLT - Dates and Times seconds() function:
28855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *    number date:seconds(string?)
28865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The date:seconds function returns the number of seconds specified
28875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * by the argument string. If no argument is given, then the current
28885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * local date/time, as returned by exsltDateCurrent() is used as the
28895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * default argument. If the date/time string is a xs:duration, then the
28905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * years and months must be zero (or not present). Parsing a duration
28915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * converts the fields to seconds. If the date/time string is not a
28925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * duration (and not null), then the legal formats are:
28935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
28945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date     (CCYY-MM-DD)
28955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYearMonth (CCYY-MM)
28965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYear      (CCYY)
28975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In these cases the difference between the @dateTime and
28985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1970-01-01T00:00:00Z is calculated and converted to seconds.
28995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
29005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that there was some confusion over whether "difference" meant
29015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that a dateTime of 1970-01-01T00:00:01Z should be a positive one or
29025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a negative one.  After correspondence with exslt.org, it was determined
29035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that the intent of the specification was to have it positive.  The
29045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * coding was modified in July 2003 to reflect this.
29055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
29065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns seconds or Nan.
29075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
29085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static double
29095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateSeconds (const xmlChar *dateTime)
29105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
29115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dt;
29125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret = xmlXPathNAN;
29135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dateTime == NULL) {
29155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
29165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = exsltDateCurrent();
29175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (dt == NULL)
29185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
29195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return xmlXPathNAN;
29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dt = exsltDateParseDuration(dateTime);
29225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (dt == NULL)
29235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dt = exsltDateParse(dateTime);
29245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
29255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt == NULL)
29275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return xmlXPathNAN;
29285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((dt->type <= XS_DATETIME) && (dt->type >= XS_GYEAR)) {
29305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exsltDateValPtr y, dur;
29315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /*
29335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * compute the difference between the given (or current) date
29345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * and epoch date
29355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         */
29365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        y = exsltDateCreateDate(XS_DATETIME);
29375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (y != NULL) {
29385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            y->value.date.year = 1970;
29395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            y->value.date.mon  = 1;
29405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            y->value.date.day  = 1;
29415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            y->value.date.tz_flag = 1;
29425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dur = _exsltDateDifference(y, dt, 1);
29445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (dur != NULL) {
29455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ret = exsltDateCastDateToNumber(dur);
29465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                exsltDateFreeDate(dur);
29475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
29485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            exsltDateFreeDate(y);
29495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
29505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if ((dt->type == XS_DURATION) && (dt->value.dur.mon == 0))
29525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ret = exsltDateCastDateToNumber(dt);
29535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dt);
29555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
29575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
29585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
29595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
29605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDifference:
29615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @xstr: date/time string
29625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ystr: date/time string
29635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
29645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the date:difference (string,string) function which returns
29655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the duration between the first date and the second date. If the first
29665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date occurs before the second date, then the result is a positive
29675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * duration; if it occurs after the second date, the result is a
29685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * negative duration.  The two dates must both be right-truncated
29695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date/time strings in one of the formats defined in [XML Schema Part
29705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2: Datatypes]. The date/time with the most specific format (i.e. the
29715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * least truncation) is converted into the same format as the date with
29725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the least specific format (i.e. the most truncation). The permitted
29735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * formats are as follows, from most specific to least specific:
29745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:dateTime (CCYY-MM-DDThh:mm:ss)
29755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:date (CCYY-MM-DD)
29765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYearMonth (CCYY-MM)
29775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  - xs:gYear (CCYY)
29785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If either of the arguments is not in one of these formats,
29795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * date:difference returns the empty string ('').
29805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The difference between the date/times is returned as a string in the
29815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * format defined for xs:duration in [3.2.6 duration] of [XML Schema
29825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Part 2: Datatypes].
29835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the date/time string with the least specific format is in either
29845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:gYearMonth or xs:gYear format, then the number of days, hours,
29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * minutes and seconds in the duration string must be equal to zero.
29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (The format of the string will be PnYnM.) The number of months
29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * specified in the duration must be less than 12.
29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Otherwise, the number of years and months in the duration string
29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * must be equal to zero. (The format of the string will be
29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PnDTnHnMnS.) The number of seconds specified in the duration string
29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * must be less than 60; the number of minutes must be less than 60;
29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the number of hours must be less than 24.
29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns duration string or NULL.
29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDifference (const xmlChar *xstr, const xmlChar *ystr)
29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr x, y, dur;
30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar        *ret = NULL;
30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((xstr == NULL) || (ystr == NULL))
30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x = exsltDateParse(xstr);
30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (x == NULL)
30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y = exsltDateParse(ystr);
30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (y == NULL) {
30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        exsltDateFreeDate(x);
30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
30135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
30145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (((x->type < XS_GYEAR) || (x->type > XS_DATETIME)) ||
30165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ((y->type < XS_GYEAR) || (y->type > XS_DATETIME)))  {
30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	exsltDateFreeDate(x);
30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	exsltDateFreeDate(y);
30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dur = _exsltDateDifference(x, y, 0);
30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(x);
30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(y);
30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dur == NULL)
30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateFormatDuration(&(dur->value.dur));
30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dur);
30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDuration:
30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @number: a xmlChar string
30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Implements the The date:duration function returns a duration string
30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representing the number of seconds specified by the argument string.
30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If no argument is given, then the result of calling date:seconds
30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * without any arguments is used as a default argument.
30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The duration is returned as a string in the format defined for
30455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xs:duration in [3.2.6 duration] of [XML Schema Part 2: Datatypes].
30465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The number of years and months in the duration string must be equal
30475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to zero. (The format of the string will be PnDTnHnMnS.) The number
30485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of seconds specified in the duration string must be less than 60;
30495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the number of minutes must be less than 60; the number of hours must
30505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * be less than 24.
30515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the argument is Infinity, -Infinity or NaN, then date:duration
30525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * returns an empty string ('').
30535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
30545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns duration string or NULL.
30555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
30565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xmlChar *
30575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDuration (const xmlChar *number)
30585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
30595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateValPtr dur;
30605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double       secs;
30615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar     *ret;
30625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (number == NULL)
30645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        secs = exsltDateSeconds(number);
30655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
30665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        secs = xmlXPathCastStringToNumber(number);
30675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((xmlXPathIsNaN(secs)) || (xmlXPathIsInf(secs)))
30695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
30705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dur = exsltDateCreateDate(XS_DURATION);
30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dur == NULL)
30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dur->value.dur.sec = secs;
30765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateFormatDuration(&(dur->value.dur));
30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exsltDateFreeDate(dur);
30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/****************************************************************
30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *		Wrappers for use by the XPath engine		*
30865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *								*
30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ****************************************************************/
30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDateTimeFunction:
30925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
30935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
30945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateDateTime() for use by the XPath engine.
30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDateTimeFunction (xmlXPathParserContextPtr ctxt, int nargs)
30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret;
31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 0) {
31035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
31045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
31055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateDateTime();
31085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathReturnEmptyString(ctxt);
31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathReturnString(ctxt, ret);
31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDateFunction:
31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateDate() for use by the XPath engine.
31215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDateFunction (xmlXPathParserContextPtr ctxt, int nargs)
31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret, *dt = NULL;
31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {
31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = xmlXPathPopString(ctxt);
31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateDate(dt);
31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL) {
31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltGenericDebug(xsltGenericDebugContext,
31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 "{http://exslt.org/dates-and-times}date: "
31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 "invalid date or format %s\n", dt);
31455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnEmptyString(ctxt);
31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, ret);
31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)
31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dt);
31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateTimeFunction:
31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateTime() for use by the XPath engine.
31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
31625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateTimeFunction (xmlXPathParserContextPtr ctxt, int nargs)
31635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
31645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret, *dt = NULL;
31655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {
31675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
31685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
31695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = xmlXPathPopString(ctxt);
31725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
31735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
31745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
31755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
31765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateTime(dt);
31795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL) {
31815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xsltGenericDebug(xsltGenericDebugContext,
31825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 "{http://exslt.org/dates-and-times}time: "
31835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 "invalid date or format %s\n", dt);
31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnEmptyString(ctxt);
31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
31865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, ret);
31875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
31885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)
31905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dt);
31915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
31925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateYearFunction:
31955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
31965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
31975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
31985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateYear() for use by the XPath engine.
31995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
32005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
32015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateYearFunction (xmlXPathParserContextPtr ctxt, int nargs)
32025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
32035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *dt = NULL;
32045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret;
32055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {
32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
32095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
32125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = xmlXPathPopString(ctxt);
32135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
32145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
32155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
32165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
32175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateYear(dt);
32205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)
32225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dt);
32235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathReturnNumber(ctxt, ret);
32255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
32285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateLeapYearFunction:
32295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
32305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
32315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
32325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateLeapYear() for use by the XPath engine.
32335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
32345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
32355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateLeapYearFunction (xmlXPathParserContextPtr ctxt, int nargs)
32365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
32375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *dt = NULL;
32385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathObjectPtr ret;
32395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {
32415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
32425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
32435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
32465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = xmlXPathPopString(ctxt);
32475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
32485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
32495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
32505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
32515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
32525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateLeapYear(dt);
32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)
32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dt);
32575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    valuePush(ctxt, ret);
32595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define X_IN_Y(x, y)						\
32625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void							\
32635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDate##x##In##y##Function (xmlXPathParserContextPtr ctxt,	\
32645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      int nargs) {			\
32655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *dt = NULL;						\
32665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double ret;							\
32675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)								\
32685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {				\
32695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);				\
32705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;							\
32715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }								\
32725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)								\
32735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {						\
32745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = xmlXPathPopString(ctxt);				\
32755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {				\
32765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);				\
32775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;						\
32785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}							\
32795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }								\
32805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)								\
32815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDate##x##In##y(dt);				\
32825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)								\
32835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)						\
32845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dt);						\
32855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)								\
32865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathReturnNumber(ctxt, ret);				\
32875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
32885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
32905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateMonthInYearFunction:
32915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
32925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
32935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
32945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateMonthInYear() for use by the XPath engine.
32955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
32965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(Month,Year)
32975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
32995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateMonthNameFunction:
33005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
33015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
33025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
33035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateMonthName() for use by the XPath engine.
33045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
33055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
33065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateMonthNameFunction (xmlXPathParserContextPtr ctxt, int nargs)
33075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
33085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *dt = NULL;
33095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ret;
33105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {
33125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
33135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
33145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
33175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = xmlXPathPopString(ctxt);
33185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
33195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
33205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
33215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
33225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateMonthName(dt);
33255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)
33275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dt);
33285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
33305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnEmptyString(ctxt);
33315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
33325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, xmlStrdup(ret));
33335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
33365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateMonthAbbreviationFunction:
33375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
33385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
33395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
33405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateMonthAbbreviation() for use by the XPath engine.
33415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
33425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
33435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateMonthAbbreviationFunction (xmlXPathParserContextPtr ctxt, int nargs)
33445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
33455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *dt = NULL;
33465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ret;
33475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {
33495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
33505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
33515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
33545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = xmlXPathPopString(ctxt);
33555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
33565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
33575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
33585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
33595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
33605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateMonthAbbreviation(dt);
33625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)
33645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dt);
33655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
33675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnEmptyString(ctxt);
33685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
33695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, xmlStrdup(ret));
33705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
33715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
33735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateWeekInYearFunction:
33745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
33755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
33765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
33775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateWeekInYear() for use by the XPath engine.
33785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
33795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(Week,Year)
33805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
33825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateWeekInMonthFunction:
33835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
33845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
33855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
33865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateWeekInMonthYear() for use by the XPath engine.
33875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
33885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(Week,Month)
33895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
33915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayInYearFunction:
33925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
33935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
33945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
33955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateDayInYear() for use by the XPath engine.
33965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
33975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(Day,Year)
33985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
33995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
34005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayInMonthFunction:
34015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
34025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
34035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
34045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateDayInMonth() for use by the XPath engine.
34055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
34065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(Day,Month)
34075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
34095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayOfWeekInMonthFunction:
34105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
34115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
34125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
34135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDayOfWeekInMonth() for use by the XPath engine.
34145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
34155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(DayOfWeek,Month)
34165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
34185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayInWeekFunction:
34195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
34205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
34215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
34225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateDayInWeek() for use by the XPath engine.
34235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
34245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(Day,Week)
34255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
34275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDayNameFunction:
34285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
34295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
34305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
34315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateDayName() for use by the XPath engine.
34325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
34335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
34345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDayNameFunction (xmlXPathParserContextPtr ctxt, int nargs)
34355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
34365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *dt = NULL;
34375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ret;
34385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {
34405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
34415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
34425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
34455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = xmlXPathPopString(ctxt);
34465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
34475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
34485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
34495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
34505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateDayName(dt);
34535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)
34555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dt);
34565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
34585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnEmptyString(ctxt);
34595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
34605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, xmlStrdup(ret));
34615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
34645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateMonthDayFunction:
34655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
34665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
34675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
34685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateDayAbbreviation() for use by the XPath engine.
34695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
34705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
34715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDayAbbreviationFunction (xmlXPathParserContextPtr ctxt, int nargs)
34725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
34735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *dt = NULL;
34745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const xmlChar *ret;
34755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {
34775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
34785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
34795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
34825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dt = xmlXPathPopString(ctxt);
34835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
34845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
34855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
34865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
34875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
34885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateDayAbbreviation(dt);
34905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dt != NULL)
34925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(dt);
34935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
34955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnEmptyString(ctxt);
34965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
34975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, xmlStrdup(ret));
34985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
34995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
35025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateHourInDayFunction:
35035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
35045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
35055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
35065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateHourInDay() for use by the XPath engine.
35075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
35085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(Hour,Day)
35095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
35115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateMinuteInHourFunction:
35125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
35135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
35145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
35155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateMinuteInHour() for use by the XPath engine.
35165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
35175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(Minute,Hour)
35185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
35205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateSecondInMinuteFunction:
35215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
35225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
35235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
35245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateSecondInMinute() for use by the XPath engine.
35255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
35265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X_IN_Y(Second,Minute)
35275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
35295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateSecondsFunction:
35305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
35315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
35325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
35335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateSeconds() for use by the XPath engine.
35345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
35355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
35365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateSecondsFunction (xmlXPathParserContextPtr ctxt, int nargs)
35375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
35385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *str = NULL;
35395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double   ret;
35405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs > 1) {
35425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
35435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
35445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
35475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	str = xmlXPathPopString(ctxt);
35485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
35495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
35505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
35515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
35525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateSeconds(str);
35555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (str != NULL)
35565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(str);
35575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlXPathReturnNumber(ctxt, ret);
35595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
35625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateAddFunction:
35635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  an XPath parser context
35645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
35655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
35665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateAdd() for use by the XPath processor.
35675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
35685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
35695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateAddFunction (xmlXPathParserContextPtr ctxt, int nargs)
35705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
35715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret, *xstr, *ystr;
35725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 2) {
35745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
35755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
35765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ystr = xmlXPathPopString(ctxt);
35785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlXPathCheckError(ctxt))
35795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
35805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xstr = xmlXPathPopString(ctxt);
35825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlXPathCheckError(ctxt)) {
35835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlFree(ystr);
35845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
35855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
35865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateAdd(xstr, ystr);
35885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(ystr);
35905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(xstr);
35915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
35935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathReturnEmptyString(ctxt);
35945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
35955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, ret);
35965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
35975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
35995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateAddDurationFunction:
36005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  an XPath parser context
36015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
36025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
36035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateAddDuration() for use by the XPath processor.
36045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
36055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
36065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateAddDurationFunction (xmlXPathParserContextPtr ctxt, int nargs)
36075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
36085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret, *xstr, *ystr;
36095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 2) {
36115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
36125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
36135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ystr = xmlXPathPopString(ctxt);
36155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlXPathCheckError(ctxt))
36165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
36175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xstr = xmlXPathPopString(ctxt);
36195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlXPathCheckError(ctxt)) {
36205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlFree(ystr);
36215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
36225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateAddDuration(xstr, ystr);
36255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(ystr);
36275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(xstr);
36285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
36305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathReturnEmptyString(ctxt);
36315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
36325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, ret);
36335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
36365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDifferenceFunction:
36375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt:  an XPath parser context
36385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs:  the number of arguments
36395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
36405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateDifference() for use by the XPath processor.
36415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
36425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
36435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDifferenceFunction (xmlXPathParserContextPtr ctxt, int nargs)
36445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
36455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret, *xstr, *ystr;
36465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs != 2) {
36485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
36495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
36505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ystr = xmlXPathPopString(ctxt);
36525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlXPathCheckError(ctxt))
36535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
36545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xstr = xmlXPathPopString(ctxt);
36565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xmlXPathCheckError(ctxt)) {
36575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlFree(ystr);
36585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
36595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateDifference(xstr, ystr);
36625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(ystr);
36645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlFree(xstr);
36655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
36675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmlXPathReturnEmptyString(ctxt);
36685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
36695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, ret);
36705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
36715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
36735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateDurationFunction:
36745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: an XPath parser context
36755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @nargs : the number of arguments
36765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
36775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wraps exsltDateDuration() for use by the XPath engine
36785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
36795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
36805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateDurationFunction (xmlXPathParserContextPtr ctxt, int nargs)
36815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
36825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *ret;
36835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmlChar *number = NULL;
36845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((nargs < 0) || (nargs > 1)) {
36865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathSetArityError(ctxt);
36875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
36885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nargs == 1) {
36915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	number = xmlXPathPopString(ctxt);
36925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (xmlXPathCheckError(ctxt)) {
36935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xmlXPathSetTypeError(ctxt);
36945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
36955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
36965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
36975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = exsltDateDuration(number);
36995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (number != NULL)
37015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlFree(number);
37025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret == NULL)
37045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnEmptyString(ctxt);
37055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
37065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	xmlXPathReturnString(ctxt, ret);
37075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
37085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
37105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateRegister:
37115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
37125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Registers the EXSLT - Dates and Times module
37135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
37145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
37155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateRegister (void)
37165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
37175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "add",
37185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateAddFunction);
37205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "add-duration",
37215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateAddDurationFunction);
37235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "date",
37245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDateFunction);
37265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
37275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "date-time",
37285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDateTimeFunction);
37305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
37315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "day-abbreviation",
37325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDayAbbreviationFunction);
37345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "day-in-month",
37355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDayInMonthFunction);
37375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "day-in-week",
37385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDayInWeekFunction);
37405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "day-in-year",
37415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDayInYearFunction);
37435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "day-name",
37445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDayNameFunction);
37465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "day-of-week-in-month",
37475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDayOfWeekInMonthFunction);
37495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "difference",
37505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDifferenceFunction);
37525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "duration",
37535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateDurationFunction);
37555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "hour-in-day",
37565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateHourInDayFunction);
37585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "leap-year",
37595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateLeapYearFunction);
37615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "minute-in-hour",
37625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateMinuteInHourFunction);
37645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "month-abbreviation",
37655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateMonthAbbreviationFunction);
37675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "month-in-year",
37685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateMonthInYearFunction);
37705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "month-name",
37715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateMonthNameFunction);
37735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "second-in-minute",
37745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateSecondInMinuteFunction);
37765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "seconds",
37775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateSecondsFunction);
37795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "sum",
37805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateSumFunction);
37825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "time",
37835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateTimeFunction);
37855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "week-in-month",
37865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateWeekInMonthFunction);
37885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "week-in-year",
37895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateWeekInYearFunction);
37915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xsltRegisterExtModuleFunction ((const xmlChar *) "year",
37925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   (const xmlChar *) EXSLT_DATE_NAMESPACE,
37935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   exsltDateYearFunction);
37945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
37955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
37975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exsltDateXpathCtxtRegister:
37985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
37995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Registers the EXSLT - Dates and Times module for use outside XSLT
38005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
38015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int
38025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exsltDateXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix)
38035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
38045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ctxt
38055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && prefix
38065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterNs(ctxt,
38075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               prefix,
38085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               (const xmlChar *) EXSLT_DATE_NAMESPACE)
38095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "add",
38115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateAddFunction)
38135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "add-duration",
38155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateAddDurationFunction)
38175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "date",
38195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDateFunction)
38215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_TIME
38225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "date-time",
38245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDateTimeFunction)
38265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
38275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "day-abbreviation",
38295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDayAbbreviationFunction)
38315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "day-in-month",
38335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDayInMonthFunction)
38355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "day-in-week",
38375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDayInWeekFunction)
38395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "day-in-year",
38415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDayInYearFunction)
38435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "day-name",
38455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDayNameFunction)
38475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "day-of-week-in-month",
38495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDayOfWeekInMonthFunction)
38515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "difference",
38535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDifferenceFunction)
38555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "duration",
38575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateDurationFunction)
38595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "hour-in-day",
38615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateHourInDayFunction)
38635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "leap-year",
38655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateLeapYearFunction)
38675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "minute-in-hour",
38695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateMinuteInHourFunction)
38715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "month-abbreviation",
38735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateMonthAbbreviationFunction)
38755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "month-in-year",
38775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateMonthInYearFunction)
38795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "month-name",
38815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateMonthNameFunction)
38835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "second-in-minute",
38855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateSecondInMinuteFunction)
38875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "seconds",
38895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateSecondsFunction)
38915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "sum",
38935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateSumFunction)
38955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
38965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "time",
38975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
38985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateTimeFunction)
38995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
39005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "week-in-month",
39015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
39025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateWeekInMonthFunction)
39035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
39045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "week-in-year",
39055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
39065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateWeekInYearFunction)
39075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && !xmlXPathRegisterFuncNS(ctxt,
39085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) "year",
39095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   (const xmlChar *) EXSLT_DATE_NAMESPACE,
39105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   exsltDateYearFunction)) {
39115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0;
39125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
39135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
39145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915