Constructor: |
public GDate(CharSequence string) {
// first trim XML whitespace
int len = string.length();
int start = 0;
while (len > 0 && isSpace(string.charAt(len - 1)))
len -= 1;
while (start < len && isSpace(string.charAt(start)))
start += 1;
// pick optional timezone off the end
if (len - start >= 1 && string.charAt(len - 1) == 'Z')
{
_bits |= HAS_TIMEZONE;
len -= 1;
}
else if (len - start >= 6)
timezone: {
int tzsign;
int tzhour;
int tzminute;
if (string.charAt(len - 3) != ':')
break timezone;
switch (string.charAt(len - 6))
{
case '-':
tzsign = -1; break;
case '+':
tzsign = 1; break;
default:
break timezone;
}
tzhour = twoDigit(string, len - 5);
tzminute = twoDigit(string, len - 2);
if (tzhour > 14)
throw new IllegalArgumentException("time zone hour must be two digits between -14 and +14");
if (tzminute > 59)
throw new IllegalArgumentException("time zone minute must be two digits between 00 and 59");
_bits |= HAS_TIMEZONE;
_tzsign = tzsign;
_tzh = tzhour;
_tzm = tzminute;
len -= 6;
}
// pick date fields off the beginning if it doesn't look like a time
if (start < len && (start + 2 >= len || string.charAt(start + 2) != ':'))
scandate:
{
// parse year sign
boolean negyear = false;
if (start < len && string.charAt(start) == '-')
{
negyear = true;
start += 1;
}
// scan year digits
int value = 0;
int digits = -start;
char ch;
boolean startsWithZero = start < len && digitVal(string.charAt(start))==0;
for (;;)
{
ch = start < len ? string.charAt(start) : '\0';
if (!isDigit(ch))
break;
if ( startsWithZero && start+digits >=4 )
throw new IllegalArgumentException("year value starting with zero must be 4 or less digits: " + string);
value = value * 10 + digitVal(ch);
start += 1;
}
digits += start;
if (digits > 9)
throw new IllegalArgumentException("year too long (up to 9 digits)");
else if (digits >= 4)
{
_bits |= HAS_YEAR;
_CY = negyear ? -value : value;
if (_CY == 0) throw new IllegalArgumentException("year must not be zero");
}
else if (digits > 0)
throw new IllegalArgumentException("year must be four digits (may pad with zeroes, e.g., 0560)");
if ( _CY > MAX_YEAR )
throw new IllegalArgumentException("year value not supported: too big, must be less than " + MAX_YEAR);
if ( _CY < MIN_YEAR )
throw new IllegalArgumentException("year values not supported: too small, must be bigger than " + MIN_YEAR);
// hyphen introduces a month
if (ch != '-')
{
if (negyear && !hasYear())
throw new IllegalArgumentException(); // a single minus
else
break scandate;
}
start += 1;
// two-digit month
if (len - start >= 2)
{
value = twoDigit(string, start);
if (value >= 1 && value < = 12)
{
_bits |= HAS_MONTH;
_M = value;
start += 2;
}
}
// hyphen introduces a day
ch = start < len ? string.charAt(start) : '\0';
if (ch != '-')
{
if (!hasMonth())
throw new IllegalArgumentException(); // minus after a year
else
break scandate;
}
start += 1;
// two-digit day
if (len - start >= 2)
{
value = twoDigit(string, start);
if (value >= 1 && value < = 31)
{
_bits |= HAS_DAY;
_D = value;
start += 2;
}
}
if (!hasDay())
{
// error in the original schema spec permits an extra '-' here
if (hasMonth() && !hasYear())
{
ch = start < len ? string.charAt(start) : '\0';
if (ch == '-')
{
start += 1;
break scandate;
}
}
throw new IllegalArgumentException(); // minus after a month
}
}
// time
if (start < len)
{
if (hasYear() || hasMonth() || hasDay())
{
if (string.charAt(start) != 'T')
throw new IllegalArgumentException("date and time must be separated by 'T'");
start += 1;
}
if (len < start + 8 || string.charAt(start + 2) != ':' || string.charAt(start + 5) != ':')
throw new IllegalArgumentException();
int h = twoDigit(string, start);
if (h > 24)
throw new IllegalArgumentException("hour must be between 00 and 23");
int m = twoDigit(string, start + 3);
if (m >= 60)
throw new IllegalArgumentException("minute must be between 00 and 59");
int s = twoDigit(string, start + 6);
if (s >= 60)
throw new IllegalArgumentException("second must be between 00 and 59");
start += 8;
BigDecimal fs = _zero;
if (start < len)
{
if (string.charAt(start) != '.')
throw new IllegalArgumentException();
if (start + 1 < len)
{
for (int i = start + 1; i < len; i++)
{
if (!isDigit(string.charAt(i)))
throw new IllegalArgumentException();
}
try
{
fs = new BigDecimal(string.subSequence(start, len).toString());
}
catch (Throwable e)
{
throw new IllegalArgumentException();
}
}
}
_bits |= HAS_TIME;
_h = h;
_m = m;
_s = s;
_fs = fs;
}
if ( hasTime() && _h == 24 )
{
if ( _m != 0 || _s != 0 || _fs.compareTo(_zero) != 0 )
throw new IllegalArgumentException("if hour is 24, minutes, seconds and fraction must be 0");
else
{ // normalize to next day if it has date or at least has day
if ( hasDate() )
{
GDateBuilder gdb = new GDateBuilder(_CY, _M, _D, _h, _m, _s, _fs, _tzsign, _tzh, _tzm);
gdb.normalize24h();
_D = gdb.getDay();
_M = gdb.getMonth();
_CY = gdb.getYear();
_h = 0;
}
else if ( hasDay() ) // if no date only days increment
{
_D++;
_h = 0;
}
}
}
if (!isValid())
throw new IllegalArgumentException("invalid date");
}
Constructs a GDate based on a lexical representation. |
public GDate(Date date) {
// requires some date math, so ctor lives on GDateBuilder
this(new GDateBuilder(date));
}
Constructs a GDate based on a java.util.Date.
The current offset of the default timezone is used as the timezone.
For example, if eastern daylight time is in effect at the given
date, the timezone on the east coast of the united states
translates to GMT-05:00 (EST) + 1:00 (DT offset) == GMT-04:00. |
public GDate(Calendar calendar) {
// we must scrape the "isSet" information out before accessing anything
boolean isSetYear = calendar.isSet(Calendar.YEAR);
boolean isSetEra = calendar.isSet(Calendar.ERA);
boolean isSetMonth = calendar.isSet(Calendar.MONTH);
boolean isSetDay = calendar.isSet(Calendar.DAY_OF_MONTH);
boolean isSetHourOfDay = calendar.isSet(Calendar.HOUR_OF_DAY);
boolean isSetHour = calendar.isSet(Calendar.HOUR);
boolean isSetAmPm = calendar.isSet(Calendar.AM_PM);
boolean isSetMinute = calendar.isSet(Calendar.MINUTE);
boolean isSetSecond = calendar.isSet(Calendar.SECOND);
boolean isSetMillis = calendar.isSet(Calendar.MILLISECOND);
boolean isSetZone = calendar.isSet(Calendar.ZONE_OFFSET);
boolean isSetDst = calendar.isSet(Calendar.DST_OFFSET);
if (isSetYear)
{
int y = calendar.get(Calendar.YEAR);
if (isSetEra && calendar instanceof GregorianCalendar)
if (calendar.get(Calendar.ERA) == GregorianCalendar.BC)
y = -y; //1 - y;
_bits |= HAS_YEAR;
_CY = y;
}
if (isSetMonth)
{
_bits |= HAS_MONTH;
_M = calendar.get(Calendar.MONTH) + 1; // !!note
}
if (isSetDay)
{
_bits |= HAS_DAY;
_D = calendar.get(Calendar.DAY_OF_MONTH);
}
boolean gotTime = false;
int h = 0;
int m = 0;
int s = 0;
BigDecimal fs = _zero;
if (isSetHourOfDay)
{
h = calendar.get(Calendar.HOUR_OF_DAY);
gotTime = true;
}
else if (isSetHour && isSetAmPm)
{
h = calendar.get(Calendar.HOUR) + calendar.get(Calendar.AM_PM) * 12;
gotTime = true;
}
if (isSetMinute)
{
m = calendar.get(Calendar.MINUTE);
gotTime = true;
}
if (isSetSecond)
{
s = calendar.get(Calendar.SECOND);
gotTime = true;
}
if (isSetMillis)
{
fs = BigDecimal.valueOf(calendar.get(Calendar.MILLISECOND), 3);
gotTime = true;
}
if (gotTime)
{
_bits |= HAS_TIME;
_h = h;
_m = m;
_s = s;
_fs = fs;
}
if (isSetZone)
{
int zoneOffsetInMilliseconds = calendar.get(Calendar.ZONE_OFFSET);
if (isSetDst)
zoneOffsetInMilliseconds += calendar.get(Calendar.DST_OFFSET);
_bits |= HAS_TIMEZONE;
if (zoneOffsetInMilliseconds == 0)
{
_tzsign = 0;
_tzh = 0;
_tzm = 0;
TimeZone zone = calendar.getTimeZone();
String id = zone.getID();
if (id != null && id.length() > 3) switch (id.charAt(3))
{
case '+': _tzsign = 1; break; // GMT+00:00
case '-': _tzsign = -1; break; // GMT-00:00
}
}
else
{
_tzsign = (zoneOffsetInMilliseconds < 0 ? -1 : +1);
zoneOffsetInMilliseconds = zoneOffsetInMilliseconds * _tzsign;
_tzh = zoneOffsetInMilliseconds / 3600000;
_tzm = (zoneOffsetInMilliseconds - _tzh * 3600000) / 60000;
}
}
}
Constructs a GDate based on a java.util.Calendar.
If the calendar does not have some fields set, the same absence
of information is reflected in the GDate. Note that
java.util.GregorianCalendar fills in all fields as soon as any
are fetched, so constructing a GDate with the same calendar object
twice may result in a different GDate because of a changed calendar.
Note that org.apache.xmlbeans.XmlCalendar is stable if you re-get a set field,
so it does not have the same problem. |
public GDate(GDateSpecification gdate) {
if (gdate.hasTimeZone())
{
_bits |= HAS_TIMEZONE;
_tzsign = gdate.getTimeZoneSign();
_tzh = gdate.getTimeZoneHour();
_tzm = gdate.getTimeZoneMinute();
}
if (gdate.hasTime())
{
_bits |= HAS_TIME;
_h = gdate.getHour();
_m = gdate.getMinute();
_s = gdate.getSecond();
_fs = gdate.getFraction();
}
if (gdate.hasDay())
{
_bits |= HAS_DAY;
_D = gdate.getDay();
}
if (gdate.hasMonth())
{
_bits |= HAS_MONTH;
_M = gdate.getMonth();
}
if (gdate.hasYear())
{
_bits |= HAS_YEAR;
_CY = gdate.getYear();
}
}
Constructs a GDate based on another GDateSpecification. |
public GDate(int year,
int month,
int day,
int hour,
int minute,
int second,
BigDecimal fraction) {
_bits = HAS_YEAR | HAS_MONTH | HAS_DAY | HAS_TIME;
_CY = year;
_M = month;
_D = day;
_h = hour;
_m = minute;
_s = second;
_fs = fraction == null ? _zero : fraction;
if (!isValid())
throw new IllegalArgumentException();
}
Constructs a GDate with the specified year, month, day,
hours, minutes, seconds, and optional fractional seconds, in
an unspecified timezone.
Note that by not specifying the timezone the GDate
becomes partially unordered with respect to times that
do have a specified timezone. |
public GDate(int year,
int month,
int day,
int hour,
int minute,
int second,
BigDecimal fraction,
int tzSign,
int tzHour,
int tzMinute) {
_bits = HAS_TIMEZONE | HAS_YEAR | HAS_MONTH | HAS_DAY | HAS_TIME;
_CY = year;
_M = month;
_D = day;
_h = hour;
_m = minute;
_s = second;
_fs = fraction == null ? _zero : fraction;
_tzsign = tzSign;
_tzh = tzHour;
_tzm = tzMinute;
if (!isValid())
throw new IllegalArgumentException();
}
Constructs an absolute GDate with the specified year,
month, day, hours, minutes, seconds, and optional fractional
seconds, and in the timezone specified.
If you wish to have a time or date that isn't in a specified timezone,
then use the constructor that does not include the timezone arguments. |
Method from org.apache.xmlbeans.GDate Detail: |
public GDate add(GDurationSpecification duration) {
GDateBuilder builder = new GDateBuilder(this);
builder.addGDuration(duration);
return builder.toGDate();
}
Adds a duration to this GDate, and returns a new GDate. |
public String canonicalString() {
ensureCanonicalString();
return _canonicalString;
}
The canonical string representation. Specific moments or
times-of-day in a specified timezone are normalized to
UTC time to produce a canonical string form for them.
Other recurring time specifications keep their timezone
information. |
public int compareToGDate(GDateSpecification datespec) {
return GDateBuilder.compareGDate(this, datespec);
}
Comparison to another GDate.
- Returns -1 if this < date. (less-than)
- Returns 0 if this == date. (equal)
- Returns 1 if this > date. (greater-than)
- Returns 2 if this <> date. (incomparable)
Two instances are incomparable if they have different amounts
of information. |
static final int digitVal(char ch) {
return (ch - '0');
}
|
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof GDate))
return false;
ensureCanonicalString();
return _canonicalString.equals(((GDate)obj).canonicalString());
}
GDate is an immutable class, and equality is computed based
on its canonical value. |
static String formatGDate(GDateSpecification spec) {
// We've used a char[] rather than a StringBuffer for a 4x speedup
// -YY(10)YY-MM-DDTHH:MM:SS.FFFFFF+ZH:ZM
// 1 + 10 + 3+ 3+ 3+ 3+ 3+1 + s + 3+ 3 = 33 + s
BigDecimal fs = spec.getFraction();
char[] message = new char[33 + (fs == null ? 0 : fs.scale())];
int i = 0;
if (spec.hasYear() || spec.hasMonth() || spec.hasDay())
{
dmy: {
if (spec.hasYear())
i = _padFourAppend(message, 0, spec.getYear());
else
message[i++] = '-';
if (!(spec.hasMonth() || spec.hasDay()))
break dmy;
message[i++] = '-';
if (spec.hasMonth())
i = _padTwoAppend(message, i, spec.getMonth());
if (!spec.hasDay())
break dmy;
message[i++] = '-';
i = _padTwoAppend(message, i, spec.getDay());
break dmy;
}
if (spec.hasTime())
message[i++] = 'T';
}
if (spec.hasTime())
{
i = _padTwoAppend(message, i, spec.getHour());
message[i++] = ':';
i = _padTwoAppend(message, i, spec.getMinute());
message[i++] = ':';
i = _padTwoAppend(message, i, spec.getSecond());
if (fs != _zero) // (optimization ~3%)
{
String frac = fs.toString();
int point = frac.indexOf('.');
if (point >= 0)
{
frac.getChars(point, frac.length(), message, i);
i += frac.length() - point;
}
}
}
if (spec.hasTimeZone())
{
if (spec.getTimeZoneSign() == 0)
{
message[i++] = 'Z';
}
else
{
message[i++] = spec.getTimeZoneSign() > 0 ? '+' : '-';
i = _padTwoAppend(message, i, spec.getTimeZoneHour());
message[i++] = ':';
i = _padTwoAppend(message, i, spec.getTimeZoneMinute());
}
}
// it would be nice to use (0, i, message) ctor instead
return new String(message, 0, i);
}
|
public int getBuiltinTypeCode() {
return GDateBuilder.btcForFlags(_bits);
}
|
public XmlCalendar getCalendar() {
return new XmlCalendar(this);
}
Retrieves the value of the current time as an XmlCalendar .
XmlCalendar is a subclass of java.util.GregorianCalendar
which is slightly customized to match XML schema date rules.
The returned XmlCalendar has only those time and date fields
set that are reflected in the GDate object. Because of the way the
java.util.Calendar contract works, any information in the isSet() vanishes
as soon as you view any unset field using get() methods.
This means that if it is important to understand which date fields
are set, you must call isSet() first before get(). |
public Date getDate() {
return GDateBuilder.dateForGDate(this);
}
Retrieves the value of the current time as a java.util.Date
instance. |
public final int getDay() {
return _D;
}
Gets the day-of-month. The first day of each month is 1. |
public int getFlags() {
return _bits;
}
Returns a combination of flags indicating the information
contained by this GDate. The five flags are
HAS_TIMEZONE, HAS_YEAR, HAS_MONTH, HAS_DAY, and HAS_TIME. |
public final BigDecimal getFraction() {
return _fs;
}
Gets the fraction-of-second. Range from 0 (inclusive) to 1 (exclusive). |
public final int getHour() {
return _h;
}
Gets the hour-of-day. Midnight is 0, and 11PM is 23. |
public int getJulianDate() {
return GDateBuilder.julianDateForGDate(this);
}
Returns the Julian date corresponding to this Gregorian date.
The Julian date (JD) is a continuous count of days from
1 January 4713 BC. |
public int getMillisecond() {
if (_fs == null)
return 0;
return _fs.setScale(3, BigDecimal.ROUND_DOWN).unscaledValue().intValue();
}
Gets the rounded millisecond value. Range from 0 to 999 |
public final int getMinute() {
return _m;
}
Gets the minute-of-hour. Range from 0 to 59. |
public final int getMonth() {
return _M;
}
Gets the month-of-year. January is 1. |
public final int getSecond() {
return _s;
}
Gets the second-of-minute. Range from 0 to 59. |
public final int getTimeZoneHour() {
return _tzh;
}
Gets the time zone hour.
This is always positive: for the sign, look at
getTimeZoneSign(). |
public final int getTimeZoneMinute() {
return _tzm;
}
Gets the time zone minutes.
This is always positive: for the sign, look at
getTimeZoneSign(). |
public final int getTimeZoneSign() {
return _tzsign;
}
Gets the time zone sign. For time zones east of GMT,
this is positive; for time zones west, this is negative. |
public final int getYear() {
return _CY;
}
Gets the year. Should be a four-digit year specification. |
public final boolean hasDate() {
return ((_bits & (HAS_DAY | HAS_MONTH | HAS_YEAR)) == (HAS_DAY | HAS_MONTH | HAS_YEAR));
}
True if this date/time specification specifies a full date (year, month, day) |
public final boolean hasDay() {
return ((_bits & HAS_DAY) != 0);
}
True if this date/time specification specifies a day-of-month. |
public final boolean hasMonth() {
return ((_bits & HAS_MONTH) != 0);
}
True if this date/time specification specifies a month-of-year. |
public final boolean hasTime() {
return ((_bits & HAS_TIME) != 0);
}
True if this date/time specification specifies a time-of-day. |
public final boolean hasTimeZone() {
return ((_bits & HAS_TIMEZONE) != 0);
}
True if this date/time specification specifies a timezone. |
public final boolean hasYear() {
return ((_bits & HAS_YEAR) != 0);
}
True if this date/time specification specifies a year. |
public int hashCode() {
ensureCanonicalString();
return _canonicalString.hashCode();
}
Returns a hash code for this GDate. |
static final boolean isDigit(char ch) {
return ((char)(ch - '0') < = '9' - '0'); // char is unsigned
}
|
public final boolean isImmutable() {
return true;
}
Returns true: all GDate instances are immutable. |
static final boolean isSpace(char ch) {
switch (ch)
{
case ' ':
case '\t':
case '\r':
case '\n':
return true;
default:
return false;
}
}
|
public boolean isValid() {
return GDateBuilder.isValidGDate(this);
}
True if this GDate corresponds to a valid gregorian date value
in XML schema. |
public GDate subtract(GDurationSpecification duration) {
GDateBuilder builder = new GDateBuilder(this);
builder.subtractGDuration(duration);
return builder.toGDate();
}
Adds a duration to this GDate, and returns a new GDate. |
static final TimeZone timeZoneForGDate(GDateSpecification date) {
// use a cached timezone if integral; otherwise make a new one.
if (!date.hasTimeZone())
return TimeZone.getDefault();
if (date.getTimeZoneSign() == 0)
return GMTZONE;
if (date.getTimeZoneMinute() == 0 && date.getTimeZoneHour() < = 14 && date.getTimeZoneHour() >= 0)
return date.getTimeZoneSign() < 0 ? MINUSZONE[date.getTimeZoneHour()] : PLUSZONE[date.getTimeZoneHour()];
char[] zb = new char[9];
zb[0] = 'G';
zb[1] = 'M';
zb[2] = 'T';
zb[3] = (date.getTimeZoneSign() < 0) ? '-' : '+';
GDate._padTwoAppend(zb, 4, date.getTimeZoneHour());
zb[6] = ':';
GDate._padTwoAppend(zb, 7, date.getTimeZoneMinute());
return TimeZone.getTimeZone(new String(zb));
}
|
public String toString() {
if (_string == null)
_string = formatGDate(this);
return _string;
}
The natural string representation. This represents the information
that is available, including timezone. For types that correspond
to defined schema types (schemaBuiltinTypeCode() > 0),
this provides the natural lexical representation.
When both time and timezone are specified, this string is not
the canonical representation unless the timezone is UTC (Z)
(since the same moment in time can be expressed in different
timezones). To get a canonical string, use the canonicalString()
method. |