org.apache.xmlbeans.XmlCalendar Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.document.library.opener.onedrive.web
Show all versions of com.liferay.document.library.opener.onedrive.web
Liferay Document Library Opener OneDrive Web
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans;
import java.util.GregorianCalendar;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.math.BigDecimal;
/**
* An XML Schema compatible subclass of {@link java.util.GregorianCalendar GregorianCalendar}.
* XmlCalendar modifies several key details in the behavior of
* GregorianCalendar to make it more useful when dealing with XML dates.
*
* It is easy to convert between XmlCalendar and {@link GDate}, or to
* parse or emit an XmlCalendar using a standard XML Schema
* lexical representation.
*
* -
* To match XML Schema dates, this XmlCalendar is a fully proleptic
* Gregorian calendar by default, which means that Gregorian calendar
* rules are applied backwards in time as if they had always been in
* effect, actual historical circumstances concerning the observance
* of the 1582 decree of Pope Gregory XIII notwithstanding.
*
* -
* In order to better support partially-specified dates for XML Schema,
* this implementation provides a stable get(field) method
* that does not modify the instance if you are acessing a field right
* after it was explicitly set: a set followed by a get will always
* return the same thing and will not fill in any other fields. However,
* if you get a field that was not explicitly set, then all the fields
* are still automatically filled and normalized for you, just like a
* regular GregorianCalendar. If you wish to force the completion and
* defaulting of all the fields (without hunting to get one that happens
* to be unset), you can always do so by calling getTime().
*
* -
* When a year is unspecified and needs to be filled in automatically
* (for example when using a .get or .getTime method as discussed above),
* the year is defaulted to year 0 (also known as 1 BC). This is different
* from {@link GregorianCalendar}, which chooses 1970. The reason 0 is preferable
* is that it is a leap year and so it permits the date --2-29 to be specified
* stably. A different default year can be chosen via the static method
* {@link #setDefaultYear(int) XmlCalendar.setDefaultYear()}, or by setting the
* system property "user.defaultyear". If you do change this value, you should
* pick another leap year such as 2000 and avoid non-leap years such as 1900.
*
* -
* When constructing an XmlCalendar from an XML Schema
* formatted date or time string or GDate object, the timezone
* for the calendar is taken from the string if it is present, or
* taken to be {@link java.util.TimeZone#getDefault() TimeZone.getDefault()} if not.
*
* For example, the XML timezone "Z" is translated to "GMT";
* the XML timezone "+05:00" is translated to "GMT+05:00".
*
*
* -
* Finally, this implementation provides a String constructor and a
* toString() method that comply with the XML Schema conventions
* for formatting a date. If only a subset of fields have been
* explicitly set, toString() produces a string with the proper subset
* of information.
*
*
*/
public class XmlCalendar extends GregorianCalendar
{
/**
* Constructs an XmlCalendar for a standard XML
* schema formatted date string.
*
* The parser accepts any of the following formats:
*
* YYYY-MM-DDThh:mm:ss - dateTime
* YYYY-MM-DD - date
* hh:mm:ss - time
* YYYY - gYear
* --MM - gMonth
* ---DD - gDay
*
* The parser actually accepts all 16 combinations of subsets of
* fields (Y, M, D, T) using the same scheme, even for combinations
* that are not defined as types in the schema spec, such as
* year, day, and time:
*
* YYYY--DDThh:mm:ss - [everything but month specified]
*
* In the string, each field must be padded to its full width, for
* example, January must be --01, not just --1.
*
* In particular, a year must be padded to at least four digits, so
* "98" is not a valid year, although "1998" and "0098" are both valid
* years, unambiguously 19 centuries separated from each other. A year
* may also be preceded by a minus symbol: -0001 is 1 BC and -0002 is
* 2 BC.
*
* Finally a timezone is always allowed (yet optional) at the end.
* Timezones must be either "Z" (UTC, which we translate to GMT),
* or simple offsets from UTC in the range "-14:00" to "+14:00",
* for example: "14:30:00-05:00" specifies 2:30 PM in the
* afternoon at UTC-05:00, which is the same as EST.
*
* If a timezone is not specified, the default TimeZone is used.
*/
public XmlCalendar(String xmlSchemaDateString)
{
this(new GDate(xmlSchemaDateString)); // use GDate to parse
}
/**
* Constructs an XmlCalendar from a GDate.
*
* If the instance is not completed, you can round-trip to an
* equivalent GDate by writing "new GDate(new XmlCalendar(gdate))".
* However, if you access any of the unset fields of the calendar, all
* the fields will be automatically filled in, so partial dates
* without timezones or other fields will not round-trip after access.
*/
public XmlCalendar(GDateSpecification date)
{
this(GDate.timeZoneForGDate(date), date);
}
private XmlCalendar(TimeZone tz, GDateSpecification date)
{
super(tz);
setGregorianChange(_beginningOfTime); // proleptic
clear();
if (date.hasYear())
{
int y = date.getYear(); // is never 0
if (y > 0)
{
set(Calendar.ERA, GregorianCalendar.AD);
}
else // y < 0
{
set(Calendar.ERA, GregorianCalendar.BC);
//y = 1 - y;
y = -y; // no need to add 1
}
set(Calendar.YEAR, y);
}
if (date.hasMonth())
set(Calendar.MONTH, date.getMonth() - 1); // note!!
if (date.hasDay())
set(Calendar.DAY_OF_MONTH, date.getDay());
if (date.hasTime())
{
set(Calendar.HOUR_OF_DAY, date.getHour());
set(Calendar.MINUTE, date.getMinute());
set(Calendar.SECOND, date.getSecond());
if (date.getFraction().scale() > 0)
set(Calendar.MILLISECOND, date.getMillisecond());
}
if (date.hasTimeZone())
{
set(Calendar.ZONE_OFFSET, date.getTimeZoneSign() * 1000 * 60 * (date.getTimeZoneHour() * 60 + date.getTimeZoneMinute()));
set(Calendar.DST_OFFSET, 0); // note!! if we don't do this, then GregorianCalendar will pick up DST from the time zone
}
}
/**
* Constructs an XmlCalendar from a Date.
*
* The default TimeZone is used for computing the various fields.
*/
public XmlCalendar(Date date)
{
this(TimeZone.getDefault(), new GDate(date));
complete();
}
/**
* Constructs an XmlCalendar with the specified year, month, day,
* hours, minutes, seconds, and optional fractional seconds, in
* the default timezone.
*/
public XmlCalendar(
int year,
int month,
int day,
int hour,
int minute,
int second,
BigDecimal fraction)
{
this(TimeZone.getDefault(), new GDate(year, month, day, hour, minute, second, fraction));
}
/**
* Constructs an XmlCalendar with the specified year, month, day,
* hours, minutes, seconds, and optional fractional seconds, in
* the specified timezone.
*/
public XmlCalendar(
int year,
int month,
int day,
int hour,
int minute,
int second,
BigDecimal fraction,
int tzSign,
int tzHour,
int tzMinute)
{
this(new GDate(year, month, day, hour, minute, second, fraction, tzSign, tzHour, tzMinute));
}
/**
* Gets the value for a given time field.
*
* Unlike the GregorianCalendar implementation, the get() does not
* force a complete of all fields. If you wish to force a completion
* of all the fields, call getTime() first.
*/
public int get(int field)
{
if (!isSet(field) || isTimeSet)
return super.get(field); // forces a complete
else
return internalGet(field); // does not force a complete.
}
/**
* Constructs an empty instance with no fields set.
*/
public XmlCalendar()
{
setGregorianChange(_beginningOfTime); // proleptic
clear();
}
private static int defaultYear = Integer.MIN_VALUE;
private static final int DEFAULT_DEFAULT_YEAR = 0;
/**
* Returns the default year that is used when no year is specified.
*/
public static int getDefaultYear()
{
if (defaultYear == Integer.MIN_VALUE)
{
try
{
String yearstring = SystemProperties.getProperty("user.defaultyear");
if (yearstring != null)
defaultYear = Integer.parseInt(yearstring);
else
defaultYear = DEFAULT_DEFAULT_YEAR;
}
catch (Throwable t)
{
defaultYear = DEFAULT_DEFAULT_YEAR;
}
}
return defaultYear;
}
/**
* Sets the default year to be used when no year is specified.
*/
public static void setDefaultYear(int year)
{
defaultYear = year;
}
/**
* Overrides GregorianCalendar.computeTime to apply a different
* default year. (It must be a leap year.)
*/
protected void computeTime()
{
boolean unsetYear = !isSet(YEAR);
if (unsetYear)
set(YEAR, getDefaultYear());
try
{
super.computeTime();
}
finally
{
if (unsetYear)
clear(YEAR);
}
}
private static Date _beginningOfTime = new Date(Long.MIN_VALUE);
/**
* Prints the XmlCalendar using a standard XML Schema
* format, as described in XmlCalendar(String s).
*/
public String toString()
{
return (new GDate(this)).toString(); // use GDate to print
}
}