Java tutorial
/** * Copyright (C) 2014-2015 Philip Helger (www.helger.com) * philip[at]helger[dot]com * * 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 com.helger.datetime.xml; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import javax.annotation.CheckForSigned; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeConstants; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.joda.time.LocalTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.helger.commons.CGlobal; import com.helger.commons.annotations.PresentForCodeCoverage; import com.helger.commons.exceptions.InitializationException; import com.helger.datetime.PDTFactory; /** * Utility class for XML date/time data type handling. * * @author Philip Helger */ @Immutable public final class PDTXMLConverter { private static final Logger s_aLogger = LoggerFactory.getLogger(PDTXMLConverter.class); private static final DatatypeFactory s_aDTFactory; static { try { // required for the Gregorian calendar s_aDTFactory = DatatypeFactory.newInstance(); } catch (final DatatypeConfigurationException ex) { throw new InitializationException("Failed to init DataTypeFactory", ex); } } @PresentForCodeCoverage private static final PDTXMLConverter s_aInstance = new PDTXMLConverter(); private PDTXMLConverter() { } /** * Get the timezone offset to UTC of the passed calendar in minutes to be used * in {@link XMLGregorianCalendar}. * * @param aCalendar * The calendar to use. May not be <code>null</code>. * @return 0 for no offset to UTC, the minutes otherwise. Usually in 60minutes * steps :) */ public static int getTimezoneOffsetInMinutes(@Nonnull final Calendar aCalendar) { final int nOffsetInMillis = aCalendar.getTimeZone().getOffset(aCalendar.getTimeInMillis()); return nOffsetInMillis / (int) CGlobal.MILLISECONDS_PER_MINUTE; } /** * Get the passed date as {@link GregorianCalendar}. * * @param aDate * The source date. May be <code>null</code>. * @return Never <code>null</code>. */ @Nonnull public static GregorianCalendar getCalendar(@Nonnull final Date aDate) { final GregorianCalendar aCalendar = new GregorianCalendar(); aCalendar.setTime(aDate); return aCalendar; } /** * Get the passed milli seconds as {@link GregorianCalendar}. * * @param nMillis * Milli seconds since 1.1.1970 * @return Never <code>null</code>. */ @Nonnull public static GregorianCalendar getCalendar(final long nMillis) { final GregorianCalendar aCalendar = new GregorianCalendar(); aCalendar.setTimeInMillis(nMillis); return aCalendar; } /** * @return A new XML calendar instance, with all fields uninitialized. Never * <code>null</code>. */ @Nonnull public static XMLGregorianCalendar createNewCalendar() { return s_aDTFactory.newXMLGregorianCalendar(); } /** * Get the current date as {@link XMLGregorianCalendar}. * * @return Never <code>null</code>. */ @Nonnull public static XMLGregorianCalendar getXMLCalendarDateNow() { return getXMLCalendarDate(PDTFactory.getCurrentLocalDate()); } /** * Get the passed object as {@link XMLGregorianCalendar} date (without a * time). * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendarDate(@Nullable final LocalDate aBase) { return aBase == null ? null : s_aDTFactory.newXMLGregorianCalendarDate(aBase.getYear(), aBase.getMonthOfYear(), aBase.getDayOfMonth(), DatatypeConstants.FIELD_UNDEFINED); } /** * Get the passed object as {@link XMLGregorianCalendar} date (without a * time). * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendarDate(@Nullable final Date aBase) { return aBase == null ? null : getXMLCalendarDate(getCalendar(aBase)); } /** * Get the passed object as {@link XMLGregorianCalendar} date (without a * time). * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendarDate(@Nullable final GregorianCalendar aBase) { return aBase == null ? null : s_aDTFactory.newXMLGregorianCalendarDate(aBase.get(Calendar.YEAR), aBase.get(Calendar.MONTH), aBase.get(Calendar.DAY_OF_MONTH), getTimezoneOffsetInMinutes(aBase)); } /** * Get the passed object as {@link XMLGregorianCalendar} date (without a * time). * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendarDate(@Nullable final XMLGregorianCalendar aBase) { return aBase == null ? null : s_aDTFactory.newXMLGregorianCalendarDate(aBase.getYear(), aBase.getMonth(), aBase.getDay(), aBase.getTimezone() == 0 ? DatatypeConstants.FIELD_UNDEFINED : aBase.getTimezone()); } /** * <p> * Create a Java representation of XML Schema builtin datatype * <code>date</code> or <code>g*</code>. * </p> * <p> * For example, an instance of <code>gYear</code> can be created invoking this * factory with <code>month</code> and <code>day</code> parameters set to * {@link DatatypeConstants#FIELD_UNDEFINED}. * </p> * <p> * A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is * not set. * </p> * * @param nYear * Year to be created. * @param nMonth * Month to be created. * @param nDay * Day to be created. * @return <code>XMLGregorianCalendar</code> created from parameter values. * @see DatatypeConstants#FIELD_UNDEFINED * @throws IllegalArgumentException * If any individual parameter's value is outside the maximum value * constraint for the field as determined by the Date/Time Data * Mapping table in {@link XMLGregorianCalendar} or if the composite * values constitute an invalid <code>XMLGregorianCalendar</code> * instance as determined by {@link XMLGregorianCalendar#isValid()}. */ @Nonnull public static XMLGregorianCalendar getXMLCalendarDate(final int nYear, final int nMonth, final int nDay) { return getXMLCalendarDate(nYear, nMonth, nDay, DatatypeConstants.FIELD_UNDEFINED); } /** * <p> * Create a Java representation of XML Schema builtin datatype * <code>date</code> or <code>g*</code>. * </p> * <p> * For example, an instance of <code>gYear</code> can be created invoking this * factory with <code>month</code> and <code>day</code> parameters set to * {@link DatatypeConstants#FIELD_UNDEFINED}. * </p> * <p> * A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is * not set. * </p> * * @param nYear * Year to be created. * @param nMonth * Month to be created. * @param nDay * Day to be created. * @param nTimezone * Offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} * indicates optional field is not set. * @return <code>XMLGregorianCalendar</code> created from parameter values. * @see DatatypeConstants#FIELD_UNDEFINED * @throws IllegalArgumentException * If any individual parameter's value is outside the maximum value * constraint for the field as determined by the Date/Time Data * Mapping table in {@link XMLGregorianCalendar} or if the composite * values constitute an invalid <code>XMLGregorianCalendar</code> * instance as determined by {@link XMLGregorianCalendar#isValid()}. */ @Nonnull public static XMLGregorianCalendar getXMLCalendarDate(final int nYear, final int nMonth, final int nDay, final int nTimezone) { return s_aDTFactory.newXMLGregorianCalendarDate(nYear, nMonth, nDay, nTimezone); } /** * Get the current time as {@link XMLGregorianCalendar}. * * @return Never <code>null</code>. */ @Nonnull public static XMLGregorianCalendar getXMLCalendarTimeNow() { return getXMLCalendarTime(PDTFactory.getCurrentLocalTime()); } /** * Get the passed object as {@link XMLGregorianCalendar} time (without a * date). * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendarTime(@Nullable final LocalTime aBase) { return aBase == null ? null : s_aDTFactory.newXMLGregorianCalendarTime(aBase.getHourOfDay(), aBase.getMinuteOfHour(), aBase.getSecondOfMinute(), aBase.getMillisOfSecond(), DatatypeConstants.FIELD_UNDEFINED); } /** * Get the passed object as {@link XMLGregorianCalendar} time (without a * date). * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendarTime(@Nullable final Date aBase) { return aBase == null ? null : getXMLCalendarTime(getCalendar(aBase)); } /** * Get the passed object as {@link XMLGregorianCalendar} time (without a * date). * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendarTime(@Nullable final GregorianCalendar aBase) { return aBase == null ? null : s_aDTFactory.newXMLGregorianCalendarTime(aBase.get(Calendar.HOUR_OF_DAY), aBase.get(Calendar.MINUTE), aBase.get(Calendar.SECOND), aBase.get(Calendar.MILLISECOND), getTimezoneOffsetInMinutes(aBase)); } /** * Get the passed object as {@link XMLGregorianCalendar} time (without a * date). * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendarTime(@Nullable final XMLGregorianCalendar aBase) { return aBase == null ? null : s_aDTFactory.newXMLGregorianCalendarTime(aBase.getHour(), aBase.getMinute(), aBase.getSecond(), aBase.getMillisecond(), aBase.getTimezone()); } /** * <p> * Create a Java representation of XML Schema builtin datatype * <code>date</code> or <code>g*</code>. * </p> * <p> * For example, an instance of <code>gYear</code> can be created invoking this * factory with <code>month</code> and <code>day</code> parameters set to * {@link DatatypeConstants#FIELD_UNDEFINED}. * </p> * <p> * A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is * not set. * </p> * * @param nHour * Hour to be created. * @param nMinute * Minute to be created. * @param nSecond * Second to be created. * @param nMilliSecond * Milli second to be created. * @return <code>XMLGregorianCalendar</code> created from parameter values. * @see DatatypeConstants#FIELD_UNDEFINED * @throws IllegalArgumentException * If any individual parameter's value is outside the maximum value * constraint for the field as determined by the Date/Time Data * Mapping table in {@link XMLGregorianCalendar} or if the composite * values constitute an invalid <code>XMLGregorianCalendar</code> * instance as determined by {@link XMLGregorianCalendar#isValid()}. */ @Nonnull public static XMLGregorianCalendar getXMLCalendarTime(final int nHour, final int nMinute, final int nSecond, final int nMilliSecond) { return getXMLCalendarTime(nHour, nMinute, nSecond, nMilliSecond, DatatypeConstants.FIELD_UNDEFINED); } /** * <p> * Create a Java representation of XML Schema builtin datatype * <code>date</code> or <code>g*</code>. * </p> * <p> * For example, an instance of <code>gYear</code> can be created invoking this * factory with <code>month</code> and <code>day</code> parameters set to * {@link DatatypeConstants#FIELD_UNDEFINED}. * </p> * <p> * A {@link DatatypeConstants#FIELD_UNDEFINED} value indicates that field is * not set. * </p> * * @param nHour * Hour to be created. * @param nMinute * Minute to be created. * @param nSecond * Second to be created. * @param nMilliSecond * Milli second to be created. * @param nTimezone * Offset in minutes. {@link DatatypeConstants#FIELD_UNDEFINED} * indicates optional field is not set. * @return <code>XMLGregorianCalendar</code> created from parameter values. * @see DatatypeConstants#FIELD_UNDEFINED * @throws IllegalArgumentException * If any individual parameter's value is outside the maximum value * constraint for the field as determined by the Date/Time Data * Mapping table in {@link XMLGregorianCalendar} or if the composite * values constitute an invalid <code>XMLGregorianCalendar</code> * instance as determined by {@link XMLGregorianCalendar#isValid()}. */ @Nonnull public static XMLGregorianCalendar getXMLCalendarTime(final int nHour, final int nMinute, final int nSecond, final int nMilliSecond, final int nTimezone) { return s_aDTFactory.newXMLGregorianCalendarTime(nHour, nMinute, nSecond, nMilliSecond, nTimezone); } /** * Get the current date and time as {@link XMLGregorianCalendar} in the * default time zone. * * @return Never <code>null</code>. */ @Nonnull public static XMLGregorianCalendar getXMLCalendarNow() { return getXMLCalendar(PDTFactory.getCurrentDateTime()); } /** * Get the current date and time as {@link XMLGregorianCalendar} in UTC. * * @return Never <code>null</code>. */ @Nonnull public static XMLGregorianCalendar getXMLCalendarNowUTC() { return getXMLCalendar(PDTFactory.getCurrentDateTimeUTC()); } /** * Get the passed object as {@link XMLGregorianCalendar} with date and time. * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendar(@Nullable final LocalDateTime aBase) { return aBase == null ? null : s_aDTFactory.newXMLGregorianCalendar(aBase.getYear(), aBase.getMonthOfYear(), aBase.getDayOfMonth(), aBase.getHourOfDay(), aBase.getMinuteOfHour(), aBase.getSecondOfMinute(), aBase.getMillisOfSecond(), DatatypeConstants.FIELD_UNDEFINED); } /** * Get the passed object as {@link XMLGregorianCalendar} with date and time. * * @param aBase * The source object. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendar(@Nullable final DateTime aBase) { return aBase == null ? null : s_aDTFactory.newXMLGregorianCalendar(aBase.toGregorianCalendar()); } /** * Get the passed {@link GregorianCalendar} as {@link XMLGregorianCalendar}. * * @param aCal * Source calendar. May be <code>null</code>. * @return <code>null</code> if the passed calendar is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendar(@Nullable final GregorianCalendar aCal) { return aCal == null ? null : s_aDTFactory.newXMLGregorianCalendar(aCal); } /** * Create a new {@link XMLGregorianCalendar} using separate objects for date * and time. * * @param aDate * Source date. May be <code>null</code>. * @param aTime * Source time. May be <code>null</code>. * @return <code>null</code> if the passed date and time are <code>null</code> * . */ @Nullable public static XMLGregorianCalendar getXMLCalendar(@Nullable final XMLGregorianCalendar aDate, @Nullable final XMLGregorianCalendar aTime) { if (aDate == null && aTime == null) return null; if (aTime == null) { // Date only return s_aDTFactory.newXMLGregorianCalendar(aDate.getYear(), aDate.getMonth(), aDate.getDay(), 0, 0, 0, 0, aDate.getTimezone()); } if (aDate == null) { // Time only return s_aDTFactory.newXMLGregorianCalendar(0, 0, 0, aTime.getHour(), aTime.getMinute(), aTime.getSecond(), aTime.getMillisecond(), aTime.getTimezone()); } if (aDate.getTimezone() != aTime.getTimezone()) s_aLogger.warn("Date and time have different timezones: " + aDate.getTimezone() + " vs. " + aTime.getTimezone()); return s_aDTFactory.newXMLGregorianCalendar(aDate.getYear(), aDate.getMonth(), aDate.getDay(), aTime.getHour(), aTime.getMinute(), aTime.getSecond(), aTime.getMillisecond(), aDate.getTimezone()); } /** * Get the passed milli seconds as {@link XMLGregorianCalendar}. * * @param nMillis * Milli seconds since 1.1.1970 * @return Never <code>null</code>. */ @Nonnull public static XMLGregorianCalendar getXMLCalendar(final long nMillis) { return s_aDTFactory.newXMLGregorianCalendar(getCalendar(nMillis)); } /** * Get the passed {@link Date} as {@link XMLGregorianCalendar}. * * @param aDate * Source date. May be <code>null</code>. * @return <code>null</code> if the passed date is <code>null</code>. */ @Nullable public static XMLGregorianCalendar getXMLCalendar(@Nullable final Date aDate) { return aDate == null ? null : s_aDTFactory.newXMLGregorianCalendar(getCalendar(aDate)); } /** * Convert the passed {@link XMLGregorianCalendar} to a * {@link GregorianCalendar}. * * @param aCal * Source calendar. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static GregorianCalendar getGregorianCalendar(@Nullable final XMLGregorianCalendar aCal) { return aCal == null ? null : aCal.toGregorianCalendar(aCal.getTimeZone(aCal.getTimezone()), null, null); } /** * Get the passed {@link XMLGregorianCalendar} as {@link LocalDate}. * * @param aCal * The source {@link XMLGregorianCalendar}. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static LocalDate getLocalDate(@Nullable final XMLGregorianCalendar aCal) { return aCal == null ? null : PDTFactory.createLocalDate(getGregorianCalendar(aCal)); } /** * Get the passed {@link XMLGregorianCalendar} as {@link LocalTime}. * * @param aCal * The source {@link XMLGregorianCalendar}. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static LocalTime getLocalTime(@Nullable final XMLGregorianCalendar aCal) { return aCal == null ? null : PDTFactory.createLocalTime(getGregorianCalendar(aCal)); } /** * Get the passed {@link XMLGregorianCalendar} as {@link LocalDateTime}. * * @param aCal * The source {@link XMLGregorianCalendar}. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static LocalDateTime getLocalDateTime(@Nullable final XMLGregorianCalendar aCal) { return aCal == null ? null : PDTFactory.createLocalDateTime(getGregorianCalendar(aCal)); } /** * Get the passed {@link XMLGregorianCalendar} as {@link DateTime}. * * @param aCal * The source {@link XMLGregorianCalendar}. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static DateTime getDateTime(@Nullable final XMLGregorianCalendar aCal) { return aCal == null ? null : PDTFactory.createDateTime(getGregorianCalendar(aCal)); } /** * Get the passed {@link XMLGregorianCalendar} as {@link Date}. * * @param aCal * The source {@link XMLGregorianCalendar}. May be <code>null</code>. * @return <code>null</code> if the parameter is <code>null</code>. */ @Nullable public static Date getDate(@Nullable final XMLGregorianCalendar aCal) { final GregorianCalendar aGregorianCalendar = getGregorianCalendar(aCal); return aGregorianCalendar == null ? null : aGregorianCalendar.getTime(); } /** * Get the passed {@link XMLGregorianCalendar} as milli seconds. * * @param aCal * The source {@link XMLGregorianCalendar}. May be <code>null</code>. * @return <code>{@link CGlobal#ILLEGAL_ULONG}</code> if the parameter is * <code>null</code>. */ @CheckForSigned public static long getMillis(@Nullable final XMLGregorianCalendar aCal) { final GregorianCalendar aGregorianCalendar = getGregorianCalendar(aCal); return aGregorianCalendar == null ? CGlobal.ILLEGAL_ULONG : aGregorianCalendar.getTimeInMillis(); } }