下面列出了java.util.GregorianCalendar#BC 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static SpearalDateTime forGregorianCalendar(GregorianCalendar calendar) {
calendar.setTimeZone(UTC);
int year = calendar.get(Calendar.YEAR);
if (calendar.get(Calendar.ERA) == GregorianCalendar.BC)
year = -year;
return new SpearalDateTime(
year,
calendar.get(Calendar.MONTH) + 1,
calendar.get(Calendar.DATE),
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
calendar.get(Calendar.SECOND),
calendar.get(Calendar.MILLISECOND) * 1000000,
true, true
);
}
private void validateDate() {
this.calendar.getTime();
int year = this.calendar.get(Calendar.YEAR);
if (this.calendar.isSet(Calendar.ERA) && this.calendar.get(Calendar.ERA) == GregorianCalendar.BC) {
year = 0 - year + 1;
}
}
@Override
public String stringValue() {
StringBuilder stringBuilder = new StringBuilder();
if (this.calendar.get(Calendar.ERA) == GregorianCalendar.BC) {
int yearBC = this.calendar.get(Calendar.YEAR) - 1;
stringBuilder.append('-');
stringBuilder.append(String.format("%d", yearBC));
} else {
stringBuilder.append(String.format("%d", this.calendar.get(Calendar.YEAR)));
}
stringBuilder.append('-');
stringBuilder.append(String.format("%02d", this.calendar.get(Calendar.MONTH) + 1));
stringBuilder.append('-');
stringBuilder.append(String.format("%02d", this.calendar.get(Calendar.DAY_OF_MONTH)));
stringBuilder.append('T');
stringBuilder.append(String.format("%02d", this.calendar.get(Calendar.HOUR_OF_DAY)));
stringBuilder.append(':');
stringBuilder.append(String.format("%02d", this.calendar.get(Calendar.MINUTE)));
stringBuilder.append(':');
stringBuilder.append(String.format("%02d", this.calendar.get(Calendar.SECOND)));
int ms = this.calendar.get(Calendar.MILLISECOND);
if (ms != 0) {
stringBuilder.append('.');
stringBuilder.append(String.format("%03d", ms));
}
if (this.getHasTimeZone()) {
stringBuilder.append(this.getTimeZone());
}
return stringBuilder.toString();
}
/**
* Reported bug is that a GregorianCalendar with a cutover of Date(Long.MAX_VALUE)
* doesn't behave as a pure Julian calendar.
* CANNOT REPRODUCE THIS BUG
*/
public void Test4149677() {
TimeZone[] zones = {TimeZone.getTimeZone("GMT"),
TimeZone.getTimeZone("PST"),
TimeZone.getTimeZone("EAT")};
for (int i = 0; i < zones.length; ++i) {
GregorianCalendar calendar = new GregorianCalendar(zones[i]);
// Make sure extreme values don't wrap around
calendar.setTime(new Date(Long.MIN_VALUE));
if (calendar.get(ERA) != GregorianCalendar.BC) {
errln("Fail: Date(Long.MIN_VALUE) has an AD year in " + zones[i]);
}
calendar.setTime(new Date(Long.MAX_VALUE));
if (calendar.get(ERA) != GregorianCalendar.AD) {
errln("Fail: Date(Long.MAX_VALUE) has a BC year in " + zones[i]);
}
calendar.setGregorianChange(new Date(Long.MAX_VALUE));
// to obtain a pure Julian calendar
boolean is100Leap = calendar.isLeapYear(100);
if (!is100Leap) {
errln("test failed with zone " + zones[i].getID());
errln(" cutover date is Date(Long.MAX_VALUE)");
errln(" isLeapYear(100) returns: " + is100Leap);
}
}
}
public int getYear() {
int year = this.calendar.get(Calendar.YEAR);
if (this.calendar.get(Calendar.ERA) == GregorianCalendar.BC) {
return -(year - 1);
} else {
return year;
}
}
public static ISO8601Date fromCalendar(Calendar calendar) {
int year;
if (calendar.get(Calendar.ERA) == GregorianCalendar.BC) {
year = 1 - calendar.get(Calendar.YEAR);
} else {
year = calendar.get(Calendar.YEAR);
}
return new ISO8601Date(calendar.getTimeZone(), year, calendar.get(Calendar.MONTH)+1, calendar.get(Calendar.DAY_OF_MONTH));
}
/**
* Formats a <code>Calendar</code> value into an ISO8601-compliant
* date/time string.
*
* @param cal
* The time value to be formatted into a date/time string.
* @return The formatted date/time string.
*/
public static String format(final Calendar cal) {
if (cal == null) {
throw new IllegalArgumentException("argument can not be null");
}
// determine era and adjust year if necessary
int year = cal.get(Calendar.YEAR);
if (cal.isSet(Calendar.ERA) && cal.get(Calendar.ERA) == GregorianCalendar.BC) {
/**
* calculate year using astronomical system: year n BCE =>
* astronomical year -n + 1
*/
year = 0 - year + 1;
}
/**
* the format of the date/time string is: YYYY-MM-DDThh:mm:ss.SSSTZD
* note that we cannot use java.text.SimpleDateFormat for formatting
* because it can't handle years <= 0 and TZD's
*/
StringBuilder buf = new StringBuilder();
// year ([-]YYYY)
buf.append(XXXX_FORMAT.format(year));
buf.append('-');
// month (MM)
buf.append(XX_FORMAT.format(cal.get(Calendar.MONTH) + 1));
buf.append('-');
// day (DD)
buf.append(XX_FORMAT.format(cal.get(Calendar.DAY_OF_MONTH)));
buf.append('T');
// hour (hh)
buf.append(XX_FORMAT.format(cal.get(Calendar.HOUR_OF_DAY)));
buf.append(':');
// minute (mm)
buf.append(XX_FORMAT.format(cal.get(Calendar.MINUTE)));
buf.append(':');
// second (ss)
buf.append(XX_FORMAT.format(cal.get(Calendar.SECOND)));
buf.append('.');
// millisecond (SSS)
buf.append(XXX_FORMAT.format(cal.get(Calendar.MILLISECOND)));
// time zone designator (Z or +00:00 or -00:00)
TimeZone tz = cal.getTimeZone();
// determine offset of timezone from UTC (incl. daylight saving)
int offset = tz.getOffset(cal.getTimeInMillis());
if (offset != 0) {
int hours = Math.abs((offset / (60 * 1000)) / 60);
int minutes = Math.abs((offset / (60 * 1000)) % 60);
buf.append(offset < 0 ? '-' : '+');
buf.append(XX_FORMAT.format(hours));
buf.append(':');
buf.append(XX_FORMAT.format(minutes));
} else {
buf.append('Z');
}
return buf.toString();
}
/**
* Formats a <code>Calendar</code> value into an ISO8601-compliant date/time
* string.
*
* @param cal
* The time value to be formatted into a date/time string.
* @return The formatted date/time string.
*/
public static String format(final Calendar cal) {
if (cal == null) {
throw new IllegalArgumentException("argument can not be null");
}
// determine era and adjust year if necessary
int year = cal.get(Calendar.YEAR);
if (cal.isSet(Calendar.ERA) && cal.get(Calendar.ERA) == GregorianCalendar.BC) {
/**
* calculate year using astronomical system: year n BCE =>
* astronomical year -n + 1
*/
year = 0 - year + 1;
}
/**
* the format of the date/time string is: YYYY-MM-DDThh:mm:ss.SSSTZD
* note that we cannot use java.text.SimpleDateFormat for formatting
* because it can't handle years <= 0 and TZD's
*/
StringBuilder buf = new StringBuilder();
// year ([-]YYYY)
buf.append(XXXX_FORMAT.format(year));
buf.append('-');
// month (MM)
buf.append(XX_FORMAT.format(cal.get(Calendar.MONTH) + 1));
buf.append('-');
// day (DD)
buf.append(XX_FORMAT.format(cal.get(Calendar.DAY_OF_MONTH)));
buf.append('T');
// hour (hh)
buf.append(XX_FORMAT.format(cal.get(Calendar.HOUR_OF_DAY)));
buf.append(':');
// minute (mm)
buf.append(XX_FORMAT.format(cal.get(Calendar.MINUTE)));
buf.append(':');
// second (ss)
buf.append(XX_FORMAT.format(cal.get(Calendar.SECOND)));
buf.append('.');
// millisecond (SSS)
buf.append(XXX_FORMAT.format(cal.get(Calendar.MILLISECOND)));
// time zone designator (+/-hh:mm)
buf.append(getTimeZone(cal));
return buf.toString();
}
public void validateLiteral(SqlLiteral literal) {
switch (literal.getTypeName()) {
case DECIMAL:
// Decimal and long have the same precision (as 64-bit integers), so
// the unscaled value of a decimal must fit into a long.
// REVIEW jvs 4-Aug-2004: This should probably be calling over to
// the available calculator implementations to see what they
// support. For now use ESP instead.
//
// jhyde 2006/12/21: I think the limits should be baked into the
// type system, not dependent on the calculator implementation.
BigDecimal bd = (BigDecimal) literal.getValue();
BigInteger unscaled = bd.unscaledValue();
long longValue = unscaled.longValue();
if (!BigInteger.valueOf(longValue).equals(unscaled)) {
// overflow
throw newValidationError(literal,
RESOURCE.numberLiteralOutOfRange(bd.toString()));
}
break;
case DOUBLE:
validateLiteralAsDouble(literal);
break;
case BINARY:
final BitString bitString = (BitString) literal.getValue();
if ((bitString.getBitCount() % 8) != 0) {
throw newValidationError(literal, RESOURCE.binaryLiteralOdd());
}
break;
case DATE:
case TIME:
case TIMESTAMP:
Calendar calendar = literal.getValueAs(Calendar.class);
final int year = calendar.get(Calendar.YEAR);
final int era = calendar.get(Calendar.ERA);
if (year < 1 || era == GregorianCalendar.BC || year > 9999) {
throw newValidationError(literal,
RESOURCE.dateLiteralOutOfRange(literal.toString()));
}
break;
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
case INTERVAL_DAY_MINUTE:
case INTERVAL_DAY_SECOND:
case INTERVAL_HOUR:
case INTERVAL_HOUR_MINUTE:
case INTERVAL_HOUR_SECOND:
case INTERVAL_MINUTE:
case INTERVAL_MINUTE_SECOND:
case INTERVAL_SECOND:
if (literal instanceof SqlIntervalLiteral) {
SqlIntervalLiteral.IntervalValue interval =
(SqlIntervalLiteral.IntervalValue)
literal.getValue();
SqlIntervalQualifier intervalQualifier =
interval.getIntervalQualifier();
// ensure qualifier is good before attempting to validate literal
validateIntervalQualifier(intervalQualifier);
String intervalStr = interval.getIntervalLiteral();
// throws CalciteContextException if string is invalid
int[] values = intervalQualifier.evaluateIntervalLiteral(intervalStr,
literal.getParserPosition(), typeFactory.getTypeSystem());
Util.discard(values);
}
break;
default:
// default is to do nothing
}
}
/**
* <p>Convert a <code>java.util.GregorianCalendar</code> to XML Schema 1.0
* representation.</p>
*
* <table border="2" rules="all" cellpadding="2">
* <thead>
* <tr>
* <th align="center" colspan="2">
* Field by Field Conversion from
* <code>java.util.GregorianCalendar</code> to this class
* </th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
* <th><code>java.util.GregorianCalendar</code> field</th>
* </tr>
* <tr>
* <th>{@link #setYear(int)}</th>
* <th><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></th>
* </tr>
* <tr>
* <th>{@link #setMonth(int)}</th>
* <th><code>MONTH + 1</code></th>
* </tr>
* <tr>
* <th>{@link #setDay(int)}</th>
* <th><code>DAY_OF_MONTH</code></th>
* </tr>
* <tr>
* <th>{@link #setTime(int,int,int, BigDecimal)}</th>
* <th><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></th>
* </tr>
* <tr>
* <th>{@link #setTimezone(int)}<i>*</i></th>
* <th><code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
* <i>(in minutes)</i>
* </th>
* </tr>
* </tbody>
* </table>
* <p><i>*</i>conversion loss of information. It is not possible to represent
* a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
* XML Schema 1.0 date/time datatype representation.</p>
*
* <p>To compute the return value's <code>TimeZone</code> field,
* <ul>
* <li>when <code>this.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
* create a <code>java.util.TimeZone</code> with a custom timezone id
* using the <code>this.getTimezone()</code>.</li>
* <li>else use the <code>GregorianCalendar</code> default timezone value
* for the host is defined as specified by
* <code>java.util.TimeZone.getDefault()</code>.</li></p>
*
* @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
*/
public XMLGregorianCalendarImpl(GregorianCalendar cal) {
int year = cal.get(Calendar.YEAR);
if (cal.get(Calendar.ERA) == GregorianCalendar.BC) {
year = -year;
}
this.setYear(year);
// Calendar.MONTH is zero based, XSD Date datatype's month field starts
// with JANUARY as 1.
this.setMonth(cal.get(Calendar.MONTH) + 1);
this.setDay(cal.get(Calendar.DAY_OF_MONTH));
this.setTime(
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
cal.get(Calendar.SECOND),
cal.get(Calendar.MILLISECOND));
// Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds.
int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
this.setTimezone(offsetInMinutes);
}
/**
* <p>Convert a <code>java.util.GregorianCalendar</code> to XML Schema 1.0
* representation.</p>
*
* <table border="2" rules="all" cellpadding="2">
* <thead>
* <tr>
* <th align="center" colspan="2">
* Field by Field Conversion from
* <code>java.util.GregorianCalendar</code> to this class
* </th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
* <th><code>java.util.GregorianCalendar</code> field</th>
* </tr>
* <tr>
* <th>{@link #setYear(int)}</th>
* <th><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></th>
* </tr>
* <tr>
* <th>{@link #setMonth(int)}</th>
* <th><code>MONTH + 1</code></th>
* </tr>
* <tr>
* <th>{@link #setDay(int)}</th>
* <th><code>DAY_OF_MONTH</code></th>
* </tr>
* <tr>
* <th>{@link #setTime(int,int,int, BigDecimal)}</th>
* <th><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></th>
* </tr>
* <tr>
* <th>{@link #setTimezone(int)}<i>*</i></th>
* <th><code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
* <i>(in minutes)</i>
* </th>
* </tr>
* </tbody>
* </table>
* <p><i>*</i>conversion loss of information. It is not possible to represent
* a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
* XML Schema 1.0 date/time datatype representation.</p>
*
* <p>To compute the return value's <code>TimeZone</code> field,
* <ul>
* <li>when <code>this.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
* create a <code>java.util.TimeZone</code> with a custom timezone id
* using the <code>this.getTimezone()</code>.</li>
* <li>else use the <code>GregorianCalendar</code> default timezone value
* for the host is defined as specified by
* <code>java.util.TimeZone.getDefault()</code>.</li></p>
*
* @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
*/
public XMLGregorianCalendarImpl(GregorianCalendar cal) {
int year = cal.get(Calendar.YEAR);
if (cal.get(Calendar.ERA) == GregorianCalendar.BC) {
year = -year;
}
this.setYear(year);
// Calendar.MONTH is zero based, XSD Date datatype's month field starts
// with JANUARY as 1.
this.setMonth(cal.get(Calendar.MONTH) + 1);
this.setDay(cal.get(Calendar.DAY_OF_MONTH));
this.setTime(
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
cal.get(Calendar.SECOND),
cal.get(Calendar.MILLISECOND));
// Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds.
int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
this.setTimezone(offsetInMinutes);
}
/**
* <p>Convert a <code>java.util.GregorianCalendar</code> to XML Schema 1.0
* representation.</p>
*
* <table border="2" rules="all" cellpadding="2">
* <thead>
* <tr>
* <th align="center" colspan="2">
* Field by Field Conversion from
* <code>java.util.GregorianCalendar</code> to this class
* </th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
* <th><code>java.util.GregorianCalendar</code> field</th>
* </tr>
* <tr>
* <th>{@link #setYear(int)}</th>
* <th><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></th>
* </tr>
* <tr>
* <th>{@link #setMonth(int)}</th>
* <th><code>MONTH + 1</code></th>
* </tr>
* <tr>
* <th>{@link #setDay(int)}</th>
* <th><code>DAY_OF_MONTH</code></th>
* </tr>
* <tr>
* <th>{@link #setTime(int,int,int, BigDecimal)}</th>
* <th><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></th>
* </tr>
* <tr>
* <th>{@link #setTimezone(int)}<i>*</i></th>
* <th><code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
* <i>(in minutes)</i>
* </th>
* </tr>
* </tbody>
* </table>
* <p><i>*</i>conversion loss of information. It is not possible to represent
* a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
* XML Schema 1.0 date/time datatype representation.</p>
*
* <p>To compute the return value's <code>TimeZone</code> field,
* <ul>
* <li>when <code>this.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
* create a <code>java.util.TimeZone</code> with a custom timezone id
* using the <code>this.getTimezone()</code>.</li>
* <li>else use the <code>GregorianCalendar</code> default timezone value
* for the host is defined as specified by
* <code>java.util.TimeZone.getDefault()</code>.</li></p>
*
* @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
*/
public XMLGregorianCalendarImpl(GregorianCalendar cal) {
int year = cal.get(Calendar.YEAR);
if (cal.get(Calendar.ERA) == GregorianCalendar.BC) {
year = -year;
}
this.setYear(year);
// Calendar.MONTH is zero based, XSD Date datatype's month field starts
// with JANUARY as 1.
this.setMonth(cal.get(Calendar.MONTH) + 1);
this.setDay(cal.get(Calendar.DAY_OF_MONTH));
this.setTime(
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
cal.get(Calendar.SECOND),
cal.get(Calendar.MILLISECOND));
// Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds.
int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
this.setTimezone(offsetInMinutes);
}
/** Returns an ISO8601 string representation of the time given
by the calendar*/
public static String ISOdate(Calendar c) {
return ((c.get(Calendar.ERA) == GregorianCalendar.BC ? "-" : "") + fourDigits.format(c.get(Calendar.YEAR)) + '-' + twoDigits
.format(c.get(Calendar.MONTH) + 1) + '-' + twoDigits.format(c.get(Calendar.DAY_OF_MONTH)));
}
/**
* <p>Convert a <code>java.util.GregorianCalendar</code> to XML Schema 1.0
* representation.</p>
*
* <table border="2" rules="all" cellpadding="2">
* <thead>
* <tr>
* <th align="center" colspan="2">
* Field by Field Conversion from
* <code>java.util.GregorianCalendar</code> to this class
* </th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
* <th><code>java.util.GregorianCalendar</code> field</th>
* </tr>
* <tr>
* <th>{@link #setYear(int)}</th>
* <th><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></th>
* </tr>
* <tr>
* <th>{@link #setMonth(int)}</th>
* <th><code>MONTH + 1</code></th>
* </tr>
* <tr>
* <th>{@link #setDay(int)}</th>
* <th><code>DAY_OF_MONTH</code></th>
* </tr>
* <tr>
* <th>{@link #setTime(int,int,int, BigDecimal)}</th>
* <th><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></th>
* </tr>
* <tr>
* <th>{@link #setTimezone(int)}<i>*</i></th>
* <th><code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
* <i>(in minutes)</i>
* </th>
* </tr>
* </tbody>
* </table>
* <p><i>*</i>conversion loss of information. It is not possible to represent
* a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
* XML Schema 1.0 date/time datatype representation.</p>
*
* <p>To compute the return value's <code>TimeZone</code> field,
* <ul>
* <li>when <code>this.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
* create a <code>java.util.TimeZone</code> with a custom timezone id
* using the <code>this.getTimezone()</code>.</li>
* <li>else use the <code>GregorianCalendar</code> default timezone value
* for the host is defined as specified by
* <code>java.util.TimeZone.getDefault()</code>.</li></p>
*
* @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
*/
public XMLGregorianCalendarImpl(GregorianCalendar cal) {
int year1 = cal.get(Calendar.YEAR);
if (cal.get(Calendar.ERA) == GregorianCalendar.BC) {
year1 = -year1;
}
this.setYear(year1);
// Calendar.MONTH is zero based, XSD Date datatype's month field starts
// with JANUARY as 1.
this.setMonth(cal.get(Calendar.MONTH) + 1);
this.setDay(cal.get(Calendar.DAY_OF_MONTH));
this.setTime(
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
cal.get(Calendar.SECOND),
cal.get(Calendar.MILLISECOND));
// Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds.
int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
this.setTimezone(offsetInMinutes);
save();
}
/**
* <p>Convert a <code>java.util.GregorianCalendar</code> to XML Schema 1.0
* representation.</p>
*
* <table border="2" rules="all" cellpadding="2">
* <thead>
* <tr>
* <th align="center" colspan="2">
* Field by Field Conversion from
* <code>java.util.GregorianCalendar</code> to this class
* </th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
* <th><code>java.util.GregorianCalendar</code> field</th>
* </tr>
* <tr>
* <th>{@link #setYear(int)}</th>
* <th><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></th>
* </tr>
* <tr>
* <th>{@link #setMonth(int)}</th>
* <th><code>MONTH + 1</code></th>
* </tr>
* <tr>
* <th>{@link #setDay(int)}</th>
* <th><code>DAY_OF_MONTH</code></th>
* </tr>
* <tr>
* <th>{@link #setTime(int,int,int, BigDecimal)}</th>
* <th><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></th>
* </tr>
* <tr>
* <th>{@link #setTimezone(int)}<i>*</i></th>
* <th><code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
* <i>(in minutes)</i>
* </th>
* </tr>
* </tbody>
* </table>
* <p><i>*</i>conversion loss of information. It is not possible to represent
* a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
* XML Schema 1.0 date/time datatype representation.</p>
*
* <p>To compute the return value's <code>TimeZone</code> field,
* <ul>
* <li>when <code>this.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
* create a <code>java.util.TimeZone</code> with a custom timezone id
* using the <code>this.getTimezone()</code>.</li>
* <li>else use the <code>GregorianCalendar</code> default timezone value
* for the host is defined as specified by
* <code>java.util.TimeZone.getDefault()</code>.</li></p>
*
* @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
*/
public XMLGregorianCalendarImpl(GregorianCalendar cal) {
int year = cal.get(Calendar.YEAR);
if (cal.get(Calendar.ERA) == GregorianCalendar.BC) {
year = -year;
}
this.setYear(year);
// Calendar.MONTH is zero based, XSD Date datatype's month field starts
// with JANUARY as 1.
this.setMonth(cal.get(Calendar.MONTH) + 1);
this.setDay(cal.get(Calendar.DAY_OF_MONTH));
this.setTime(
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
cal.get(Calendar.SECOND),
cal.get(Calendar.MILLISECOND));
// Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds.
int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
this.setTimezone(offsetInMinutes);
save();
}
/**
* Formats a <code>Calendar</code> value into an ISO8601-compliant
* date/time string. This method is copied from
* org.fosstrak.epcis.utils.TimeParser (module epcis-commons).
*
* @see org.fosstrak.epcis.utils.TimeParser#format(Calendar)
* @param cal
* The time value to be formatted into a date/time string.
* @return The formatted date/time string.
*/
private static String format(final Calendar cal) {
if (cal == null) {
throw new IllegalArgumentException("argument can not be null");
}
// determine era and adjust year if necessary
int year = cal.get(Calendar.YEAR);
if (cal.isSet(Calendar.ERA) && cal.get(Calendar.ERA) == GregorianCalendar.BC) {
/**
* calculate year using astronomical system: year n BCE =>
* astronomical year -n + 1
*/
year = 0 - year + 1;
}
/**
* the format of the date/time string is: YYYY-MM-DDThh:mm:ss.SSSTZD
* note that we cannot use java.text.SimpleDateFormat for formatting
* because it can't handle years <= 0 and TZD's
*/
StringBuilder buf = new StringBuilder();
// year ([-]YYYY)
buf.append(XXXX_FORMAT.format(year));
buf.append('-');
// month (MM)
buf.append(XX_FORMAT.format(cal.get(Calendar.MONTH) + 1));
buf.append('-');
// day (DD)
buf.append(XX_FORMAT.format(cal.get(Calendar.DAY_OF_MONTH)));
buf.append('T');
// hour (hh)
buf.append(XX_FORMAT.format(cal.get(Calendar.HOUR_OF_DAY)));
buf.append(':');
// minute (mm)
buf.append(XX_FORMAT.format(cal.get(Calendar.MINUTE)));
buf.append(':');
// second (ss)
buf.append(XX_FORMAT.format(cal.get(Calendar.SECOND)));
buf.append('.');
// millisecond (SSS)
buf.append(XXX_FORMAT.format(cal.get(Calendar.MILLISECOND)));
// time zone designator (+/-hh:mm)
buf.append(getTimeZone(cal));
return buf.toString();
}
/**
* <p>Convert a <code>java.util.GregorianCalendar</code> to XML Schema 1.0
* representation.</p>
*
* <table border="2" rules="all" cellpadding="2">
* <thead>
* <tr>
* <th align="center" colspan="2">
* Field by Field Conversion from
* <code>java.util.GregorianCalendar</code> to this class
* </th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
* <th><code>java.util.GregorianCalendar</code> field</th>
* </tr>
* <tr>
* <th>{@link #setYear(int)}</th>
* <th><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></th>
* </tr>
* <tr>
* <th>{@link #setMonth(int)}</th>
* <th><code>MONTH + 1</code></th>
* </tr>
* <tr>
* <th>{@link #setDay(int)}</th>
* <th><code>DAY_OF_MONTH</code></th>
* </tr>
* <tr>
* <th>{@link #setTime(int,int,int, BigDecimal)}</th>
* <th><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></th>
* </tr>
* <tr>
* <th>{@link #setTimezone(int)}<i>*</i></th>
* <th><code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
* <i>(in minutes)</i>
* </th>
* </tr>
* </tbody>
* </table>
* <p><i>*</i>conversion loss of information. It is not possible to represent
* a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
* XML Schema 1.0 date/time datatype representation.</p>
*
* <p>To compute the return value's <code>TimeZone</code> field,
* <ul>
* <li>when <code>this.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
* create a <code>java.util.TimeZone</code> with a custom timezone id
* using the <code>this.getTimezone()</code>.</li>
* <li>else use the <code>GregorianCalendar</code> default timezone value
* for the host is defined as specified by
* <code>java.util.TimeZone.getDefault()</code>.</li></p>
*
* @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
*/
public XMLGregorianCalendarImpl(GregorianCalendar cal) {
int year = cal.get(Calendar.YEAR);
if (cal.get(Calendar.ERA) == GregorianCalendar.BC) {
year = -year;
}
this.setYear(year);
// Calendar.MONTH is zero based, XSD Date datatype's month field starts
// with JANUARY as 1.
this.setMonth(cal.get(Calendar.MONTH) + 1);
this.setDay(cal.get(Calendar.DAY_OF_MONTH));
this.setTime(
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
cal.get(Calendar.SECOND),
cal.get(Calendar.MILLISECOND));
// Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds.
int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
this.setTimezone(offsetInMinutes);
}
/**
* Returns the string representation of this {@code FileTime}. The string
* is returned in the <a
* href="http://www.w3.org/TR/NOTE-datetime">ISO 8601</a> format:
* <pre>
* YYYY-MM-DDThh:mm:ss[.s+]Z
* </pre>
* where "{@code [.s+]}" represents a dot followed by one of more digits
* for the decimal fraction of a second. It is only present when the decimal
* fraction of a second is not zero. For example, {@code
* FileTime.fromMillis(1234567890000L).toString()} yields {@code
* "2009-02-13T23:31:30Z"}, and {@code FileTime.fromMillis(1234567890123L).toString()}
* yields {@code "2009-02-13T23:31:30.123Z"}.
*
* <p> A {@code FileTime} is primarily intended to represent the value of a
* file's time stamp. Where used to represent <i>extreme values</i>, where
* the year is less than "{@code 0001}" or greater than "{@code 9999}" then
* this method deviates from ISO 8601 in the same manner as the
* <a href="http://www.w3.org/TR/xmlschema-2/#deviantformats">XML Schema
* language</a>. That is, the year may be expanded to more than four digits
* and may be negative-signed. If more than four digits then leading zeros
* are not present. The year before "{@code 0001}" is "{@code -0001}".
*
* @return the string representation of this file time
*/
@Override
public String toString() {
String v = valueAsString;
if (v == null) {
// overflow saturates to Long.MIN_VALUE or Long.MAX_VALUE so this
// limits the range:
// [-292275056-05-16T16:47:04.192Z,292278994-08-17T07:12:55.807Z]
long ms = toMillis();
// nothing to do when seconds/minutes/hours/days
String fractionAsString = "";
if (unit.compareTo(TimeUnit.SECONDS) < 0) {
long fraction = asDaysAndNanos().fractionOfSecondInNanos();
if (fraction != 0L) {
// fraction must be positive
if (fraction < 0L) {
final long MAX_FRACTION_PLUS_1 = 1000L * 1000L * 1000L;
fraction += MAX_FRACTION_PLUS_1;
if (ms != Long.MIN_VALUE) ms--;
}
// convert to String, adding leading zeros as required and
// stripping any trailing zeros
String s = Long.toString(fraction);
int len = s.length();
int width = 9 - len;
StringBuilder sb = new StringBuilder(".");
while (width-- > 0) {
sb.append('0');
}
if (s.charAt(len-1) == '0') {
// drop trailing zeros
len--;
while (s.charAt(len-1) == '0')
len--;
sb.append(s.substring(0, len));
} else {
sb.append(s);
}
fractionAsString = sb.toString();
}
}
// create calendar to use with formatter.
GregorianCalendar cal =
new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT);
if (value < 0L)
cal.setGregorianChange(new Date(Long.MIN_VALUE));
cal.setTimeInMillis(ms);
// years are negative before common era
String sign = (cal.get(Calendar.ERA) == GregorianCalendar.BC) ? "-" : "";
// [-]YYYY-MM-DDThh:mm:ss[.s]Z
v = new Formatter(Locale.ROOT)
.format("%s%tFT%tR:%tS%sZ", sign, cal, cal, cal, fractionAsString)
.toString();
valueAsString = v;
}
return v;
}
/**
* <p>Convert a <code>java.util.GregorianCalendar</code> to XML Schema 1.0
* representation.</p>
*
* <table border="2" rules="all" cellpadding="2">
* <thead>
* <tr>
* <th align="center" colspan="2">
* Field by Field Conversion from
* <code>java.util.GregorianCalendar</code> to this class
* </th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <th><code>javax.xml.datatype.XMLGregorianCalendar</code> field</th>
* <th><code>java.util.GregorianCalendar</code> field</th>
* </tr>
* <tr>
* <th>{@link #setYear(int)}</th>
* <th><code>ERA == GregorianCalendar.BC ? -YEAR : YEAR</code></th>
* </tr>
* <tr>
* <th>{@link #setMonth(int)}</th>
* <th><code>MONTH + 1</code></th>
* </tr>
* <tr>
* <th>{@link #setDay(int)}</th>
* <th><code>DAY_OF_MONTH</code></th>
* </tr>
* <tr>
* <th>{@link #setTime(int,int,int, BigDecimal)}</th>
* <th><code>HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND</code></th>
* </tr>
* <tr>
* <th>{@link #setTimezone(int)}<i>*</i></th>
* <th><code>(ZONE_OFFSET + DST_OFFSET) / (60*1000)</code><br/>
* <i>(in minutes)</i>
* </th>
* </tr>
* </tbody>
* </table>
* <p><i>*</i>conversion loss of information. It is not possible to represent
* a <code>java.util.GregorianCalendar</code> daylight savings timezone id in the
* XML Schema 1.0 date/time datatype representation.</p>
*
* <p>To compute the return value's <code>TimeZone</code> field,
* <ul>
* <li>when <code>this.getTimezone() != DatatypeConstants.FIELD_UNDEFINED</code>,
* create a <code>java.util.TimeZone</code> with a custom timezone id
* using the <code>this.getTimezone()</code>.</li>
* <li>else use the <code>GregorianCalendar</code> default timezone value
* for the host is defined as specified by
* <code>java.util.TimeZone.getDefault()</code>.</li></p>
*
* @param cal <code>java.util.GregorianCalendar</code> used to create <code>XMLGregorianCalendar</code>
*/
public XMLGregorianCalendarImpl(GregorianCalendar cal) {
int year = cal.get(Calendar.YEAR);
if (cal.get(Calendar.ERA) == GregorianCalendar.BC) {
year = -year;
}
this.setYear(year);
// Calendar.MONTH is zero based, XSD Date datatype's month field starts
// with JANUARY as 1.
this.setMonth(cal.get(Calendar.MONTH) + 1);
this.setDay(cal.get(Calendar.DAY_OF_MONTH));
this.setTime(
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
cal.get(Calendar.SECOND),
cal.get(Calendar.MILLISECOND));
// Calendar ZONE_OFFSET and DST_OFFSET fields are in milliseconds.
int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000);
this.setTimezone(offsetInMinutes);
}
/**
* computeEncodedDate extracts the year, month and date from
* a Calendar value and encodes them as
* year << 16 + month << 8 + date
* Use this function will help to remember to add 1 to month
* which is 0 based in the Calendar class
* @param cal the Calendar
* @return the encodedDate
*
* @exception StandardException if the value is out of the DB2 date range
*/
static int computeEncodedDate(Calendar cal) throws StandardException
{
if (cal.get(Calendar.ERA) == GregorianCalendar.BC)
throw StandardException.newException( SQLState.LANG_DATE_RANGE_EXCEPTION);
return computeEncodedDate(cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH) + 1,
cal.get(Calendar.DATE));
}