#332 casting xs:date to xs:gYearMonth etc

v8.3
closed
Michael Kay
5
2012-10-08
2005-03-21
Michael Kay
No

When an xs:date or xs:dateTime value is cast to a value
of type xs:gYear, gYearMonth, gMonth, gMonthDay, or
gDay, the resulting value does not compare equal to a
value of type gYear (etc) produced directly from its
lexical representation.

Source fix: In package net.sf.saxon.value,

in class GYearValue add method

public void setDateValue(DateValue d) {
    super.setDateValue(d);
    calendar.set(Calendar.MONTH, 0);
    calendar.set(Calendar.DATE, 1);
}

in class GYearMonthValue add method

public void setDateValue(DateValue d) {
    super.setDateValue(d);
    calendar.set(Calendar.DATE, 1);        
}

in class GMonthValue add method

public void setDateValue(DateValue d) {
    super.setDateValue(d);
    calendar.set(Calendar.YEAR, 2000);
    calendar.set(Calendar.DATE, 1);
}

in class GMonthDayValue add method

public void setDateValue(DateValue d) {
    super.setDateValue(d);
    calendar.set(Calendar.YEAR, 2000);
}

in class GDayValue add method

public void setDateValue(DateValue d) {
    super.setDateValue(d);
    calendar.set(Calendar.YEAR, 2000);
    calendar.set(Calendar.MONTH, 0);          
}

Michael Kay
Saxonica

Discussion

  • Michael Kay
    Michael Kay
    2005-03-24

    Logged In: YES
    user_id=251681

    The above patch is incorrect and is withdrawn. It creates a
    gYear (etc) that shares the same calendar object as the
    original date object, and then modifies it, corrupting the
    original value. A revised fix is under development.

     
  • Michael Kay
    Michael Kay
    2005-03-24

    Logged In: YES
    user_id=251681

    The following revised fix has been tested against the full
    regression test suite.

    (a) in net.sf.saxon.value.DateValue, method
    convertPrimitive, replace the relevant sections of the
    switch expression by:

        case Type.G_YEAR: {
            GregorianCalendar cal2 = new
    

    GregorianCalendar(calendar.getTimeZone());
    cal2.clear();
    cal2.set(calendar.get(Calendar.YEAR), 0, 1);
    cal2.set(Calendar.ZONE_OFFSET, tzOffset60000);
    cal2.set(Calendar.DST_OFFSET, 0);
    calendar.getTime();
    return new GYearValue(cal2, zoneSpecified,
    tzOffset);
    }
    case Type.G_YEAR_MONTH: {
    GregorianCalendar cal2 = new
    GregorianCalendar(calendar.getTimeZone());
    cal2.clear();
    cal2.set(calendar.get(Calendar.YEAR),
    calendar.get(Calendar.MONTH), 1);
    cal2.set(Calendar.ZONE_OFFSET, tzOffset
    60000);
    cal2.set(Calendar.DST_OFFSET, 0);
    calendar.getTime();
    return new GYearMonthValue(cal2, zoneSpecified,
    tzOffset);
    }
    case Type.G_MONTH: {
    GregorianCalendar cal2 = new
    GregorianCalendar(calendar.getTimeZone());
    cal2.clear();
    cal2.set(2000, calendar.get(Calendar.MONTH), 1);
    cal2.set(Calendar.ZONE_OFFSET, tzOffset60000);
    cal2.set(Calendar.DST_OFFSET, 0);
    calendar.getTime();
    return new GMonthValue(cal2, zoneSpecified,
    tzOffset);
    }
    case Type.G_MONTH_DAY: {
    GregorianCalendar cal2 = new
    GregorianCalendar(calendar.getTimeZone());
    cal2.clear();
    cal2.set(2000, calendar.get(Calendar.MONTH),
    calendar.get(Calendar.DATE));
    cal2.set(Calendar.ZONE_OFFSET, tzOffset
    60000);
    cal2.set(Calendar.DST_OFFSET, 0);
    calendar.getTime();
    return new GMonthDayValue(cal2, zoneSpecified,
    tzOffset);
    }
    case Type.G_DAY:{
    GregorianCalendar cal2 = new
    GregorianCalendar(calendar.getTimeZone());
    cal2.clear();
    cal2.set(2000, 0, calendar.get(Calendar.DATE));
    cal2.set(Calendar.ZONE_OFFSET, tzOffset*60000);
    cal2.set(Calendar.DST_OFFSET, 0);
    calendar.getTime();
    return new GDayValue(cal2, zoneSpecified, tzOffset);
    }

    (b) In net.sf.saxon.value.GYear, add a new constructor:

    public GYearValue(GregorianCalendar calendar, boolean
    

    timezoneSpecified, int tzoffset) {
    super(calendar, timezoneSpecified, tzoffset);
    }

    Add identical constructors, differing only in the name of
    the constructor, to classes GYearMonthValue, GMonthValue,
    GMOnthDayValue, and GDayValue in the same package.