2 * date.c: Implementation of the EXSLT -- Dates and Times module
5 * http://www.exslt.org/date/date.html
7 * See Copyright for the status of this software.
10 * Charlie Bozeman <cbozeman@HiWAAY.net>
11 * Thomas Broyer <tbroyer@ltgt.net>
15 * implement "other" date/time extension functions
18 #include "libexslt/libexslt.h"
23 #if defined(WIN32) && !defined (__CYGWIN__)
24 #include <win32config.h>
29 #include <libxml/tree.h>
30 #include <libxml/xpath.h>
31 #include <libxml/xpathInternals.h>
33 #include <libxslt/xsltconfig.h>
34 #include <libxslt/xsltutils.h>
35 #include <libxslt/xsltInternals.h>
36 #include <libxslt/extensions.h>
45 #define DEBUG_EXSLT_DATE
48 /* types of date and/or time (from schema datatypes) */
62 typedef struct _exsltDate exsltDate;
63 typedef exsltDate *exsltDatePtr;
67 unsigned int mon :4; /* 1 <= mon <= 12 */
68 unsigned int day :5; /* 1 <= day <= 31 */
69 unsigned int hour :5; /* 0 <= hour <= 23 */
70 unsigned int min :6; /* 0 <= min <= 59 */
72 int tz_flag :1; /* is tzo explicitely set? */
73 int tzo :11; /* -1440 <= tzo <= 1440 */
76 /****************************************************************
78 * Compat./Port. macros *
80 ****************************************************************/
82 #if defined(HAVE_TIME_H) && defined(HAVE_LOCALTIME) \
83 && defined(HAVE_TIME) && defined(HAVE_GMTIME) \
84 && defined(HAVE_MKTIME)
88 /****************************************************************
90 * Convenience macros and functions *
92 ****************************************************************/
94 #define IS_TZO_CHAR(c) \
95 ((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
97 #define VALID_YEAR(yr) (yr != 0)
98 #define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12))
99 /* VALID_DAY should only be used when month is unknown */
100 #define VALID_DAY(day) ((day >= 1) && (day <= 31))
101 #define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23))
102 #define VALID_MIN(min) ((min >= 0) && (min <= 59))
103 #define VALID_SEC(sec) ((sec >= 0) && (sec < 60))
104 #define VALID_TZO(tzo) ((tzo > -1440) && (tzo < 1440))
106 (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
108 static const int daysInMonth[12] =
109 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
110 static const int daysInMonthLeap[12] =
111 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
113 #define VALID_MDAY(dt) \
114 (IS_LEAP(dt->year) ? \
115 (dt->day <= daysInMonthLeap[dt->mon - 1]) : \
116 (dt->day <= daysInMonth[dt->mon - 1]))
118 #define VALID_DATE(dt) \
119 (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
121 #define VALID_TIME(dt) \
122 (VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \
123 VALID_SEC(dt->sec) && VALID_TZO(dt->tzo))
125 #define VALID_DATETIME(dt) \
126 (VALID_DATE(dt) && VALID_TIME(dt))
129 static const int dayInYearByMonth[12] =
130 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
131 static const int dayInLeapYearByMonth[12] =
132 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
134 #define DAY_IN_YEAR(day, month, year) \
136 dayInLeapYearByMonth[month - 1] : \
137 dayInYearByMonth[month - 1]) + day)
140 * _exsltDateParseGYear:
141 * @dt: pointer to a date structure
142 * @str: pointer to the string to analyze
144 * Parses a xs:gYear without time zone and fills in the appropriate
145 * field of the @dt structure. @str is updated to point just after the
146 * xs:gYear. It is supposed that @dt->year is big enough to contain
149 * Returns 0 or the error code
152 _exsltDateParseGYear (exsltDatePtr dt, const xmlChar **str) {
153 const xmlChar *cur = *str, *firstChar;
154 int isneg = 0, digcnt = 0;
156 if (((*cur < '0') || (*cur > '9')) &&
157 (*cur != '-') && (*cur != '+'))
167 while ((*cur >= '0') && (*cur <= '9')) {
168 dt->year = dt->year * 10 + (*cur - '0');
173 /* year must be at least 4 digits (CCYY); over 4
174 * digits cannot have a leading zero. */
175 if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
179 dt->year = - dt->year;
181 if (!VALID_YEAR(dt->year))
186 #ifdef DEBUG_EXSLT_DATE
187 xsltGenericDebug(xsltGenericDebugContext,
188 "Parsed year %04i\n", dt->year);
196 * @dt: the #exsltDate to format
197 * @cur: a pointer to an allocated buffer
199 * Formats @dt in xsl:gYear format. Result is appended to @cur and
200 * @cur is updated to point after the xsl:gYear.
202 #define FORMAT_GYEAR(dt, cur) \
203 if (dt->year < 0) { \
208 int year = (dt->year < 0) ? - dt->year : dt->year; \
209 xmlChar tmp_buf[100], *tmp = tmp_buf; \
210 /* virtually adds leading zeros */ \
211 while (year < 1000) \
213 /* result is in reverse-order */ \
215 *tmp = '0' + (year % 10); \
219 /* restore the correct order */ \
220 while (tmp > tmp_buf) { \
229 * @num: the integer to fill in
230 * @cur: an #xmlChar *
231 * @invalid: an integer
233 * Parses a 2-digits integer and updates @num with the value. @cur is
234 * updated to point just after the integer.
235 * In case of error, @invalid is set to %TRUE, values of @num and
236 * @cur are undefined.
238 #define PARSE_2_DIGITS(num, cur, invalid) \
239 if ((cur[0] < '0') || (cur[0] > '9') || \
240 (cur[1] < '0') || (cur[1] > '9')) \
243 num = (cur[0] - '0') * 10 + (cur[1] - '0'); \
248 * @num: the integer to format
249 * @cur: a pointer to an allocated buffer
251 * Formats a 2-digits integer. Result is appended to @cur and
252 * @cur is updated to point after the integer.
254 #define FORMAT_2_DIGITS(num, cur) \
255 *cur = '0' + ((num / 10) % 10); \
257 *cur = '0' + (num % 10); \
262 * @num: the double to fill in
263 * @cur: an #xmlChar *
264 * @invalid: an integer
266 * Parses a float and updates @num with the value. @cur is
267 * updated to point just after the float. The float must have a
268 * 2-digits integer part and may or may not have a decimal part.
269 * In case of error, @invalid is set to %TRUE, values of @num and
270 * @cur are undefined.
272 #define PARSE_FLOAT(num, cur, invalid) \
273 PARSE_2_DIGITS(num, cur, invalid); \
274 if (!invalid && (*cur == '.')) { \
277 if ((*cur < '0') || (*cur > '9')) \
279 while ((*cur >= '0') && (*cur <= '9')) { \
281 num += (*cur - '0') * mult; \
288 * @num: the double to format
289 * @cur: a pointer to an allocated buffer
291 * Formats a float. Result is appended to @cur and @cur is updated to
292 * point after the integer. The float representation has a 2-digits
293 * integer part and may or may not have a decimal part.
295 #define FORMAT_FLOAT(num, cur) \
297 xmlChar *sav, *str; \
300 str = xmlXPathCastNumberToString(num); \
308 * _exsltDateParseGMonth:
309 * @dt: pointer to a date structure
310 * @str: pointer to the string to analyze
312 * Parses a xs:gMonth without time zone and fills in the appropriate
313 * field of the @dt structure. @str is updated to point just after the
316 * Returns 0 or the error code
319 _exsltDateParseGMonth (exsltDatePtr dt, const xmlChar **str) {
320 const xmlChar *cur = *str;
323 PARSE_2_DIGITS(dt->mon, cur, ret);
327 if (!VALID_MONTH(dt->mon))
332 #ifdef DEBUG_EXSLT_DATE
333 xsltGenericDebug(xsltGenericDebugContext,
334 "Parsed month %02i\n", dt->mon);
342 * @dt: the #exsltDate to format
343 * @cur: a pointer to an allocated buffer
345 * Formats @dt in xsl:gMonth format. Result is appended to @cur and
346 * @cur is updated to point after the xsl:gMonth.
348 #define FORMAT_GMONTH(dt, cur) \
349 FORMAT_2_DIGITS(dt->mon, cur)
352 * _exsltDateParseGDay:
353 * @dt: pointer to a date structure
354 * @str: pointer to the string to analyze
356 * Parses a xs:gDay without time zone and fills in the appropriate
357 * field of the @dt structure. @str is updated to point just after the
360 * Returns 0 or the error code
363 _exsltDateParseGDay (exsltDatePtr dt, const xmlChar **str) {
364 const xmlChar *cur = *str;
367 PARSE_2_DIGITS(dt->day, cur, ret);
371 if (!VALID_DAY(dt->day))
376 #ifdef DEBUG_EXSLT_DATE
377 xsltGenericDebug(xsltGenericDebugContext,
378 "Parsed day %02i\n", dt->day);
386 * @dt: the #exsltDate to format
387 * @cur: a pointer to an allocated buffer
389 * Formats @dt in xsl:gDay format. Result is appended to @cur and
390 * @cur is updated to point after the xsl:gDay.
392 #define FORMAT_GDAY(dt, cur) \
393 FORMAT_2_DIGITS(dt->day, cur)
397 * @dt: the #exsltDate to format
398 * @cur: a pointer to an allocated buffer
400 * Formats @dt in xsl:date format. Result is appended to @cur and
401 * @cur is updated to point after the xsl:date.
403 #define FORMAT_DATE(dt, cur) \
404 FORMAT_GYEAR(dt, cur); \
407 FORMAT_GMONTH(dt, cur); \
410 FORMAT_GDAY(dt, cur);
413 * _exsltDateParseTime:
414 * @dt: pointer to a date structure
415 * @str: pointer to the string to analyze
417 * Parses a xs:time without time zone and fills in the appropriate
418 * fields of the @dt structure. @str is updated to point just after the
420 * In case of error, values of @dt fields are undefined.
422 * Returns 0 or the error code
425 _exsltDateParseTime (exsltDatePtr dt, const xmlChar **str) {
426 const xmlChar *cur = *str;
429 PARSE_2_DIGITS(dt->hour, cur, ret);
437 PARSE_2_DIGITS(dt->min, cur, ret);
445 PARSE_FLOAT(dt->sec, cur, ret);
454 #ifdef DEBUG_EXSLT_DATE
455 xsltGenericDebug(xsltGenericDebugContext,
456 "Parsed time %02i:%02i:%02.f\n",
457 dt->hour, dt->min, dt->sec);
465 * @dt: the #exsltDate to format
466 * @cur: a pointer to an allocated buffer
468 * Formats @dt in xsl:time format. Result is appended to @cur and
469 * @cur is updated to point after the xsl:time.
471 #define FORMAT_TIME(dt, cur) \
472 FORMAT_2_DIGITS(dt->hour, cur); \
475 FORMAT_2_DIGITS(dt->min, cur); \
478 FORMAT_FLOAT(dt->sec, cur);
481 * _exsltDateParseTimeZone:
482 * @dt: pointer to a date structure
483 * @str: pointer to the string to analyze
485 * Parses a time zone without time zone and fills in the appropriate
486 * field of the @dt structure. @str is updated to point just after the
489 * Returns 0 or the error code
492 _exsltDateParseTimeZone (exsltDatePtr dt, const xmlChar **str) {
493 const xmlChar *cur = *str;
515 int isneg = 0, tmp = 0;
516 isneg = (*cur == '-');
520 PARSE_2_DIGITS(tmp, cur, ret);
523 if (!VALID_HOUR(tmp))
532 PARSE_2_DIGITS(tmp, cur, ret);
542 if (!VALID_TZO(dt->tzo))
553 #ifdef DEBUG_EXSLT_DATE
554 xsltGenericDebug(xsltGenericDebugContext,
555 "Parsed time zone offset (%s) %i\n",
556 dt->tz_flag ? "explicit" : "implicit", dt->tzo);
564 * @dt: the #exsltDate to format
565 * @cur: a pointer to an allocated buffer
567 * Formats @dt timezone. Result is appended to @cur and
568 * @cur is updated to point after the timezone.
570 #define FORMAT_TZ(dt, cur) \
571 if (dt->tzo == 0) { \
575 int aTzo = (dt->tzo < 0) ? - dt->tzo : dt->tzo; \
576 int tzHh = aTzo / 60, tzMm = aTzo % 60; \
577 *cur = (dt->tzo < 0) ? '-' : '+' ; \
579 FORMAT_2_DIGITS(tzHh, cur); \
582 FORMAT_2_DIGITS(tzMm, cur); \
585 /****************************************************************
587 * XML Schema Dates/Times Datatypes Handling *
589 ****************************************************************/
592 * exsltDateCreateDate:
594 * Creates a new #exsltDate, uninitialized.
596 * Returns the #exsltDate
599 exsltDateCreateDate (void) {
602 ret = (exsltDatePtr) xmlMalloc(sizeof(exsltDate));
604 xsltGenericError(xsltGenericErrorContext,
605 "exsltDateCreateDate: out of memory\n");
608 memset (ret, 0, sizeof(exsltDate));
615 * @date: an #exsltDatePtr
620 exsltDateFreeDate (exsltDatePtr date) {
631 * Returns the current date and time.
634 exsltDateCurrent (void) {
635 struct tm *localTm, *gmTm;
639 ret = exsltDateCreateDate();
643 /* get current time */
645 localTm = localtime(&secs);
647 ret->type = XS_DATETIME;
649 /* get real year, not years since 1900 */
650 ret->year = localTm->tm_year + 1900;
652 ret->mon = localTm->tm_mon + 1;
653 ret->day = localTm->tm_mday;
654 ret->hour = localTm->tm_hour;
655 ret->min = localTm->tm_min;
657 /* floating point seconds */
658 ret->sec = (double) localTm->tm_sec;
660 /* determine the time zone offset from local to gm time */
661 gmTm = gmtime(&secs);
663 ret->tzo = (((ret->day * 1440) + (ret->hour * 60) + ret->min) -
664 ((gmTm->tm_mday * 1440) + (gmTm->tm_hour * 60) +
673 * @dateTime: string to analyse
675 * Parses a date/time string
677 * Returns a newly built #exsltDatePtr of NULL in case of error
680 exsltDateParse (const xmlChar *dateTime) {
683 const xmlChar *cur = dateTime;
685 #define RETURN_TYPE_IF_VALID(t) \
686 if (IS_TZO_CHAR(*cur)) { \
687 ret = _exsltDateParseTimeZone(dt, &cur); \
696 if (dateTime == NULL)
699 if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
702 dt = exsltDateCreateDate();
706 if ((cur[0] == '-') && (cur[1] == '-')) {
708 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
713 /* is it an xs:gDay? */
716 ret = _exsltDateParseGDay(dt, &cur);
720 RETURN_TYPE_IF_VALID(XS_GDAY);
726 * it should be an xs:gMonthDay or xs:gMonth
728 ret = _exsltDateParseGMonth(dt, &cur);
736 /* is it an xs:gMonth? */
739 RETURN_TYPE_IF_VALID(XS_GMONTH);
743 /* it should be an xs:gMonthDay */
744 ret = _exsltDateParseGDay(dt, &cur);
748 RETURN_TYPE_IF_VALID(XS_GMONTHDAY);
754 * It's a right-truncated date or an xs:time.
755 * Try to parse an xs:time then fallback on right-truncated dates.
757 if ((*cur >= '0') && (*cur <= '9')) {
758 ret = _exsltDateParseTime(dt, &cur);
760 /* it's an xs:time */
761 RETURN_TYPE_IF_VALID(XS_TIME);
765 /* fallback on date parsing */
768 ret = _exsltDateParseGYear(dt, &cur);
772 /* is it an xs:gYear? */
773 RETURN_TYPE_IF_VALID(XS_GYEAR);
779 ret = _exsltDateParseGMonth(dt, &cur);
783 /* is it an xs:gYearMonth? */
784 RETURN_TYPE_IF_VALID(XS_GYEARMONTH);
790 ret = _exsltDateParseGDay(dt, &cur);
791 if ((ret != 0) || !VALID_DATE(dt))
794 /* is it an xs:date? */
795 RETURN_TYPE_IF_VALID(XS_DATE);
801 /* it should be an xs:dateTime */
802 ret = _exsltDateParseTime(dt, &cur);
806 ret = _exsltDateParseTimeZone(dt, &cur);
807 if ((ret != 0) || (*cur != 0) || !VALID_DATETIME(dt))
810 dt->type = XS_DATETIME;
816 exsltDateFreeDate(dt);
821 * exsltDateFormatDateTime:
824 * Formats @dt in xs:dateTime format.
826 * Returns a newly allocated string, or NULL in case of error
829 exsltDateFormatDateTime (const exsltDatePtr dt) {
830 xmlChar buf[100], *cur = buf;
832 if ((dt == NULL) || !VALID_DATETIME(dt))
835 FORMAT_DATE(dt, cur);
838 FORMAT_TIME(dt, cur);
842 return xmlStrdup(buf);
846 * exsltDateFormatDate:
849 * Formats @dt in xs:date format.
851 * Returns a newly allocated string, or NULL in case of error
854 exsltDateFormatDate (const exsltDatePtr dt) {
855 xmlChar buf[100], *cur = buf;
857 if ((dt == NULL) || !VALID_DATETIME(dt))
860 FORMAT_DATE(dt, cur);
861 if (dt->tz_flag || (dt->tzo != 0)) {
866 return xmlStrdup(buf);
870 * exsltDateFormatTime:
873 * Formats @dt in xs:time format.
875 * Returns a newly allocated string, or NULL in case of error
878 exsltDateFormatTime (const exsltDatePtr dt) {
879 xmlChar buf[100], *cur = buf;
881 if ((dt == NULL) || !VALID_TIME(dt))
884 FORMAT_TIME(dt, cur);
885 if (dt->tz_flag || (dt->tzo != 0)) {
890 return xmlStrdup(buf);
893 /****************************************************************
895 * EXSLT - Dates and Times functions *
897 ****************************************************************/
902 * Implements the EXSLT - Dates and Times date-time() function:
903 * string date:date-time()
905 * Returns the current date and time as a date/time string.
908 exsltDateDateTime (void) {
913 cur = exsltDateCurrent();
915 ret = exsltDateFormatDateTime(cur);
916 exsltDateFreeDate(cur);
925 * @dateTime: a date/time string
927 * Implements the EXSLT - Dates and Times date() function:
928 * string date:date (string?)
930 * Returns the date specified in the date/time string given as the
931 * argument. If no argument is given, then the current local
932 * date/time, as returned by date:date-time is used as a default
934 * The date/time string specified as an argument must be a string in
935 * the format defined as the lexical representation of either
936 * xs:dateTime or xs:date. If the argument is not in either of these
937 * formats, returns NULL.
940 exsltDateDate (const xmlChar *dateTime) {
941 exsltDatePtr dt = NULL;
944 if (dateTime == NULL) {
946 dt = exsltDateCurrent();
951 dt = exsltDateParse(dateTime);
954 if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
955 exsltDateFreeDate(dt);
960 ret = exsltDateFormatDate(dt);
961 exsltDateFreeDate(dt);
968 * @dateTime: a date/time string
970 * Implements the EXSLT - Dates and Times time() function:
971 * string date:time (string?)
973 * Returns the time specified in the date/time string given as the
974 * argument. If no argument is given, then the current local
975 * date/time, as returned by date:date-time is used as a default
977 * The date/time string specified as an argument must be a string in
978 * the format defined as the lexical representation of either
979 * xs:dateTime or xs:time. If the argument is not in either of these
980 * formats, returns NULL.
983 exsltDateTime (const xmlChar *dateTime) {
984 exsltDatePtr dt = NULL;
987 if (dateTime == NULL) {
989 dt = exsltDateCurrent();
994 dt = exsltDateParse(dateTime);
997 if ((dt->type != XS_DATETIME) && (dt->type != XS_TIME)) {
998 exsltDateFreeDate(dt);
1003 ret = exsltDateFormatTime(dt);
1004 exsltDateFreeDate(dt);
1011 * @dateTime: a date/time string
1013 * Implements the EXSLT - Dates and Times year() function
1014 * number date:year (string?)
1015 * Returns the year of a date as a number. If no argument is given,
1016 * then the current local date/time, as returned by date:date-time is
1017 * used as a default argument.
1018 * The date/time string specified as the first argument must be a
1019 * right-truncated string in the format defined as the lexical
1020 * representation of xs:dateTime in one of the formats defined in [XML
1021 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1022 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1023 * - xs:date (CCYY-MM-DD)
1024 * - xs:gYearMonth (CCYY-MM)
1026 * If the date/time string is not in one of these formats, then NaN is
1030 exsltDateYear (const xmlChar *dateTime) {
1034 if (dateTime == NULL) {
1036 dt = exsltDateCurrent();
1041 dt = exsltDateParse(dateTime);
1044 if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE) &&
1045 (dt->type != XS_GYEARMONTH) && (dt->type != XS_GYEAR)) {
1046 exsltDateFreeDate(dt);
1051 ret = (double) dt->year;
1052 exsltDateFreeDate(dt);
1058 * exsltDateLeapYear:
1059 * @dateTime: a date/time string
1061 * Implements the EXSLT - Dates and Times leap-year() function:
1062 * boolean date:leap-yea (string?)
1063 * Returns true if the year given in a date is a leap year. If no
1064 * argument is given, then the current local date/time, as returned by
1065 * date:date-time is used as a default argument.
1066 * The date/time string specified as the first argument must be a
1067 * right-truncated string in the format defined as the lexical
1068 * representation of xs:dateTime in one of the formats defined in [XML
1069 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1070 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1071 * - xs:date (CCYY-MM-DD)
1072 * - xs:gYearMonth (CCYY-MM)
1074 * If the date/time string is not in one of these formats, then NaN is
1077 static xmlXPathObjectPtr
1078 exsltDateLeapYear (const xmlChar *dateTime) {
1082 year = exsltDateYear(dateTime);
1083 if (xmlXPathIsNaN(year))
1084 return xmlXPathNewFloat(xmlXPathNAN);
1088 return xmlXPathNewBoolean(1);
1090 return xmlXPathNewBoolean(0);
1094 * exsltDateMonthInYear:
1095 * @dateTime: a date/time string
1097 * Implements the EXSLT - Dates and Times month-in-year() function:
1098 * number date:month-in-year (string?)
1099 * Returns the month of a date as a number. If no argument is given,
1100 * then the current local date/time, as returned by date:date-time is
1101 * used the default argument.
1102 * The date/time string specified as the argument is a left or
1103 * right-truncated string in the format defined as the lexical
1104 * representation of xs:dateTime in one of the formats defined in [XML
1105 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1106 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1107 * - xs:date (CCYY-MM-DD)
1108 * - xs:gYearMonth (CCYY-MM)
1109 * - xs:gMonth (--MM--)
1110 * - xs:gMonthDay (--MM-DD)
1111 * If the date/time string is not in one of these formats, then NaN is
1115 exsltDateMonthInYear (const xmlChar *dateTime) {
1119 if (dateTime == NULL) {
1121 dt = exsltDateCurrent();
1126 dt = exsltDateParse(dateTime);
1129 if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE) &&
1130 (dt->type != XS_GYEARMONTH) && (dt->type != XS_GMONTH) &&
1131 (dt->type != XS_GMONTHDAY)) {
1132 exsltDateFreeDate(dt);
1137 ret = (double) dt->mon;
1138 exsltDateFreeDate(dt);
1144 * exsltDateMonthName:
1145 * @dateTime: a date/time string
1147 * Implements the EXSLT - Dates and Time month-name() function
1148 * string date:month-name (string?)
1149 * Returns the full name of the month of a date. If no argument is
1150 * given, then the current local date/time, as returned by
1151 * date:date-time is used the default argument.
1152 * The date/time string specified as the argument is a left or
1153 * right-truncated string in the format defined as the lexical
1154 * representation of xs:dateTime in one of the formats defined in [XML
1155 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1156 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1157 * - xs:date (CCYY-MM-DD)
1158 * - xs:gYearMonth (CCYY-MM)
1159 * - xs:gMonth (--MM--)
1160 * If the date/time string is not in one of these formats, then an
1161 * empty string ('') is returned.
1162 * The result is an English month name: one of 'January', 'February',
1163 * 'March', 'April', 'May', 'June', 'July', 'August', 'September',
1164 * 'October', 'November' or 'December'.
1166 static const xmlChar *
1167 exsltDateMonthName (const xmlChar *dateTime) {
1168 static const xmlChar monthNames[13][10] = {
1170 { 'J', 'a', 'n', 'u', 'a', 'r', 'y', 0 },
1171 { 'F', 'e', 'b', 'r', 'u', 'a', 'r', 'y', 0 },
1172 { 'M', 'a', 'r', 'c', 'h', 0 },
1173 { 'A', 'p', 'r', 'i', 'l', 0 },
1174 { 'M', 'a', 'y', 0 },
1175 { 'J', 'u', 'n', 'e', 0 },
1176 { 'J', 'u', 'l', 'y', 0 },
1177 { 'A', 'u', 'g', 'u', 's', 't', 0 },
1178 { 'S', 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', 0 },
1179 { 'O', 'c', 't', 'o', 'b', 'e', 'r', 0 },
1180 { 'N', 'o', 'v', 'e', 'm', 'b', 'e', 'r', 0 },
1181 { 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 0 }
1184 month = exsltDateMonthInYear(dateTime);
1185 if (!VALID_MONTH(month))
1187 return monthNames[month];
1191 * exsltDateMonthAbbreviation:
1192 * @dateTime: a date/time string
1194 * Implements the EXSLT - Dates and Time month-abbreviation() function
1195 * string date:month-abbreviation (string?)
1196 * Returns the abbreviation of the month of a date. If no argument is
1197 * given, then the current local date/time, as returned by
1198 * date:date-time is used the default argument.
1199 * The date/time string specified as the argument is a left or
1200 * right-truncated string in the format defined as the lexical
1201 * representation of xs:dateTime in one of the formats defined in [XML
1202 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1203 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1204 * - xs:date (CCYY-MM-DD)
1205 * - xs:gYearMonth (CCYY-MM)
1206 * - xs:gMonth (--MM--)
1207 * If the date/time string is not in one of these formats, then an
1208 * empty string ('') is returned.
1209 * The result is an English month abbreviation: one of 'Jan', 'Feb',
1210 * 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov' or
1213 static const xmlChar *
1214 exsltDateMonthAbbreviation (const xmlChar *dateTime) {
1215 static const xmlChar monthAbbreviations[13][4] = {
1217 { 'J', 'a', 'n', 0 },
1218 { 'F', 'e', 'b', 0 },
1219 { 'M', 'a', 'r', 0 },
1220 { 'A', 'p', 'r', 0 },
1221 { 'M', 'a', 'y', 0 },
1222 { 'J', 'u', 'n', 0 },
1223 { 'J', 'u', 'l', 0 },
1224 { 'A', 'u', 'g', 0 },
1225 { 'S', 'e', 'p', 0 },
1226 { 'O', 'c', 't', 0 },
1227 { 'N', 'o', 'v', 0 },
1228 { 'D', 'e', 'c', 0 }
1231 month = exsltDateMonthInYear(dateTime);
1232 if(!VALID_MONTH(month))
1234 return monthAbbreviations[month];
1239 * @yday: year day (1-366)
1242 * Determine the day-in-week from @yday and @yr. 0001-01-01 was
1243 * a Monday so all other days are calculated from there. Take the
1244 * number of years since (or before) add the number of leap years and
1245 * the day-in-year and mod by 7. This is a function because negative
1246 * years must be handled a little differently and there is no zero year.
1248 * Returns day in week (Sunday = 0)
1251 _exsltDateDayInWeek(int yday, long yr)
1256 ret = ((yr + (((yr+1)/4)-((yr+1)/100)+((yr+1)/400)) + yday) % 7);
1260 ret = (((yr-1) + (((yr-1)/4)-((yr-1)/100)+((yr-1)/400)) + yday) % 7);
1266 * exsltDateWeekInYear:
1267 * @dateTime: a date/time string
1269 * Implements the EXSLT - Dates and Times week-in-year() function
1270 * number date:week-in-year (string?)
1271 * Returns the week of the year as a number. If no argument is given,
1272 * then the current local date/time, as returned by date:date-time is
1273 * used as the default argument. For the purposes of numbering,
1274 * counting follows ISO 8601: week 1 in a year is the week containing
1275 * the first Thursday of the year, with new weeks beginning on a
1277 * The date/time string specified as the argument is a right-truncated
1278 * string in the format defined as the lexical representation of
1279 * xs:dateTime in one of the formats defined in [XML Schema Part 2:
1280 * Datatypes]. The permitted formats are as follows:
1281 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1282 * - xs:date (CCYY-MM-DD)
1283 * If the date/time string is not in one of these formats, then NaN is
1287 exsltDateWeekInYear (const xmlChar *dateTime) {
1289 int fdiy, fdiw, ret;
1291 if (dateTime == NULL) {
1293 dt = exsltDateCurrent();
1298 dt = exsltDateParse(dateTime);
1301 if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
1302 exsltDateFreeDate(dt);
1307 fdiy = DAY_IN_YEAR(1, 1, dt->year);
1310 * Determine day-in-week (0=Sun, 1=Mon, etc.) then adjust so Monday
1311 * is the first day-in-week
1313 fdiw = (_exsltDateDayInWeek(fdiy, dt->year) + 6) % 7;
1315 ret = DAY_IN_YEAR(dt->day, dt->mon, dt->year) / 7;
1317 /* ISO 8601 adjustment, 3 is Thu */
1321 exsltDateFreeDate(dt);
1323 return (double) ret;
1327 * exsltDateWeekInMonth:
1328 * @dateTime: a date/time string
1330 * Implements the EXSLT - Dates and Times week-in-month() function
1331 * number date:week-in-month (string?)
1332 * The date:week-in-month function returns the week in a month of a
1333 * date as a number. If no argument is given, then the current local
1334 * date/time, as returned by date:date-time is used the default
1335 * argument. For the purposes of numbering, the first day of the month
1336 * is in week 1 and new weeks begin on a Monday (so the first and last
1337 * weeks in a month will often have less than 7 days in them).
1338 * The date/time string specified as the argument is a right-truncated
1339 * string in the format defined as the lexical representation of
1340 * xs:dateTime in one of the formats defined in [XML Schema Part 2:
1341 * Datatypes]. The permitted formats are as follows:
1342 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1343 * - xs:date (CCYY-MM-DD)
1344 * If the date/time string is not in one of these formats, then NaN is
1348 exsltDateWeekInMonth (const xmlChar *dateTime) {
1350 int fdiy, fdiw, ret;
1352 if (dateTime == NULL) {
1354 dt = exsltDateCurrent();
1359 dt = exsltDateParse(dateTime);
1362 if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
1363 exsltDateFreeDate(dt);
1368 fdiy = DAY_IN_YEAR(1, dt->mon, dt->year);
1370 * Determine day-in-week (0=Sun, 1=Mon, etc.) then adjust so Monday
1371 * is the first day-in-week
1373 fdiw = (_exsltDateDayInWeek(fdiy, dt->year) + 6) % 7;
1375 ret = ((dt->day + fdiw) / 7) + 1;
1377 exsltDateFreeDate(dt);
1379 return (double) ret;
1383 * exsltDateDayInYear:
1384 * @dateTime: a date/time string
1386 * Implements the EXSLT - Dates and Times day-in-year() function
1387 * number date:day-in-year (string?)
1388 * Returns the day of a date in a year as a number. If no argument is
1389 * given, then the current local date/time, as returned by
1390 * date:date-time is used the default argument.
1391 * The date/time string specified as the argument is a right-truncated
1392 * string in the format defined as the lexical representation of
1393 * xs:dateTime in one of the formats defined in [XML Schema Part 2:
1394 * Datatypes]. The permitted formats are as follows:
1395 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1396 * - xs:date (CCYY-MM-DD)
1397 * If the date/time string is not in one of these formats, then NaN is
1401 exsltDateDayInYear (const xmlChar *dateTime) {
1405 if (dateTime == NULL) {
1407 dt = exsltDateCurrent();
1412 dt = exsltDateParse(dateTime);
1415 if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
1416 exsltDateFreeDate(dt);
1421 ret = DAY_IN_YEAR(dt->day, dt->mon, dt->year);
1423 exsltDateFreeDate(dt);
1425 return (double) ret;
1429 * exsltDateDayInMonth:
1430 * @dateTime: a date/time string
1432 * Implements the EXSLT - Dates and Times day-in-month() function:
1433 * number date:day-in-month (string?)
1434 * Returns the day of a date as a number. If no argument is given,
1435 * then the current local date/time, as returned by date:date-time is
1436 * used the default argument.
1437 * The date/time string specified as the argument is a left or
1438 * right-truncated string in the format defined as the lexical
1439 * representation of xs:dateTime in one of the formats defined in [XML
1440 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1441 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1442 * - xs:date (CCYY-MM-DD)
1443 * - xs:gMonthDay (--MM-DD)
1445 * If the date/time string is not in one of these formats, then NaN is
1449 exsltDateDayInMonth (const xmlChar *dateTime) {
1453 if (dateTime == NULL) {
1455 dt = exsltDateCurrent();
1460 dt = exsltDateParse(dateTime);
1463 if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE) &&
1464 (dt->type != XS_GMONTHDAY) && (dt->type != XS_GDAY)) {
1465 exsltDateFreeDate(dt);
1470 ret = (double) dt->day;
1471 exsltDateFreeDate(dt);
1477 * exsltDateDayOfWeekInMonth:
1478 * @dateTime: a date/time string
1480 * Implements the EXSLT - Dates and Times day-of-week-in-month()
1482 * number date:day-of-week-in-month (string?)
1483 * Returns the day-of-the-week in a month of a date as a number
1484 * (e.g. 3 for the 3rd Tuesday in May). If no argument is
1485 * given, then the current local date/time, as returned by
1486 * date:date-time is used the default argument.
1487 * The date/time string specified as the argument is a right-truncated
1488 * string in the format defined as the lexical representation of
1489 * xs:dateTime in one of the formats defined in [XML Schema Part 2:
1490 * Datatypes]. The permitted formats are as follows:
1491 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1492 * - xs:date (CCYY-MM-DD)
1493 * If the date/time string is not in one of these formats, then NaN is
1497 exsltDateDayOfWeekInMonth (const xmlChar *dateTime) {
1501 if (dateTime == NULL) {
1503 dt = exsltDateCurrent();
1508 dt = exsltDateParse(dateTime);
1511 if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
1512 exsltDateFreeDate(dt);
1517 ret = (dt->day / 7) + 1;
1519 exsltDateFreeDate(dt);
1521 return (double) ret;
1525 * exsltDateDayInWeek:
1526 * @dateTime: a date/time string
1528 * Implements the EXSLT - Dates and Times day-in-week() function:
1529 * number date:day-in-week (string?)
1530 * Returns the day of the week given in a date as a number. If no
1531 * argument is given, then the current local date/time, as returned by
1532 * date:date-time is used the default argument.
1533 * The date/time string specified as the argument is a left or
1534 * right-truncated string in the format defined as the lexical
1535 * representation of xs:dateTime in one of the formats defined in [XML
1536 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1537 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1538 * - xs:date (CCYY-MM-DD)
1539 * If the date/time string is not in one of these formats, then NaN is
1541 * The numbering of days of the week starts at 1 for Sunday, 2 for
1542 * Monday and so on up to 7 for Saturday.
1545 exsltDateDayInWeek (const xmlChar *dateTime) {
1550 if (dateTime == NULL) {
1552 dt = exsltDateCurrent();
1557 dt = exsltDateParse(dateTime);
1560 if ((dt->type != XS_DATETIME) && (dt->type != XS_DATE)) {
1561 exsltDateFreeDate(dt);
1566 diy = DAY_IN_YEAR(dt->day, dt->mon, dt->year);
1568 ret = (double) _exsltDateDayInWeek(diy, dt->year) + 1;
1570 exsltDateFreeDate(dt);
1577 * @dateTime: a date/time string
1579 * Implements the EXSLT - Dates and Time day-name() function
1580 * string date:day-name (string?)
1581 * Returns the full name of the day of the week of a date. If no
1582 * argument is given, then the current local date/time, as returned by
1583 * date:date-time is used the default argument.
1584 * The date/time string specified as the argument is a left or
1585 * right-truncated string in the format defined as the lexical
1586 * representation of xs:dateTime in one of the formats defined in [XML
1587 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1588 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1589 * - xs:date (CCYY-MM-DD)
1590 * If the date/time string is not in one of these formats, then an
1591 * empty string ('') is returned.
1592 * The result is an English day name: one of 'Sunday', 'Monday',
1593 * 'Tuesday', 'Wednesday', 'Thursday' or 'Friday'.
1595 static const xmlChar *
1596 exsltDateDayName (const xmlChar *dateTime) {
1597 static const xmlChar dayNames[8][10] = {
1599 { 'S', 'u', 'n', 'd', 'a', 'y', 0 },
1600 { 'M', 'o', 'n', 'd', 'a', 'y', 0 },
1601 { 'T', 'u', 'e', 's', 'd', 'a', 'y', 0 },
1602 { 'W', 'e', 'd', 'n', 'e', 's', 'd', 'a', 'y', 0 },
1603 { 'T', 'h', 'u', 'r', 's', 'd', 'a', 'y', 0 },
1604 { 'F', 'r', 'i', 'd', 'a', 'y', 0 },
1605 { 'S', 'a', 't', 'u', 'r', 'd', 'a', 'y', 0 }
1608 day = exsltDateDayInWeek(dateTime);
1609 if((day < 1) || (day > 7))
1611 return dayNames[day];
1615 * exsltDateDayAbbreviation:
1616 * @dateTime: a date/time string
1618 * Implements the EXSLT - Dates and Time day-abbreviation() function
1619 * string date:day-abbreviation (string?)
1620 * Returns the abbreviation of the day of the week of a date. If no
1621 * argument is given, then the current local date/time, as returned by
1622 * date:date-time is used the default argument.
1623 * The date/time string specified as the argument is a left or
1624 * right-truncated string in the format defined as the lexical
1625 * representation of xs:dateTime in one of the formats defined in [XML
1626 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1627 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1628 * - xs:date (CCYY-MM-DD)
1629 * If the date/time string is not in one of these formats, then an
1630 * empty string ('') is returned.
1631 * The result is a three-letter English day abbreviation: one of
1632 * 'Sun', 'Mon', 'Tue', 'Wed', 'Thu' or 'Fri'.
1634 static const xmlChar *
1635 exsltDateDayAbbreviation (const xmlChar *dateTime) {
1636 static const xmlChar dayAbbreviations[8][4] = {
1638 { 'S', 'u', 'n', 0 },
1639 { 'M', 'o', 'n', 0 },
1640 { 'T', 'u', 'e', 0 },
1641 { 'W', 'e', 'd', 0 },
1642 { 'T', 'h', 'u', 0 },
1643 { 'F', 'r', 'i', 0 },
1644 { 'S', 'a', 't', 0 }
1647 day = exsltDateDayInWeek(dateTime);
1648 if((day < 1) || (day > 7))
1650 return dayAbbreviations[day];
1654 * exsltDateHourInDay:
1655 * @dateTime: a date/time string
1657 * Implements the EXSLT - Dates and Times day-in-month() function:
1658 * number date:day-in-month (string?)
1659 * Returns the hour of the day as a number. If no argument is given,
1660 * then the current local date/time, as returned by date:date-time is
1661 * used the default argument.
1662 * The date/time string specified as the argument is a left or
1663 * right-truncated string in the format defined as the lexical
1664 * representation of xs:dateTime in one of the formats defined in [XML
1665 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1666 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1667 * - xs:time (hh:mm:ss)
1668 * If the date/time string is not in one of these formats, then NaN is
1672 exsltDateHourInDay (const xmlChar *dateTime) {
1676 if (dateTime == NULL) {
1678 dt = exsltDateCurrent();
1683 dt = exsltDateParse(dateTime);
1686 if ((dt->type != XS_DATETIME) && (dt->type != XS_TIME)) {
1687 exsltDateFreeDate(dt);
1692 ret = (double) dt->hour;
1693 exsltDateFreeDate(dt);
1699 * exsltDateMinuteInHour:
1700 * @dateTime: a date/time string
1702 * Implements the EXSLT - Dates and Times day-in-month() function:
1703 * number date:day-in-month (string?)
1704 * Returns the minute of the hour as a number. If no argument is
1705 * given, then the current local date/time, as returned by
1706 * date:date-time is used the default argument.
1707 * The date/time string specified as the argument is a left or
1708 * right-truncated string in the format defined as the lexical
1709 * representation of xs:dateTime in one of the formats defined in [XML
1710 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1711 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1712 * - xs:time (hh:mm:ss)
1713 * If the date/time string is not in one of these formats, then NaN is
1717 exsltDateMinuteInHour (const xmlChar *dateTime) {
1721 if (dateTime == NULL) {
1723 dt = exsltDateCurrent();
1728 dt = exsltDateParse(dateTime);
1731 if ((dt->type != XS_DATETIME) && (dt->type != XS_TIME)) {
1732 exsltDateFreeDate(dt);
1737 ret = (double) dt->min;
1738 exsltDateFreeDate(dt);
1744 * exsltDateSecondInMinute:
1745 * @dateTime: a date/time string
1747 * Implements the EXSLT - Dates and Times second-in-minute() function:
1748 * number date:day-in-month (string?)
1749 * Returns the second of the minute as a number. If no argument is
1750 * given, then the current local date/time, as returned by
1751 * date:date-time is used the default argument.
1752 * The date/time string specified as the argument is a left or
1753 * right-truncated string in the format defined as the lexical
1754 * representation of xs:dateTime in one of the formats defined in [XML
1755 * Schema Part 2: Datatypes]. The permitted formats are as follows:
1756 * - xs:dateTime (CCYY-MM-DDThh:mm:ss)
1757 * - xs:time (hh:mm:ss)
1758 * If the date/time string is not in one of these formats, then NaN is
1762 exsltDateSecondInMinute (const xmlChar *dateTime) {
1766 if (dateTime == NULL) {
1768 dt = exsltDateCurrent();
1773 dt = exsltDateParse(dateTime);
1776 if ((dt->type != XS_DATETIME) && (dt->type != XS_TIME)) {
1777 exsltDateFreeDate(dt);
1783 exsltDateFreeDate(dt);
1789 /****************************************************************
1791 * Wrappers for use by the XPath engine *
1793 ****************************************************************/
1797 * exsltDateDateTimeFunction:
1798 * @ctxt: an XPath parser context
1799 * @nargs : the number of arguments
1801 * Wraps #exsltDateDateTime for use by the XPath engine
1804 exsltDateDateTimeFunction (xmlXPathParserContextPtr ctxt, int nargs) {
1808 xmlXPathSetArityError(ctxt);
1812 ret = exsltDateDateTime();
1813 xmlXPathReturnString(ctxt, ret);
1818 * exsltDateDateFunction:
1819 * @ctxt: an XPath parser context
1820 * @nargs : the number of arguments
1822 * Wraps #exsltDateDate for use by the XPath engine
1825 exsltDateDateFunction (xmlXPathParserContextPtr ctxt, int nargs) {
1826 xmlChar *ret, *dt = NULL;
1828 if ((nargs < 0) || (nargs > 1)) {
1829 xmlXPathSetArityError(ctxt);
1833 dt = xmlXPathPopString(ctxt);
1834 if (xmlXPathCheckError(ctxt)) {
1835 xmlXPathSetTypeError(ctxt);
1840 ret = exsltDateDate(dt);
1843 xsltGenericDebug(xsltGenericDebugContext,
1844 "{http://exslt.org/dates-and-times}date: "
1845 "invalid date or format %s\n", dt);
1846 xmlXPathReturnEmptyString(ctxt);
1848 xmlXPathReturnString(ctxt, ret);
1856 * exsltDateTimeFunction:
1857 * @ctxt: an XPath parser context
1858 * @nargs : the number of arguments
1860 * Wraps #exsltDateTime for use by the XPath engine
1863 exsltDateTimeFunction (xmlXPathParserContextPtr ctxt, int nargs) {
1864 xmlChar *ret, *dt = NULL;
1866 if ((nargs < 0) || (nargs > 1)) {
1867 xmlXPathSetArityError(ctxt);
1871 dt = xmlXPathPopString(ctxt);
1872 if (xmlXPathCheckError(ctxt)) {
1873 xmlXPathSetTypeError(ctxt);
1878 ret = exsltDateTime(dt);
1881 xsltGenericDebug(xsltGenericDebugContext,
1882 "{http://exslt.org/dates-and-times}time: "
1883 "invalid date or format %s\n", dt);
1884 xmlXPathReturnEmptyString(ctxt);
1886 xmlXPathReturnString(ctxt, ret);
1894 * exsltDateYearFunction:
1895 * @ctxt: an XPath parser context
1896 * @nargs : the number of arguments
1898 * Wraps #exsltDateYear for use by the XPath engine
1901 exsltDateYearFunction (xmlXPathParserContextPtr ctxt, int nargs) {
1905 if ((nargs < 0) || (nargs > 1)) {
1906 xmlXPathSetArityError(ctxt);
1911 dt = xmlXPathPopString(ctxt);
1912 if (xmlXPathCheckError(ctxt)) {
1913 xmlXPathSetTypeError(ctxt);
1918 ret = exsltDateYear(dt);
1923 xmlXPathReturnNumber(ctxt, ret);
1927 * exsltDateLeapYearFunction:
1928 * @ctxt: an XPath parser context
1929 * @nargs : the number of arguments
1931 * Wraps #exsltDateLeapYear for use by the XPath engine
1934 exsltDateLeapYearFunction (xmlXPathParserContextPtr ctxt,
1937 xmlXPathObjectPtr ret;
1939 if ((nargs < 0) || (nargs > 1)) {
1940 xmlXPathSetArityError(ctxt);
1945 dt = xmlXPathPopString(ctxt);
1946 if (xmlXPathCheckError(ctxt)) {
1947 xmlXPathSetTypeError(ctxt);
1952 ret = exsltDateLeapYear(dt);
1957 valuePush(ctxt, ret);
1960 #define X_IN_Y(x, y) \
1962 exsltDate##x##In##y##Function (xmlXPathParserContextPtr ctxt, \
1964 xmlChar *dt = NULL; \
1967 if ((nargs < 0) || (nargs > 1)) { \
1968 xmlXPathSetArityError(ctxt); \
1973 dt = xmlXPathPopString(ctxt); \
1974 if (xmlXPathCheckError(ctxt)) { \
1975 xmlXPathSetTypeError(ctxt); \
1980 ret = exsltDate##x##In##y(dt); \
1985 xmlXPathReturnNumber(ctxt, ret); \
1989 * exsltDateMonthInYearFunction:
1990 * @ctxt: an XPath parser context
1991 * @nargs : the number of arguments
1993 * Wraps #exsltDateMonthInYear for use by the XPath engine
1998 * exsltDateMonthNameFunction:
1999 * @ctxt: an XPath parser context
2000 * @nargs : the number of arguments
2002 * Wraps #exsltDateMonthName for use by the XPath engine
2005 exsltDateMonthNameFunction (xmlXPathParserContextPtr ctxt,
2010 if ((nargs < 0) || (nargs > 1)) {
2011 xmlXPathSetArityError(ctxt);
2016 dt = xmlXPathPopString(ctxt);
2017 if (xmlXPathCheckError(ctxt)) {
2018 xmlXPathSetTypeError(ctxt);
2023 ret = exsltDateMonthName(dt);
2029 xmlXPathReturnEmptyString(ctxt);
2031 xmlXPathReturnString(ctxt, xmlStrdup(ret));
2035 * exsltDateMonthAbbreviationFunction:
2036 * @ctxt: an XPath parser context
2037 * @nargs : the number of arguments
2039 * Wraps #exsltDateMonthAbbreviation for use by the XPath engine
2042 exsltDateMonthAbbreviationFunction (xmlXPathParserContextPtr ctxt,
2047 if ((nargs < 0) || (nargs > 1)) {
2048 xmlXPathSetArityError(ctxt);
2053 dt = xmlXPathPopString(ctxt);
2054 if (xmlXPathCheckError(ctxt)) {
2055 xmlXPathSetTypeError(ctxt);
2060 ret = exsltDateMonthAbbreviation(dt);
2066 xmlXPathReturnEmptyString(ctxt);
2068 xmlXPathReturnString(ctxt, xmlStrdup(ret));
2072 * exsltDateWeekInYearFunction:
2073 * @ctxt: an XPath parser context
2074 * @nargs : the number of arguments
2076 * Wraps #exsltDateWeekInYear for use by the XPath engine
2081 * exsltDateWeekInMonthFunction:
2082 * @ctxt: an XPath parser context
2083 * @nargs : the number of arguments
2085 * Wraps #exsltDateWeekInMonthYear for use by the XPath engine
2090 * exsltDateDayInYearFunction:
2091 * @ctxt: an XPath parser context
2092 * @nargs : the number of arguments
2094 * Wraps #exsltDateDayInYear for use by the XPath engine
2099 * exsltDateDayInMonthFunction:
2100 * @ctxt: an XPath parser context
2101 * @nargs : the number of arguments
2103 * Wraps #exsltDateDayInMonth for use by the XPath engine
2108 * exsltDateDayOfWeekInMonthFunction:
2109 * @ctxt: an XPath parser context
2110 * @nargs : the number of arguments
2112 * Wraps #exsltDayOfWeekInMonth for use by the XPath engine
2114 X_IN_Y(DayOfWeek,Month)
2117 * exsltDateDayInWeekFunction:
2118 * @ctxt: an XPath parser context
2119 * @nargs : the number of arguments
2121 * Wraps #exsltDateDayInWeek for use by the XPath engine
2126 * exsltDateDayNameFunction:
2127 * @ctxt: an XPath parser context
2128 * @nargs : the number of arguments
2130 * Wraps #exsltDateDayName for use by the XPath engine
2133 exsltDateDayNameFunction (xmlXPathParserContextPtr ctxt,
2138 if ((nargs < 0) || (nargs > 1)) {
2139 xmlXPathSetArityError(ctxt);
2144 dt = xmlXPathPopString(ctxt);
2145 if (xmlXPathCheckError(ctxt)) {
2146 xmlXPathSetTypeError(ctxt);
2151 ret = exsltDateDayName(dt);
2157 xmlXPathReturnEmptyString(ctxt);
2159 xmlXPathReturnString(ctxt, xmlStrdup(ret));
2163 * exsltDateMonthDayFunction:
2164 * @ctxt: an XPath parser context
2165 * @nargs : the number of arguments
2167 * Wraps #exsltDateDayAbbreviation for use by the XPath engine
2170 exsltDateDayAbbreviationFunction (xmlXPathParserContextPtr ctxt,
2175 if ((nargs < 0) || (nargs > 1)) {
2176 xmlXPathSetArityError(ctxt);
2181 dt = xmlXPathPopString(ctxt);
2182 if (xmlXPathCheckError(ctxt)) {
2183 xmlXPathSetTypeError(ctxt);
2188 ret = exsltDateDayAbbreviation(dt);
2194 xmlXPathReturnEmptyString(ctxt);
2196 xmlXPathReturnString(ctxt, xmlStrdup(ret));
2201 * exsltDateHourInDayFunction:
2202 * @ctxt: an XPath parser context
2203 * @nargs : the number of arguments
2205 * Wraps #exsltDateHourInDay for use by the XPath engine
2210 * exsltDateMinuteInHourFunction:
2211 * @ctxt: an XPath parser context
2212 * @nargs : the number of arguments
2214 * Wraps #exsltDateMinuteInHour for use by the XPath engine
2219 * exsltDateSecondInMinuteFunction:
2220 * @ctxt: an XPath parser context
2221 * @nargs : the number of arguments
2223 * Wraps #exsltDateSecondInMinute for use by the XPath engine
2225 X_IN_Y(Second,Minute)
2228 * exsltDateRegister:
2230 * Registers the EXSLT - Dates and Times module
2233 exsltDateRegister(void)
2236 xsltRegisterExtModuleFunction((const xmlChar *) "date-time",
2237 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2238 exsltDateDateTimeFunction);
2240 xsltRegisterExtModuleFunction((const xmlChar *) "date",
2241 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2242 exsltDateDateFunction);
2243 xsltRegisterExtModuleFunction((const xmlChar *) "time",
2244 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2245 exsltDateTimeFunction);
2246 xsltRegisterExtModuleFunction((const xmlChar *) "year",
2247 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2248 exsltDateYearFunction);
2249 xsltRegisterExtModuleFunction((const xmlChar *) "leap-year",
2250 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2251 exsltDateLeapYearFunction);
2252 xsltRegisterExtModuleFunction((const xmlChar *) "month-in-year",
2253 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2254 exsltDateMonthInYearFunction);
2255 xsltRegisterExtModuleFunction((const xmlChar *) "month-name",
2256 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2257 exsltDateMonthNameFunction);
2258 xsltRegisterExtModuleFunction((const xmlChar *) "month-abbreviation",
2259 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2260 exsltDateMonthAbbreviationFunction);
2261 xsltRegisterExtModuleFunction((const xmlChar *) "week-in-year",
2262 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2263 exsltDateWeekInYearFunction);
2264 xsltRegisterExtModuleFunction((const xmlChar *) "week-in-month",
2265 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2266 exsltDateWeekInMonthFunction);
2267 xsltRegisterExtModuleFunction((const xmlChar *) "day-in-year",
2268 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2269 exsltDateDayInYearFunction);
2270 xsltRegisterExtModuleFunction((const xmlChar *) "day-in-month",
2271 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2272 exsltDateDayInMonthFunction);
2273 xsltRegisterExtModuleFunction((const xmlChar *) "day-of-week-in-month",
2274 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2275 exsltDateDayOfWeekInMonthFunction);
2276 xsltRegisterExtModuleFunction((const xmlChar *) "day-in-week",
2277 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2278 exsltDateDayInWeekFunction);
2279 xsltRegisterExtModuleFunction((const xmlChar *) "day-name",
2280 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2281 exsltDateDayNameFunction);
2282 xsltRegisterExtModuleFunction((const xmlChar *) "day-abbreviation",
2283 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2284 exsltDateDayAbbreviationFunction);
2285 xsltRegisterExtModuleFunction((const xmlChar *) "hour-in-day",
2286 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2287 exsltDateHourInDayFunction);
2288 xsltRegisterExtModuleFunction((const xmlChar *) "minute-in-hour",
2289 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2290 exsltDateMinuteInHourFunction);
2291 xsltRegisterExtModuleFunction((const xmlChar *) "second-in-minute",
2292 (const xmlChar *) EXSLT_DATE_NAMESPACE,
2293 exsltDateSecondInMinuteFunction);