/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, Lotus
 * Development Corporation., http://www.lotus.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

package org.apache.xalan.lib;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.apache.xpath.objects.XBoolean;
import org.apache.xpath.objects.XNumber;
import org.apache.xpath.objects.XObject;

/**
 * This class contains EXSLT dates and times extension functions.
 * It is accessed by specifying a namespace URI as follows:
 * <pre>
 *    xmlns:datetime="http://exslt.org/dates-and-times"
 * </pre>
 * 
 * The documentation for each function has been copied from the relevant
 * EXSLT Implementer page.
 * 
 * @see <a href="http://www.exslt.org/">EXSLT</a>
 * @xsl.usage general
 */

public class ExsltDatetime
{
    // Datetime formats (era and zone handled separately).
    static final String dt = "yyyy-MM-dd'T'HH:mm:ss";
    static final String d = "yyyy-MM-dd";
    static final String gym = "yyyy-MM";
    static final String gy = "yyyy";
    static final String gmd = "--MM-dd";
    static final String gm = "--MM--";
    static final String gd = "---dd";
    static final String t = "HH:mm:ss";
    static final String EMPTY_STR = "";

    /**
     * The date:date-time function returns the current date and time as a date/time string. 
     * The date/time string that's returned must be a string in the format defined as the 
     * lexical representation of xs:dateTime in 
     * <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">[3.2.7 dateTime]</a> of
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
     * The date/time format is basically CCYY-MM-DDThh:mm:ss, although implementers should consult
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and 
     * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
     * The date/time string format must include a time zone, either a Z to indicate Coordinated 
     * Universal Time or a + or - followed by the difference between the difference from UTC 
     * represented as hh:mm. 
     */
    public static String dateTime()
    {
      Calendar cal = Calendar.getInstance();
      Date datetime = cal.getTime();
      // Format for date and time.
      SimpleDateFormat dateFormat = new SimpleDateFormat(dt);
      
      StringBuffer buff = new StringBuffer(dateFormat.format(datetime));
      // Must also include offset from UTF.
      // Get the offset (in milliseconds).
      int offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
      // If there is no offset, we have "Coordinated
      // Universal Time."
      if (offset == 0)
        buff.append("Z");
      else
      {
        // Convert milliseconds to hours and minutes
        int hrs = offset/(60*60*1000);
        // In a few cases, the time zone may be +/-hh:30.
        int min = offset%(60*60*1000);
        char posneg = hrs < 0? '-': '+';
        buff.append(posneg + formatDigits(hrs) + ':' + formatDigits(min));
      }
      return buff.toString();
    }
    
    /**
     * Represent the hours and minutes with two-digit strings.
     * @param q hrs or minutes.
     * @return two-digit String representation of hrs or minutes.
     */
    private static String formatDigits(int q)
    {
      String dd = String.valueOf(Math.abs(q));
      return dd.length() == 1 ? '0' + dd : dd;
    }

    /**
     * The date:date function returns the date specified in the date/time string given 
     * as the argument. If no argument is given, then the current local date/time, as 
     * returned by date:date-time is used as a default argument. 
     * The date/time string that's returned must be a string in the format defined as the 
     * lexical representation of xs:dateTime in 
     * <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">[3.2.7 dateTime]</a> of
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
     * If the argument is not in either of these formats, date:date returns an empty string (''). 
     * The date/time format is basically CCYY-MM-DDThh:mm:ss, although implementers should consult 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and 
     * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details. 
     * The date is returned as a string with a lexical representation as defined for xs:date in 
     * [3.2.9 date] of [XML Schema Part 2: Datatypes]. The date format is basically CCYY-MM-DD, 
     * although implementers should consult [XML Schema Part 2: Datatypes] and [ISO 8601] for details.
     * If no argument is given or the argument date/time specifies a time zone, then the date string 
     * format must include a time zone, either a Z to indicate Coordinated Universal Time or a + or - 
     * followed by the difference between the difference from UTC represented as hh:mm. If an argument 
     * is specified and it does not specify a time zone, then the date string format must not include 
     * a time zone. 
     */
    public static String date(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String leader = edz[0];
      String datetime = edz[1];
      String zone = edz[2];
      if (datetime == null || zone == null) 
        return EMPTY_STR;
                    
      String[] formatsIn = {dt, d};
      String formatOut = d;
      Date date = testFormats(datetime, formatsIn);
      if (date == null) return EMPTY_STR;
      
      SimpleDateFormat dateFormat = new SimpleDateFormat(formatOut);
      dateFormat.setLenient(false);
      String dateOut = dateFormat.format(date);      
      if (dateOut.length() == 0)
          return EMPTY_STR;
      else        
        return (leader + dateOut + zone);
    }
    
    
    /**
     * See above.
     */
    public static String date()
    {
      String datetime = dateTime().toString();
      String date = datetime.substring(0, datetime.indexOf("T"));
      String zone = datetime.substring(getZoneStart(datetime));
      return (date + zone);
    }
    
    /**
     * The date:time function returns the time specified in the date/time string given 
     * as the argument. If no argument is given, then the current local date/time, as 
     * returned by date:date-time is used as a default argument. 
     * The date/time string that's returned must be a string in the format defined as the 
     * lexical representation of xs:dateTime in 
     * <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">[3.2.7 dateTime]</a> of
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * If the argument string is not in this format, date:time returns an empty string (''). 
     * The date/time format is basically CCYY-MM-DDThh:mm:ss, although implementers should consult 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a> and 
     * <a href="http://www.iso.ch/markete/8601.pdf">[ISO 8601]</a> for details.
     * The date is returned as a string with a lexical representation as defined for xs:time in 
     * <a href="http://www.w3.org/TR/xmlschema-2/#time">[3.2.8 time]</a> of [XML Schema Part 2: Datatypes].
     * The time format is basically hh:mm:ss, although implementers should consult [XML Schema Part 2: 
     * Datatypes] and [ISO 8601] for details. 
     * If no argument is given or the argument date/time specifies a time zone, then the time string 
     * format must include a time zone, either a Z to indicate Coordinated Universal Time or a + or - 
     * followed by the difference between the difference from UTC represented as hh:mm. If an argument 
     * is specified and it does not specify a time zone, then the time string format must not include 
     * a time zone. 
     */
    public static String time(String timeIn)
      throws ParseException      
    {
      String[] edz = getEraDatetimeZone(timeIn);
      String time = edz[1];
      String zone = edz[2];
      if (time == null || zone == null) 
        return EMPTY_STR;
                    
      String[] formatsIn = {dt, d};
      String formatOut =  t;
      Date date = testFormats(time, formatsIn);
      if (date == null) return EMPTY_STR;
      SimpleDateFormat dateFormat = new SimpleDateFormat(formatOut);
      String out = dateFormat.format(date);
      return (out + zone);
    }

    /**
     * See above.
     */
    public static String time()
    {
      String datetime = dateTime().toString();
      String time = datetime.substring(datetime.indexOf("T")+1);
      String zone = datetime.substring(getZoneStart(datetime));      
      return (time + zone);
    } 
       
    /**
     * The date:year function returns the year of a date as a number. If no 
     * argument is given, then the current local date/time, as returned by 
     * date:date-time is used as a default argument.
     * The date/time string specified as the first argument must be a right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime in one 
     * of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
     * The permitted formats are as follows: 
     *   xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *   xs:date (CCYY-MM-DD) 
     *   xs:gYearMonth (CCYY-MM) 
     *   xs:gYear (CCYY) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static double year(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      boolean ad = edz[0].length() == 0; // AD (Common Era -- empty leader)
      String datetime = edz[1];
      if (datetime == null) 
        return Double.NaN;
      
      String[] formats = {dt, d, gym, gy};
      double yr = getNumber(datetime, formats, Calendar.YEAR);
      if (ad || yr == Double.NaN)
        return yr;
      else
        return -yr;
    }
     
    /**
     * See above.
     */
    public static double year()
    {
      Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.YEAR);
    }
    
    /**
     * The date:year function returns the month of a date as a number. If no argument 
     * is given, then the current local date/time, as returned by date:date-time is used 
     * as a default argument. 
     * The date/time string specified as the first argument is a left or right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime in one of 
     * the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>.
     * The permitted formats are as follows: 
     *    xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *    xs:date (CCYY-MM-DD) 
     *    xs:gYearMonth (CCYY-MM)
     *    xs:gMonth (--MM--) 
     *    xs:gMonthDay (--MM-DD)
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static double monthInYear(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null)
        return Double.NaN;      
      
      String[] formats = {dt, d, gym, gm, gmd};
      return getNumber(datetime, formats, Calendar.MONTH);
    }
    
    /**
     * See above.
     */
    public static double monthInYear()
    {      
      Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.MONTH);
   }
    
    /**
     * The date:week-in-year function returns the week of the year as a number. If no argument 
     * is given, then the current local date/time, as returned by date:date-time is used as the 
     * default argument. For the purposes of numbering, counting follows ISO 8601: week 1 in a year 
     * is the week containing the first Thursday of the year, with new weeks beginning on a Monday. 
     * The date/time string specified as the argument is a right-truncated string in the format 
     * defined as the lexical representation of xs:dateTime in one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. The 
     * permitted formats are as follows: 
     *    xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *    xs:date (CCYY-MM-DD) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static double weekInYear(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return Double.NaN;      
      
      String[] formats = {dt, d};
      return getNumber(datetime, formats, Calendar.WEEK_OF_YEAR);
    }
        
    /**
     * See above.
     */
    public static double weekInYear()
    {
       Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.WEEK_OF_YEAR);
   }

    /**
     * The date:day-in-year function returns the day of a date in a year 
     * as a number. If no argument is given, then the current local
     * date/time, as returned by date:date-time is used the default argument.
     * The date/time string specified as the argument is a right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime
     * in one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows:
     *     xs:dateTime (CCYY-MM-DDThh:mm:ss)
     *     xs:date (CCYY-MM-DD) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static double dayInYear(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return Double.NaN;            
      
      String[] formats = {dt, d};
      return getNumber(datetime, formats, Calendar.DAY_OF_YEAR);
    }
    
    /**
     * See above.
     */
    public static double dayInYear()
    {
       Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.DAY_OF_YEAR);
   }
    

    /**
     * The date:day-in-month function returns the day of a date as a number. 
     * If no argument is given, then the current local date/time, as returned 
     * by date:date-time is used the default argument. 
     * The date/time string specified as the argument is a left or right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime 
     * in one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *      xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *      xs:date (CCYY-MM-DD) 
     *      xs:gMonthDay (--MM-DD) 
     *      xs:gDay (---DD) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static double dayInMonth(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      String[] formats = {dt, d, gmd, gd};
      double day = getNumber(datetime, formats, Calendar.DAY_OF_MONTH);
      return day;
    }
    
    /**
     * See above.
     */
    public static double dayInMonth()
    {
      Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.DAY_OF_MONTH);
   }
    
    /**
     * The date:day-of-week-in-month function returns the day-of-the-week 
     * in a month of a date as a number (e.g. 3 for the 3rd Tuesday in May). 
     * If no argument is given, then the current local date/time, as returned 
     * by date:date-time is used the default argument. 
     * The date/time string specified as the argument is a right-truncated string
     * in the format defined as the lexical representation of xs:dateTime in one 
     * of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *      xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *      xs:date (CCYY-MM-DD) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static double dayOfWeekInMonth(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return Double.NaN;            

      String[] formats =  {dt, d};
      return getNumber(datetime, formats, Calendar.DAY_OF_WEEK_IN_MONTH);
    }
    
    /**
     * See above.
     */
    public static double dayOfWeekInMonth()
    {
       Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.DAY_OF_WEEK_IN_MONTH);
   }
      
    
    /**
     * The date:day-in-week function returns the day of the week given in a 
     * date as a number. If no argument is given, then the current local date/time, 
     * as returned by date:date-time is used the default argument. 
     * The date/time string specified as the argument is a right-truncated string 
     * in the format defined as the lexical representation of xs:dateTime in one 
     * of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *      xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *      xs:date (CCYY-MM-DD) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
                            The numbering of days of the week starts at 1 for Sunday, 2 for Monday and so on up to 7 for Saturday.  
     */
    public static double dayInWeek(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return Double.NaN;            

      String[] formats = {dt, d};
      return getNumber(datetime, formats, Calendar.DAY_OF_WEEK);
    }
    
    /**
     * See above.
     */
    public static double dayInWeek()
    {
       Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.DAY_OF_WEEK);
   }        

    /**
     * The date:hour-in-day function returns the hour of the day as a number. 
     * If no argument is given, then the current local date/time, as returned 
     * by date:date-time is used the default argument. 
     * The date/time string specified as the argument is a right-truncated 
     * string  in the format defined as the lexical representation of xs:dateTime
     * in one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *     xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *     xs:time (hh:mm:ss) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static double hourInDay(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return Double.NaN;            
      
      String[] formats = {dt, t};
      return getNumber(datetime, formats, Calendar.HOUR_OF_DAY);
    }
    
    /**
     * See above.
     */
    public static double hourInDay()
    {
       Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.HOUR_OF_DAY);
   }
    
    /**
     * The date:minute-in-hour function returns the minute of the hour 
     * as a number. If no argument is given, then the current local
     * date/time, as returned by date:date-time is used the default argument. 
     * The date/time string specified as the argument is a right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime
     * in one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *      xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *      xs:time (hh:mm:ss) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static double minuteInHour(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return Double.NaN;            
      
      String[] formats = {dt,t};
      return getNumber(datetime, formats, Calendar.MINUTE);
    }    
    
    /**
     * See above.
     */
   public static double minuteInHour()
    {
       Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.MINUTE);
   }    

    /**
     * The date:second-in-minute function returns the second of the minute 
     * as a number. If no argument is given, then the current local 
     * date/time, as returned by date:date-time is used the default argument. 
     * The date/time string specified as the argument is a right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime
     * in one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *      xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *      xs:time (hh:mm:ss) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static double secondInMinute(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return Double.NaN;            
      
      String[] formats = {dt, t};
      return getNumber(datetime, formats, Calendar.SECOND);
    }

    /**
     * See above.
     */
    public static double secondInMinute()
    {
       Calendar cal = Calendar.getInstance();
      return cal.get(Calendar.SECOND);
    }
       
    /**
     * The date:leap-year function returns true if the year given in a date 
     * is a leap year. If no argument is given, then the current local
     * date/time, as returned by date:date-time is used as a default argument. 
     * The date/time string specified as the first argument must be a 
     * right-truncated string in the format defined as the lexical representation
     * of xs:dateTime in one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *    xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *    xs:date (CCYY-MM-DD) 
     *    xs:gYearMonth (CCYY-MM) 
     *    xs:gYear (CCYY) 
     * If the date/time string is not in one of these formats, then NaN is returned. 
     */
    public static XObject leapYear(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return new XNumber(Double.NaN);            
            
      String[] formats = {dt, d, gym, gy};
      double dbl = getNumber(datetime, formats, Calendar.YEAR);
      if (dbl == Double.NaN) 
        return new XNumber(Double.NaN);
      int yr = (int)dbl;
      return new XBoolean(yr % 400 == 0 || (yr % 100 != 0 && yr % 4 == 0));
    }
    
    /**
     * See above.
     */
    public static boolean leapYear()
    {
      Calendar cal = Calendar.getInstance();
      int yr = (int)cal.get(Calendar.YEAR);
      return (yr % 400 == 0 || (yr % 100 != 0 && yr % 4 == 0));      
    }    
       
    /**
     * The date:month-name function returns the full name of the month of a date. 
     * If no argument is given, then the current local date/time, as returned by 
     * date:date-time is used the default argument. 
     * The date/time string specified as the argument is a left or right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime in
     *  one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *    xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *    xs:date (CCYY-MM-DD) 
     *    xs:gYearMonth (CCYY-MM) 
     *    xs:gMonth (--MM--) 
     * If the date/time string is not in one of these formats, then an empty string ('') 
     * is returned. 
     * The result is an English month name: one of 'January', 'February', 'March', 
     * 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November' 
     * or 'December'. 
     */
    public static String monthName(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return EMPTY_STR;
      
      String[] formatsIn = {dt, d, gym, gm};
      String formatOut = "MMMM";
      return getNameOrAbbrev(datetimeIn, formatsIn, formatOut);    
    }
    
    /**
     * See above.
     */
    public static String monthName()
    {
      Calendar cal = Calendar.getInstance();
      String format = "MMMM";
      return getNameOrAbbrev(format);  
    }
        
    /**
     * The date:month-abbreviation function returns the abbreviation of the month of 
     * a date. If no argument is given, then the current local date/time, as returned 
     * by date:date-time is used the default argument. 
     * The date/time string specified as the argument is a left or right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime in 
     * one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *    xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *    xs:date (CCYY-MM-DD) 
     *    xs:gYearMonth (CCYY-MM) 
     *    xs:gMonth (--MM--) 
     * If the date/time string is not in one of these formats, then an empty string ('') 
     * is returned. 
     * The result is a three-letter English month abbreviation: one of 'Jan', 'Feb', 'Mar', 
     * 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov' or 'Dec'. 
     * An implementation of this extension function in the EXSLT date namespace must conform 
     * to the behaviour described in this document. 
     */
    public static String monthAbbreviation(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return EMPTY_STR;
      
      String[] formatsIn = {dt, d, gym, gm};
      String formatOut = "MMM";
      return getNameOrAbbrev(datetimeIn, formatsIn, formatOut);
    }
    
    /**
     * See above.
     */
    public static String monthAbbreviation()
    {
      String format = "MMM";
      return getNameOrAbbrev(format);  
    }
        
    /**
     * The date:day-name function returns the full name of the day of the week 
     * of a date.  If no argument is given, then the current local date/time, 
     * as returned by date:date-time is used the default argument. 
     * The date/time string specified as the argument is a left or right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime 
     * in one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *     xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *     xs:date (CCYY-MM-DD) 
     * If the date/time string is not in one of these formats, then the empty string ('') 
     * is returned. 
     * The result is an English day name: one of 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 
     * 'Thursday' or 'Friday'. 
     * An implementation of this extension function in the EXSLT date namespace must conform 
     * to the behaviour described in this document. 
     */
    public static String dayName(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return EMPTY_STR;
            
      String[] formatsIn = {dt, d};
      String formatOut = "EEEE";
      return getNameOrAbbrev(datetimeIn, formatsIn, formatOut);    
    }
    
    /**
     * See above.
     */
    public static String dayName()
    {
      String format = "EEEE";
      return getNameOrAbbrev(format);        
    }    
    
    /**
     * The date:day-abbreviation function returns the abbreviation of the day 
     * of the week of a date. If no argument is given, then the current local 
     * date/time, as returned  by date:date-time is used the default argument. 
     * The date/time string specified as the argument is a left or right-truncated 
     * string in the format defined as the lexical representation of xs:dateTime 
     * in one of the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     *     xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     *     xs:date (CCYY-MM-DD) 
     * If the date/time string is not in one of these formats, then the empty string 
     * ('') is returned. 
     * The result is a three-letter English day abbreviation: one of 'Sun', 'Mon', 'Tue', 
     * 'Wed', 'Thu' or 'Fri'. 
     * An implementation of this extension function in the EXSLT date namespace must conform 
     * to the behaviour described in this document. 
     */
    public static String dayAbbreviation(String datetimeIn)
      throws ParseException
    {
      String[] edz = getEraDatetimeZone(datetimeIn);
      String datetime = edz[1];
      if (datetime == null) 
        return EMPTY_STR;            
      
      String[] formatsIn = {dt, d};
      String formatOut = "EEE";
      return getNameOrAbbrev(datetimeIn, formatsIn, formatOut);
    }
    
    /**
     * See above.
     */
    public static String dayAbbreviation()
    {
      String format = "EEE";
      return getNameOrAbbrev(format);              
    }
    
    /**
     * Returns an array with the 3 components that a datetime input string 
     * may contain: - (for BC era), datetime, and zone. If the zone is not
     * valid, return null for that component.
     */
    private static String[] getEraDatetimeZone(String in)
    {
      String leader = "";
      String datetime = in;
      String zone = "";
      if (in.charAt(0)=='-' && !in.startsWith("--"))
      {
        leader = "-"; //  '+' is implicit , not allowed
        datetime = in.substring(1);
      }
      int z = getZoneStart(datetime);
      if (z > 0)
      {
        zone = datetime.substring(z);
        datetime = datetime.substring(0, z);
      }
      else if (z == -2)
        zone = null;
      //System.out.println("'" + leader + "' " + datetime + " " + zone);
      return new String[]{leader, datetime, zone};  
    }    
    
    /**
     * Get the start of zone information if the input ends
     * with 'Z' or +/-hh:mm. If a zone string is not
     * found, return -1; if the zone string is invalid,
     * return -2.
     */
    private static int getZoneStart (String datetime)
    {
      if (datetime.indexOf("Z") == datetime.length()-1)
        return datetime.length()-1;
      else if (datetime.length() >=6 
      		&& datetime.charAt(datetime.length()-3) == ':'
      		&& (datetime.charAt(datetime.length()-6) == '+' 
      		    || datetime.charAt(datetime.length()-6) == '-'))      		    
      {
        try
        {
          SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm");
          dateFormat.setLenient(false);
          Date d = dateFormat.parse(datetime.substring(datetime.length() -5));
          return datetime.length()-6;
        }
        catch (ParseException pe)
        {
          System.out.println("ParseException " + pe.getErrorOffset());
          return -2; // Invalid.
        }

      }
        return -1; // No zone information.
    }
    
    /**
     * Attempt to parse an input string with the allowed formats, returning
     * null if none of the formats work.
     */
    private static Date testFormats (String in, String[] formats)
      throws ParseException
    {
      for (int i = 0; i <formats.length; i++)
      {
        try
        {
          SimpleDateFormat dateFormat = new SimpleDateFormat(formats[i]);
          dateFormat.setLenient(false);          
          return dateFormat.parse(in);
        }
        catch (ParseException pe)
        {
        }
      }
      return null;
    }
    
    
    /**
     * Parse the input string and return the corresponding calendar field
     * number.
     */
    private static double getNumber(String in, String[] formats, int calField)
      throws ParseException
    {
      Calendar cal = Calendar.getInstance();
      cal.setLenient(false);
      // Try the allowed formats, from longest to shortest.
      Date date = testFormats(in, formats);
      if (date == null) return Double.NaN;
      cal.setTime(date);
      return cal.get(calField);
    }    
     
    /**
     *  Get the full name or abbreviation of the month or day.
     */
    private static String getNameOrAbbrev(String in, 
                                         String[] formatsIn,
                                         String formatOut)
      throws ParseException
    {
      for (int i = 0; i <formatsIn.length; i++) // from longest to shortest.
      {
        try
        {
          SimpleDateFormat dateFormat = new SimpleDateFormat(formatsIn[i]);
          dateFormat.setLenient(false);
          Date dt = dateFormat.parse(in);          
          dateFormat.applyPattern(formatOut);
          return dateFormat.format(dt);
        }
        catch (ParseException pe)
        {
        }
      }
      return "";
    }
    /**
     * Get the full name or abbreviation for the current month or day 
     * (no input string).
     */
    private static String getNameOrAbbrev(String format)
    {
      Calendar cal = Calendar.getInstance();
      SimpleDateFormat dateFormat = new SimpleDateFormat(format);
      return dateFormat.format(cal.getTime());
    }

    /**
     * The date:format-date function formats a date/time according to a pattern.
     * <p>
     * The first argument to date:format-date specifies the date/time to be 
     * formatted. It must be right or left-truncated date/time strings in one of 
     * the formats defined in 
     * <a href="http://www.w3.org/TR/xmlschema-2/">[XML Schema Part 2: Datatypes]</a>. 
     * The permitted formats are as follows: 
     * <ul>
     * <li>xs:dateTime (CCYY-MM-DDThh:mm:ss) 
     * <li>xs:date (CCYY-MM-DD) 
     * <li>xs:time (hh:mm:ss) 
     * <li>xs:gYearMonth (CCYY-MM) 
     * <li>xs:gYear (CCYY) 
     * <li>xs:gMonthDay (--MM-DD) 
     * <li>xs:gMonth (--MM--) 
     * <li>xs:gDay (---DD)
     * </ul>
     * The second argument is a string that gives the format pattern used to 
     * format the date. The format pattern must be in the syntax specified by 
     * the JDK 1.1 SimpleDateFormat class. The format pattern string is 
     * interpreted as described for the JDK 1.1 SimpleDateFormat class. 
     * <p>
     * If the date/time format is right-truncated (i.e. in a format other than 
     * xs:time, or xs:dateTime) then any missing components are assumed to be as 
     * follows: if no month is specified, it is given a month of 01; if no day 
     * is specified, it is given a day of 01; if no time is specified, it is 
     * given a time of 00:00:00. 
     * <p>
     * If the date/time format is left-truncated (i.e. xs:time, xs:gMonthDay, 
     * xs:gMonth or xs:gDay) and the format pattern has a token that uses a 
     * component that is missing from the date/time format used, then that token 
     * is replaced with an empty string ('') within the result.
     * 
     * The author is Helg Bredow (helg.bredow@kalido.com)
     */
    public static String formatDate(String dateTime, String pattern)
    {
        final String yearSymbols = "Gy";
        final String monthSymbols = "M";
        final String daySymbols = "dDEFwW";
        TimeZone timeZone;
        String zone;

        // Get the timezone information if it was supplied and modify the 
        // dateTime so that SimpleDateFormat will understand it.
        if (dateTime.endsWith("Z") || dateTime.endsWith("z"))
        {
            timeZone = TimeZone.getTimeZone("GMT");
            dateTime = dateTime.substring(0, dateTime.length()-1) + "GMT";
            zone = "z";
        }
        else if ((dateTime.length() >= 6) 
                 && (dateTime.charAt(dateTime.length()-3) == ':') 
                 && ((dateTime.charAt(dateTime.length()-6) == '+') 
                    || (dateTime.charAt(dateTime.length()-6) == '-')))
        {
            String offset = dateTime.substring(dateTime.length()-6);
            
            if ("+00:00".equals(offset) || "-00:00".equals(offset))
            {
                timeZone = TimeZone.getTimeZone("GMT");
            }
            else
            {
                timeZone = TimeZone.getTimeZone("GMT" + offset);
            }
            zone = "z";
            // Need to adjust it since SimpleDateFormat requires GMT+hh:mm but
            // we have +hh:mm.
            dateTime = dateTime.substring(0, dateTime.length()-6) + "GMT" + offset;
        }
        else
        {
            // Assume local time.
            timeZone = TimeZone.getDefault();
            zone = "";
            // Leave off the timezone since SimpleDateFormat will assume local
            // time if time zone is not included.
        }
        String[] formats = {dt + zone, d, gym, gy};
        
        // Try the time format first. We need to do this to prevent 
        // SimpleDateFormat from interpreting a time as a year. i.e we just need
        // to check if it's a time before we check it's a year.
        try
        {
            SimpleDateFormat inFormat = new SimpleDateFormat(t + zone);
            inFormat.setLenient(false);
            Date d= inFormat.parse(dateTime);
            SimpleDateFormat outFormat = new SimpleDateFormat(strip
                (yearSymbols + monthSymbols + daySymbols, pattern));
            outFormat.setTimeZone(timeZone);
            return outFormat.format(d);
        }
        catch (ParseException pe)
        {
        }
        
        // Try the right truncated formats.
        for (int i = 0; i < formats.length; i++)
        {
            try
            {
                SimpleDateFormat inFormat = new SimpleDateFormat(formats[i]);
                inFormat.setLenient(false);
                Date d = inFormat.parse(dateTime);
                SimpleDateFormat outFormat = new SimpleDateFormat(pattern);
                outFormat.setTimeZone(timeZone);
                return outFormat.format(d);
            }
            catch (ParseException pe)
            {
            }
        }
        
        // Now try the left truncated ones. The Java format() function doesn't
        // return the correct strings in this case. We strip any pattern 
        // symbols that shouldn't be output so that they are not defaulted to 
        // inappropriate values in the output.
        try
        {
            SimpleDateFormat inFormat = new SimpleDateFormat(gmd);
            inFormat.setLenient(false);          
            Date d = inFormat.parse(dateTime);
            SimpleDateFormat outFormat = new SimpleDateFormat(strip(yearSymbols, pattern));
            outFormat.setTimeZone(timeZone);
            return outFormat.format(d);
        }
        catch (ParseException pe)
        {
        }
        try
        {
            SimpleDateFormat inFormat = new SimpleDateFormat(gm);
            inFormat.setLenient(false);
            Date d = inFormat.parse(dateTime);
            SimpleDateFormat outFormat = new SimpleDateFormat(strip(yearSymbols, pattern));
            outFormat.setTimeZone(timeZone);
            return outFormat.format(d);
        }
        catch (ParseException pe)
        {
        }
        try
        {
            SimpleDateFormat inFormat = new SimpleDateFormat(gd);
            inFormat.setLenient(false);
            Date d = inFormat.parse(dateTime);
            SimpleDateFormat outFormat = new SimpleDateFormat(strip(yearSymbols + monthSymbols, pattern));
            outFormat.setTimeZone(timeZone);
            return outFormat.format(d);
        }
        catch (ParseException pe)
        {
        }
        return EMPTY_STR;
    }
    
    /**
     * Strips occurrences of the given character from a date format pattern.
     * @param symbols list of symbols to strip.
     * @param pattern
     * @return
     */
    private static String strip(String symbols, String pattern)
    {
        int quoteSemaphore = 0;
        int i = 0;
        StringBuffer result = new StringBuffer(pattern.length());

        while (i < pattern.length())
        {
            char ch = pattern.charAt(i);
            if (ch == '\'')
            {
                // Assume it's an openening quote so simply copy the quoted 
                // text to the result. There is nothing to strip here.
                int endQuote = pattern.indexOf('\'', i + 1);
                if (endQuote == -1)
                {
                    endQuote = pattern.length();
                }
                result.append(pattern.substring(i, endQuote));
                i = endQuote++;
            }
            else if (symbols.indexOf(ch) > -1)
            {
                // The char needs to be stripped.
                i++;
            }
            else
            {
                result.append(ch);
                i++;
            }
        }
        return result.toString();
    }

}