boolean ignoreTime = (value instanceof DateValue);
DateTimeValue dtvalue = value.toDateTime();
Matcher matcher = componentPattern.matcher(specifier);
if (!matcher.matches()) {
XPathException error = new XPathException("Unrecognized date/time component [" + specifier + ']');
error.setErrorCode("XTDE1340");
error.setXPathContext(context);
throw error;
}
String component = matcher.group(1);
String format = matcher.group(2);
if (format==null) {
format = "";
}
boolean defaultFormat = false;
if ("".equals(format) || format.startsWith(",")) {
defaultFormat = true;
switch (component.charAt(0) ) {
case 'F':
format = "Nn" + format;
break;
case 'P':
format = 'n' + format;
break;
case 'C':
case 'E':
format = 'N' + format;
break;
case 'm':
case 's':
format = "01" + format;
break;
default:
format = '1' + format;
}
}
switch (component.charAt(0)) {
case'Y': // year
if (ignoreDate) {
XPathException error = new XPathException("In formatTime(): an xs:time value does not contain a year component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int year = dtvalue.getYear();
if (year < 0) {
year = 1 - year;
}
return formatNumber(component, year, format, defaultFormat, numberer, context);
}
case'M': // month
if (ignoreDate) {
XPathException error = new XPathException("In formatTime(): an xs:time value does not contain a month component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int month = dtvalue.getMonth();
return formatNumber(component, month, format, defaultFormat, numberer, context);
}
case'D': // day in month
if (ignoreDate) {
XPathException error = new XPathException("In formatTime(): an xs:time value does not contain a day component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int day = dtvalue.getDay();
return formatNumber(component, day, format, defaultFormat, numberer, context);
}
case'd': // day in year
if (ignoreDate) {
XPathException error = new XPathException("In formatTime(): an xs:time value does not contain a day component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int day = DateValue.getDayWithinYear(dtvalue.getYear(), dtvalue.getMonth(), dtvalue.getDay());
return formatNumber(component, day, format, defaultFormat, numberer, context);
}
case'W': // week of year
if (ignoreDate) {
XPathException error = new XPathException("In formatTime(): cannot obtain the week number from an xs:time value");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int week = DateValue.getWeekNumber(dtvalue.getYear(), dtvalue.getMonth(), dtvalue.getDay());
return formatNumber(component, week, format, defaultFormat, numberer, context);
}
case'w': // week in month
if (ignoreDate) {
XPathException error = new XPathException("In formatTime(): cannot obtain the week number from an xs:time value");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int week = DateValue.getWeekNumberWithinMonth(dtvalue.getYear(), dtvalue.getMonth(), dtvalue.getDay());
return formatNumber(component, week, format, defaultFormat, numberer, context);
}
case'H': // hour in day
if (ignoreTime) {
XPathException error = new XPathException("In formatDate(): an xs:date value does not contain an hour component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
Int64Value hour = (Int64Value)value.getComponent(Component.HOURS);
return formatNumber(component, (int)hour.longValue(), format, defaultFormat, numberer, context);
}
case'h': // hour in half-day (12 hour clock)
if (ignoreTime) {
XPathException error = new XPathException("In formatDate(): an xs:date value does not contain an hour component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
Int64Value hour = (Int64Value)value.getComponent(Component.HOURS);
int hr = (int)hour.longValue();
if (hr > 12) {
hr = hr - 12;
}
if (hr == 0) {
hr = 12;
}
return formatNumber(component, hr, format, defaultFormat, numberer, context);
}
case'm': // minutes
if (ignoreTime) {
XPathException error = new XPathException("In formatDate(): an xs:date value does not contain a minutes component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
Int64Value min = (Int64Value)value.getComponent(Component.MINUTES);
return formatNumber(component, (int)min.longValue(), format, defaultFormat, numberer, context);
}
case's': // seconds
if (ignoreTime) {
XPathException error = new XPathException("In formatDate(): an xs:date value does not contain a seconds component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
IntegerValue sec = (IntegerValue)value.getComponent(Component.WHOLE_SECONDS);
return formatNumber(component, (int)sec.longValue(), format, defaultFormat, numberer, context);
}
case'f': // fractional seconds
// ignore the format
if (ignoreTime) {
XPathException error = new XPathException("In formatDate(): an xs:date value does not contain a fractional seconds component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int micros = (int)((Int64Value)value.getComponent(Component.MICROSECONDS)).longValue();
return formatNumber(component, micros, format, defaultFormat, numberer, context);
}
case'Z': // timezone in +hh:mm format, unless format=N in which case use timezone name
if (value.hasTimezone()) {
return getNamedTimeZone(value.toDateTime(), numberer.getCountry(), format);
} else {
return "";
}
case'z': // timezone
if (value.hasTimezone()) {
int tz = value.getTimezoneInMinutes();
return "GMT" + (tz == 0 ? "" : ((tz > 0 ? "+" : "-") + Math.abs(tz / 60) + (tz % 60 == 0 ? "" : ".5")));
} else {
return "";
}
case'F': // day of week
if (ignoreDate) {
XPathException error = new XPathException("In formatTime(): an xs:time value does not contain day-of-week component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int day = DateValue.getDayOfWeek(dtvalue.getYear(), dtvalue.getMonth(), dtvalue.getDay());
return formatNumber(component, day, format, defaultFormat, numberer, context);
}
case'P': // am/pm marker
if (ignoreTime) {
XPathException error = new XPathException("In formatDate(): an xs:date value does not contain an am/pm component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int minuteOfDay = dtvalue.getHour() * 60 + dtvalue.getMinute();
return formatNumber(component, minuteOfDay, format, defaultFormat, numberer, context);
}
case'C': // calendar
return numberer.getCalendarName("AD");
case'E': // era
if (ignoreDate) {
XPathException error = new XPathException("In formatTime(): an xs:time value does not contain an AD/BC component");
error.setErrorCode("XTDE1350");
error.setXPathContext(context);
throw error;
} else {
int year = dtvalue.getYear();
return numberer.getEraName(year);
}
default:
XPathException e = new XPathException("Unknown formatDate/time component specifier '" + format.charAt(0) + '\'');
e.setErrorCode("XTDE1340");
e.setXPathContext(context);
throw e;
}
}