diff options
Diffstat (limited to 'src/main/java/at/gv/util/DateTimeUtil.java')
-rw-r--r-- | src/main/java/at/gv/util/DateTimeUtil.java | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/src/main/java/at/gv/util/DateTimeUtil.java b/src/main/java/at/gv/util/DateTimeUtil.java new file mode 100644 index 0000000..c301685 --- /dev/null +++ b/src/main/java/at/gv/util/DateTimeUtil.java @@ -0,0 +1,358 @@ +/* + * Copyright 2011 Federal Chancellery Austria and + * Graz University of Technology + * + * 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 at.gv.util; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.time.DateFormatUtils; +import org.apache.commons.lang.time.DateUtils; +import org.apache.commons.validator.GenericTypeValidator; +import org.apache.commons.validator.GenericValidator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a> + */ +public final class DateTimeUtil { + + private static Logger log = LoggerFactory.getLogger(DateTimeUtil.class); + public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; + public static final String DEFAULT_TIME_PATTERN = "HH:mm:ss"; + public static final String DEFAULT_TIMESTAMP_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + + public static int calcAge(Calendar dateOfBirth, Calendar now) { + int age = now.get(Calendar.YEAR) - dateOfBirth.get(Calendar.YEAR); + + int nowM = now.get(Calendar.MONTH); + int dobM = dateOfBirth.get(Calendar.MONTH); + int nowDOM = now.get(Calendar.DAY_OF_MONTH); + int dobDOM = dateOfBirth.get(Calendar.DAY_OF_MONTH); + + if ((nowM < dobM) || ((nowM == dobM) && (nowDOM < dobDOM))) { + age--; + } + + if (age < 0) { + throw new IllegalArgumentException( + "Calculated age results in negative value."); + } + return age; + } + + public static int calcAge(Calendar dateOfBirth) { + return calcAge(dateOfBirth, Calendar.getInstance()); + } + + public static int calcAge(Date dateOfBirth, Date now) { + Calendar dob = Calendar.getInstance(); + dob.setTime(dateOfBirth); + Calendar nowCal = Calendar.getInstance(); + nowCal.setTime(now); + return calcAge(dob, nowCal); + } + + public static int calcAge(Date dateOfBirth) { + return calcAge(dateOfBirth, new Date()); + } + + public static Date parseDate(String dateString, String datePattern, + String checkRegExpPattern) { + Date returnDate = null; + if (!MiscUtil.isEmpty(checkRegExpPattern)) { + if (!GenericValidator.matchRegexp(dateString, checkRegExpPattern)) { + return null; + } + } + if (MiscUtil.isEmpty(datePattern)) { + datePattern = DEFAULT_DATE_PATTERN; + } + if (GenericValidator.isDate(dateString, datePattern, false)) { + returnDate = GenericTypeValidator.formatDate(dateString, datePattern, + false); + } + return returnDate; + } + + public static Date mergeDateTime(Date date, Date time) { + if (MiscUtil.areAllNull(date, time)) { + throw new NullPointerException( + "Date and time must not be null at the same time."); + } + if (date == null) { + return time; + } + if (time == null) { + return date; + } + Calendar dateCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + dateCal.setTime(date); + Calendar timeCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + timeCal.setTime(time); + dateCal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY)); + dateCal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE)); + dateCal.set(Calendar.SECOND, timeCal.get(Calendar.SECOND)); + dateCal.set(Calendar.MILLISECOND, timeCal.get(Calendar.MILLISECOND)); + return dateCal.getTime(); + } + + public static Date parseDate(String dateString, String datePattern) { + return parseDate(dateString, datePattern, null); + } + + public static boolean equalsIgnoreMilliseconds(Date date1, Date date2) { + if (date1 == date2) { + return true; + } + if (date1 == null || date2 == null) { + return false; + } + return DateUtils.truncate(date1, Calendar.SECOND).equals( + DateUtils.truncate(date2, Calendar.SECOND)); + } + + public static Date parseDate(String dateString) { + return parseDate(dateString, null, null); + } + + public static Date parseTime(String timeString) { + return parseDate(timeString, DEFAULT_TIME_PATTERN, null); + } + + public static String formatXMLDateTimeString(Date date) { + if (date == null) { + return "null"; + } + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + cal.get(Calendar.MILLISECOND); + return DateFormatUtils.format(date, + cal.get(Calendar.MILLISECOND) == 0 ? "yyyy-MM-dd'T'HH:mm:ssZZ" + : "yyyy-MM-dd'T'HH:mm:ss.SSSZZ"); + } + + public static String formatUTCDateTimeString(Date date) { + if (date == null) { + return "null"; + } + return DateFormatUtils.formatUTC(date, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + } + + /** + * <p> + * Parses a datetime according to ISO 8601. + * </p> + * + * <p> + * Complete date plus hours and minutes<br/> + * YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00) + * </p> + * + * <p> + * Complete date plus hours, minutes and seconds<br/> + * YYYY-MM-DDThh:mm:ssTZD(eg 1997-07-16T19:20:30+01:00) + * </p> + * + * <p> + * Complete date plus hours, minutes, seconds and a decimal fraction of a + * second<br/> + * YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) + * </p> + * + * <p> + * where: + * </p> + * + * YYYY = four-digit year<br/> + * MM = two-digit month (01=January, etc.)<br/> + * DD = two-digit day of month (01 through 31)<br/> + * hh = two digits of hour (00 through 23) (am/pm NOT allowed)<br/> + * mm = two digits of minute (00 through 59)<br/> + * ss = two digits of second (00 through 59)<br/> + * s = one or more digits representing a decimal fraction of a second<br/> + * TZD = time zone designator (Z or +hh:mm or -hh:mm)<br/> + * + * @see <a + * href="http://www.w3.org/TR/NOTE-datetime">http://www.w3.org/TR/NOTE-datetime</a> + * @param dtText + * The date. + * @param noTimeZoneMeansUTC + * @return The parsed date. + * @throws ParseException + */ + public static Date parseXMLDateTimeString(String dtText, + boolean noTimeZoneMeansUTC) throws ParseException { + if (dtText == null) { + throw new NullPointerException("Provided date text must not be null."); + } + String[] parsePatterns = { "yyyy-MM-dd'T'HH:mm:ss", + "yyyy-MM-dd'T'HH:mm:ssZZ", "yyyy-MM-dd'T'HH:mm:ss.SSSZZ", + "yyyy-MM-dd'T'HH:mm:ss.SSS" }; + + // TODO: fix hack + + if (dtText.length() > 19) { + int li = dtText.lastIndexOf(":"); + if (li >= 19) { + dtText = new StringBuffer(dtText).deleteCharAt(li).toString(); + } + if (dtText.endsWith("Z")) { + dtText = StringUtils.chop(dtText) + "UTC"; + } + } else if (noTimeZoneMeansUTC) { + log.debug("UTC can be applied because no other offset has been provided."); + dtText += "UTC"; + } + return DateUtils.parseDate(dtText, parsePatterns); + } + + public static Date parseXMLDateTimeString(String dtText) + throws ParseException { + return parseXMLDateTimeString(dtText, false); + } + + public static String getDatePattern(String languageCode) { + String datePattern = DEFAULT_DATE_PATTERN; + if (languageCode != null) { + + if ("de".equalsIgnoreCase(languageCode)) { + datePattern = "dd.MM.yyyy"; + } else if ("en".equalsIgnoreCase(languageCode)) { + datePattern = "yyyy-MM-dd"; + } else { + log.warn("language code \"" + languageCode + + "\" notsupported; using failsafe pattern \"" + datePattern + "\""); + } + } + return datePattern; + } + + public static String formatDate(Date date, String datePattern) { + if (date == null) { + throw new NullPointerException("date must not be null"); + } + SimpleDateFormat sdf = new SimpleDateFormat(datePattern); + return sdf.format(date); + } + + public static String formatDate(Date date) { + return formatDate(date, getDatePattern(null)); + } + + public static String formatTime(Date time) { + return formatDate(time, DEFAULT_TIME_PATTERN); + } + + /** + * Checks if the given reference date ({@code pReference}) is valid according + * to the given date constraints {@code from} and {@code to}. The validation + * uses an intuitive approach including {@code from} and {@code to} ignoring + * the time component of the date objects:<br/> + * e.g. {@code from=2008-09-09}, {@code to=2010-09-08}<br/> + * valid reference dates: {@code 2008-09-09T00:00:00.000}, + * {@code 2008-09-09T12:34:50.000}, {@code 2010-09-08T00:00:00.000}, + * {@code 2010-09-08T23:59:59.999} + * + * @param from + * The date the validity period starts from (inclusive ignoring time + * component). + * @param to + * The date the validity period starts from (inclusive ignoring time + * component). + * @param pReference + * The date to be validated. + * @return {@code true} if the reference date is valid, {@code false} if not. + * @throws CheckException + * Thrown if the given reference date could not be validated. + * @author <a href="mailto:thomas.knall@iaik.tugraz.at">Thomas Knall</a> + */ + public static boolean validateDateConstraint(Date from, Date to, + Date pReference) { + if (pReference == null) { + throw new NullPointerException( + "Reference date needed to verify time constraints."); + } + Calendar fromCal = null; + if (from != null) { + fromCal = Calendar.getInstance(); + fromCal.setTime(from); + fromCal = removeTimeComponent(fromCal); + } + Calendar toCal = null; + if (to != null) { + toCal = Calendar.getInstance(); + toCal.setTime(to); + toCal = removeTimeComponent(toCal); + } + Calendar refCal = Calendar.getInstance(); + refCal.setTime(pReference); + refCal = removeTimeComponent(refCal); + + if ((fromCal != null && refCal.before(fromCal)) + || (toCal != null && refCal.after(toCal))) { + return false; + } + + return true; + } + + /** + * Removes the time component from a date object returning a new date + * instance. + * + * @param cal + * The original date object. + * @return A new date object (without time component). + * @author <a href="mailto:thomas.knall@egiz.gv.at">Thomas Knall</a> + */ + public static Date removeTimeComponent(Date date) { + Calendar cal = Calendar.getInstance(); + cal.setTime(date); + return removeTimeComponent(cal).getTime(); + } + + /** + * Removes the time component from a calendar object returning a new calendar + * instance. + * + * @param cal + * The original calendar object. + * @return A new calendar object (without time component). + * @author <a href="mailto:thomas.knall@egiz.gv.at">Thomas Knall</a> + */ + public static Calendar removeTimeComponent(Calendar cal) { + Calendar newCal = (Calendar) cal.clone(); + newCal.set(Calendar.HOUR_OF_DAY, 0); + newCal.set(Calendar.MINUTE, 0); + newCal.set(Calendar.SECOND, 0); + newCal.set(Calendar.MILLISECOND, 0); + return newCal; + } + + public static String formatTimeStamp(Date timestamp) { + return formatDate(timestamp, DEFAULT_TIMESTAMP_PATTERN); + } + + private DateTimeUtil() { + } + +} |