/* * Copyright 2013 * * @author Devin S. Olson (dolson@czarnowski.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 org.openntf.domino.utils; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import java.util.regex.Pattern; import lotus.domino.NotesException; import org.openntf.domino.DateTime; import org.openntf.domino.Item; /** * Date and Time handling utilities * * @author Devin S. Olson (dolson@czarnowski.com) * */ public enum Dates { DATEONLY(Strings.TIMESTAMP_DATEONLY, Strings.REGEX_DATEONLY, false), TIMEONLY(Strings.TIMESTAMP_TIMEONLY, Strings.REGEX_TIMEONLY, true), DAYMONTH_NAMES(Strings.TIMESTAMP_DAYMONTH_NAMES, Strings.REGEX_DAYMONTH_NAMES, true), DEFAULT(Strings.TIMESTAMP_DEFAULT, Strings.REGEX_DEFAULT, true), MEDDATE(Strings.TIMESTAMP_MEDDATE, Strings.REGEX_MEDDATE, false), MILITARY(Strings.TIMESTAMP_MILITARY, Strings.REGEX_MILITARY, true), SHORTDATE(Strings.TIMESTAMP_SHORTDATE, Strings.REGEX_SHORTDATE, false), SIMPLETIME(Strings.TIMESTAMP_SIMPLETIME, Strings.REGEX_SIMPLETIME, true); private final String _timestampFormat; private final String _regex; private final boolean _hasTimeComponent; private Pattern _pattern; private SimpleDateFormat _sdf; /** * Instance Constructor * * @param format * Format for the instance * @param regex * String used to generate the pattern */ private Dates(final String timestampFormat, final String regex, final boolean hastimecomponent) { this._timestampFormat = timestampFormat; this._regex = Strings.REGEX_BEGIN_NOCASE + regex + Strings.REGEX_END; this._pattern = Pattern.compile(Strings.REGEX_BEGIN_NOCASE + regex + Strings.REGEX_END); this._hasTimeComponent = hastimecomponent; } @Override public String toString() { return Dates.class.getName() + " " + this.name() + "{\"" + this.getInstanceTimestampFormat() + "\", " + this.getPattern() + "}"; } /** * Gets the format * * @return the format */ public String getInstanceTimestampFormat() { return this._timestampFormat; } /** * Gets the regex * * @return the regex */ public String getRegex() { return this._regex; } /** * Gets the Pattern object * * @return the Pattern */ public Pattern getPattern() { if (null == this._pattern) { this._pattern = Pattern.compile(this.getRegex()); } return this._pattern; } /** * Gets the SimpleDateFormat object * * @return the SimpleDateFormat */ public SimpleDateFormat getSimpleDateFormat() { if (null == this._sdf) { this._sdf = Dates.getSimpleDateFormat(this.getInstanceTimestampFormat()); this._sdf.setLenient(true); } return this._sdf; } /** * Gets the timestamp for the current moment. * * @return Timestamp for the current moment. */ public String getInstanceTimestamp() { return this.getInstanceTimestamp(null); } /** * Gets the timestamp for the specified date. * * @param date * moment for which to get the Timestamp. If null the current moment will be used. * * @return Timestamp for the specified date. */ public String getInstanceTimestamp(final Date date) { return this.getSimpleDateFormat().format((null == date) ? Dates.getDate() : date); } /** * Gets the timestamp for the specified date. * * @param object * Object from which a date can be determined. * * @return Timestamp for the specified date. */ public String getInstanceTimestamp(final Object object) { return this.getInstanceTimestamp(Dates.getDate(object)); } /** * Indicates if the formatter has a Time Component * * @return Flag indicating if the formatter has a time component. */ public boolean hasTimeComponent() { return this._hasTimeComponent; } /** * Determines if a given source string matches the Pattern. * * @param source * String for which to test for match against Pattern. * * @return Flag indicating if the source string matches the Pattern. */ public boolean matches(final String source) { return this.getPattern().matcher(source).matches(); } /** * Attempts to spawn a new Date by parsing a string. * * @param string * Value from which to attempt to construct a new Date object. * * @return new Date object constructed from the string. Null on error. */ public Date parseInstance(final String string) { try { if (Strings.isBlankString(string)) { throw new IllegalArgumentException("String to parse is null or blank"); } final SimpleDateFormat sdf = this.getSimpleDateFormat(); Date result = sdf.parse(string); if (null == result) { throw new ParseException("Unable to parse: " + string, 0); } if (this.hasTimeComponent() && (string.toUpperCase().indexOf("PM") > 0)) { Calendar cal = Dates.getCalendar(result); if (cal.get(Calendar.HOUR_OF_DAY) < 12) { // AM vs PM Parsing problem has occurred. Add 12 hours to the time. cal.add(Calendar.HOUR_OF_DAY, 12); result = cal.getTime(); } } return result; } catch (final Exception e) { DominoUtils.handleException(e); } return null; } /* * *************************************************** * *************************************************** * * PUBLIC STATIC methods * * *************************************************** * *************************************************** */ private static AtomicLong timeCodeSeed = new AtomicLong(System.currentTimeMillis() / 1000); /** * Generates a timecode. * * A timecode is a 6 character long alphanumeric (base36) String representing the current date and time. * * @return base36 String representing the current date and time * */ public static String getTimeCode() { try { // Long ntime = Math.abs(System.currentTimeMillis()); // nanoseconds is too accurate // if (ntime.equals(Long.MIN_VALUE)) { // ntime = Long.MAX_VALUE; // } // if we use currentTimeMillis() we generate a 8 digit string (till May 25, 2059 - then it is nine digits) // // Dec 7, 2014 = I3DN8QO0 // if we count only the last 6 digits, we get every millisecond a new value => nearly no collisions // but we have a repeat period of < 1 Month: // I5000000 = Jan 16, 2015 // I6000000 = Feb 11, 2015 // I7000000 = Mar 8, 2015 // // if we count only the first 6 digits, we get a new digit, every 1296 ms // now we use seconds (and an intelligent shift mechanism that handles subsequent calls intelligent long current = System.currentTimeMillis() / 1000; long newValue = 0; for (;;) { newValue = timeCodeSeed.incrementAndGet(); if (newValue >= current) break; if (timeCodeSeed.compareAndSet(current, newValue)) break; } final String result = Long.toString(newValue, 36).toUpperCase(Locale.ENGLISH); // generates a 8 digit string final int length = result.length(); if (length > 6) { return result.substring(6 - length); // cut off the first digits } else if (length < 6) { return Strings.getFilledString(6 - length, '0') + result; } return result; } catch (final Exception e) { DominoUtils.handleException(e); } return ""; } /** * Gets the timestamp for a specified date. * * @param date * date from which to generate a timestamp * * @param format * format for the timestamp. * * @return the timestamp for the specified date. */ public static String getTimestamp(final Object object, final String format) { try { if (Strings.isBlankString(format)) { return Dates.DEFAULT.getInstanceTimestamp(object); } final Dates tf = Dates.get(format); if (null != tf) { return tf.getInstanceTimestamp(object); } final Date date = (Dates.getDate(object)); final SimpleDateFormat sdf = Dates.getSimpleDateFormat(format); return sdf.format((null == date) ? Dates.getDate() : date); } catch (final Exception e) { DominoUtils.handleException(e); } return ""; } /** * Gets the timestamp for a specified date. * * @param date * date from which to generate a timestamp * * @return timestamp for the specified date */ public static String getTimestamp(final Date date) { return Dates.DEFAULT.getInstanceTimestamp(date); } /** * Gets the timestamp for the current date. * * @return timestamp for the current date */ public static String getTimestamp() { return Dates.DEFAULT.getInstanceTimestamp(); } /** * Gets the timestamp for the current date. * * @param format * format for the timestamp. * * @return the timestamp for the current date. */ public static String getTimestamp(final String format) { return Dates.getTimestamp(Dates.getDate(), format); } /** * Compares two Objects as Dates. Returns true if the first is after the second. * * Arguments are first compared by existence, then by value. * * @param object0 * First Object to compare. * * @param object1 * Second Object to compare. * * @return Flag indicating if the first object is after the second object. * */ public static boolean isAfter(final Object object0, final Object object1) { try { return (Dates.compareDates(object0, object1, false) > DominoUtils.EQUAL); } catch (final Exception e) { DominoUtils.handleException(e); } return false; } /** * Compares two Objects as Dates. Returns true if the first is before the second. * * Arguments are first compared by existence, then by value. * * @param object0 * First Object to compare. * * @param object1 * Second Object to compare. * * @return Flag indicating if the first object is before the second object. * */ public static boolean isBefore(final Object object0, final Object object1) { try { return (Dates.compareDates(object0, object1, false) < DominoUtils.EQUAL); } catch (final Exception e) { DominoUtils.handleException(e); } return false; } /** * Determines if two Dates represent the same day. * * Spawns Calendar objects from the arguments, and returns true if the year, month, and day for the objects are equal. * * @param object0 * First object from which a Calendar object can be constructed. * * @param object1 * Second object from which a Calendar object can be constructed. * * * @return Flag indicating of the two Dates represent the same day. * */ public static boolean isSameDay(final Object object0, final Object object1) { try { if (null == object0) { throw new IllegalArgumentException("object0 is null"); } if (null == object1) { throw new IllegalArgumentException("object1 is null"); } final Calendar cal0 = Dates.getCalendar(object0); final Calendar cal1 = Dates.getCalendar(object1); return ((cal0.get(Calendar.YEAR) == cal1.get(Calendar.YEAR)) && (cal0.get(Calendar.DAY_OF_YEAR) == cal1 .get(Calendar.DAY_OF_YEAR))); } catch (final Exception e) { DominoUtils.handleException(e); } return false; } /** * Determines if a date is within a specified range. * * @param source * Date to check. * * @param begin * Begin date range. * * @param end * End date range. (must be after begin) * * @param inclusive * Flag indicating to include begin and end as valid dates for checking. * * @return Flag indicating if source is (after begin) AND (before end); OR (if inclusive is true) equal to begin or equal to end. */ public static boolean isInRange(final Object source, final Object begin, final Object end, final boolean inclusive) { final Calendar calSource = Dates.getCalendar(source); final Calendar calBegin = Dates.getCalendar(begin); final Calendar calEnd = Dates.getCalendar(end); return (Dates.isAfter(calSource, calBegin) && Dates.isBefore(calSource, calEnd)) || (inclusive && (calSource.equals(calBegin) || calSource.equals(calEnd))); } /** * Determines if a date has a time value of Midnight (12:00:00 AM) * * NOTE: ONLY CHECKS to the Seconds level. Milliseconds are NOT checked. * * @param source * Date to check. * * @return Flag indicating if the specified source has a time value equal to Midnight. */ public static boolean isMidnight(final Object source) { return Dates.isMidnight(source, false); } /** * Determines if a date has a time value of Midnight (12:00:00 AM) * * @param source * Date to check. * * @param compareMilliseconds * Flag indicating if milliseconds should be checked. If FALSE, then source will only be checked to the SECONDS level. * * @return Flag indicating if the specified source has a time value equal to Midnight. */ public static boolean isMidnight(final Object source, final boolean compareMilliseconds) { final Calendar cal = Dates.getCalendar(source); if (null != cal) { final boolean result = ((cal.get(Calendar.HOUR_OF_DAY) == 0) && (cal.get(Calendar.MINUTE) == 0) && (cal.get(Calendar.SECOND) == 0)); if (result) { return (compareMilliseconds) ? (cal.get(Calendar.MILLISECOND) == 0) : true; } } return false; } /** * Gets the days between two Dates. * * Spawns Calendar objects from the arguments, and returns the number of days between them. Returns a negative value if the first * argument is after the second argument. * * @param object0 * First object from which a Calendar object can be constructed. * * @param object1 * Second object from which a Calendar object can be constructed. * * @return Days between the two objects. Maximum days is 2,147,483,647, a range of nearly 5.9 million years. * */ public static int getDaysBetween(final Object object0, final Object object1) { int result = 0; // Maximum days is 2,147,483,647, a range of nearly 5.9 million years. try { if (null == object0) { throw new IllegalArgumentException("object0 is null"); } if (null == object1) { throw new IllegalArgumentException("object1 is null"); } final Calendar cal0 = Dates.getCalendar(object0); final Calendar cal1 = Dates.getCalendar(object1); if ((cal0.get(Calendar.YEAR) == cal1.get(Calendar.YEAR)) && (cal0.get(Calendar.DAY_OF_YEAR) == cal1.get(Calendar.DAY_OF_YEAR))) { return 0; } if (cal1.before(cal0)) { return -Dates.getDaysBetween(cal1, cal0); } final Calendar temp = (Calendar) cal0.clone(); while (temp.before(cal1)) { temp.add(Calendar.DAY_OF_MONTH, 1); result++; } } catch (final Exception e) { DominoUtils.handleException(e); } return result; } /** * Gets the days between two Dates, excluding Saturdays, Sundays, and (optionally) Holidays. * * Spawns Calendar objects from the arguments, and returns the number of days between them. Returns a negative value if the first * argument is after the second argument. * * @param object0 * First object from which a Calendar object can be constructed. * * @param object1 * Second object from which a Calendar object can be constructed. * * @param holidays * Holiday days (as Calendary.DAY_OF_YEAR) to exclude * * @return Business Days between the two objects. Maximum days is 2,147,483,647, a range of nearly 5.9 million years. * */ public static int getBusinessDaysBetween(final Object object0, final Object object1, final List<Integer> holidays) { int result = 0; // Maximum days is 2,147,483,647, a range of nearly 5.9 million years. try { if (null == object0) { throw new IllegalArgumentException("object0 is null"); } if (null == object1) { throw new IllegalArgumentException("object1 is null"); } final Calendar cal0 = Dates.getCalendar(object0); final Calendar cal1 = Dates.getCalendar(object1); if ((cal0.get(Calendar.YEAR) == cal1.get(Calendar.YEAR)) && (cal0.get(Calendar.DAY_OF_YEAR) == cal1.get(Calendar.DAY_OF_YEAR))) { return 0; } if (cal1.before(cal0)) { return -Dates.getDaysBetween(cal1, cal0); } final Calendar temp = (Calendar) cal0.clone(); if (null == holidays) { while (temp.before(cal1)) { temp.add(Calendar.DAY_OF_MONTH, 1); if ((Calendar.SATURDAY != temp.get(Calendar.DAY_OF_WEEK)) && (Calendar.SUNDAY != temp.get(Calendar.DAY_OF_WEEK))) { result++; } } } else { while (temp.before(cal1)) { temp.add(Calendar.DAY_OF_MONTH, 1); if ((Calendar.SATURDAY != temp.get(Calendar.DAY_OF_WEEK)) && (Calendar.SUNDAY != temp.get(Calendar.DAY_OF_WEEK)) && !holidays.contains(temp.get(Calendar.DAY_OF_YEAR))) { result++; } } } } catch (final Exception e) { DominoUtils.handleException(e); } return result; } /** * Gets the hours between two Dates. * * Spawns Calendar objects from the arguments, and returns the number of days between them. Returns a negative value if the first * argument is after the second argument. * * @param object0 * First object from which a Calendar object can be constructed. * * @param object1 * Second object from which a Calendar object can be constructed. * * @return whole number of hours between two values. Assumes object0 < object1, returns negative value otherwise. Maximum hours * converted from 9,223,372,036,854,775,807 milliseconds, a range of just over 293 million years * */ public static long getHoursBetween(final Object object0, final Object object1) { // whole number of hours between two values. Assumes object0 < object1, // returns negative otherwise // long maximum hours converted from 9,223,372,036,854,775,807 // milliseconds, // a range of just over 293 million years try { if (null == object0) { throw new IllegalArgumentException("object0 is null"); } if (null == object1) { throw new IllegalArgumentException("object1 is null"); } return Dates.getHours(object1) - Dates.getHours(object0); } catch (final Exception e) { DominoUtils.handleException(e); } return 0; } /** * Gets the minutes between two Dates. * * Spawns Calendar objects from the arguments, and returns the number of days between them. Returns a negative value if the first * argument is after the second argument. * * @param object0 * First object from which a Calendar object can be constructed. * * @param object1 * Second object from which a Calendar object can be constructed. * * @return whole number of minutes between two values. Assumes object0 < object1, returns negative value otherwise. Maximum minutes * converted from 9,223,372,036,854,775,807 milliseconds, a range of just over 293 million years * */ public static long getMinutesBetween(final Object object0, final Object object1) { // whole number of minutes between two values. Assumes object0 < // object1, // returns negative otherwise // long maximum minutes converted from 9,223,372,036,854,775,807 // milliseconds, // a range of just over 293 million years try { if (null == object0) { throw new IllegalArgumentException("object0 is null"); } if (null == object1) { throw new IllegalArgumentException("object1 is null"); } return Dates.getMinutes(object1) - Dates.getMinutes(object0); } catch (final Exception e) { DominoUtils.handleException(e); } return 0; } /** * Gets the seconds between two Dates. * * Spawns Calendar objects from the arguments, and returns the number of days between them. Returns a negative value if the first * argument is after the second argument. * * @param object0 * First object from which a Calendar object can be constructed. * * @param object1 * Second object from which a Calendar object can be constructed. * * @return whole number of seconds between two values. Assumes object0 < object1, returns negative value otherwise. Maximum seconds * converted from 9,223,372,036,854,775,807 milliseconds, a range of just over 293 million years * */ public static long getSecondsBetween(final Object object0, final Object object1) { // whole number of seconds between two values. Assumes object0 < // object1, // returns negative otherwise // long maximum seconds converted from 9,223,372,036,854,775,807 // milliseconds, // a range of just over 293 million years try { if (null == object0) { throw new IllegalArgumentException("object0 is null"); } if (null == object1) { throw new IllegalArgumentException("object1 is null"); } return Dates.getSeconds(object1) - Dates.getSeconds(object0); } catch (final Exception e) { DominoUtils.handleException(e); } return 0; } /** * Gets the milliseconds between two Dates. * * Spawns Calendar objects from the arguments, and returns the number of days between them. Returns a negative value if the first * argument is after the second argument. * * @param object0 * First object from which a Calendar object can be constructed. * * @param object1 * Second object from which a Calendar object can be constructed. * * @return whole number of milliseconds between two values. Assumes object0 < object1, returns negative value otherwise. Maximum * milliseconds is 9,223,372,036,854,775,807, a range of just over 293 million years * */ public static long getMillisecondsBetween(final Object object0, final Object object1) { // whole number of milliseconds between two values. Assumes object0 < // object1, // returns negative otherwise // long maximum milliseconds is converted from // 9,223,372,036,854,775,807, a range of just over 293 million years try { if (null == object0) { throw new IllegalArgumentException("object0 is null"); } if (null == object1) { throw new IllegalArgumentException("object1 is null"); } return Dates.getTime(object1) - Dates.getTime(object0); } catch (final Exception e) { DominoUtils.handleException(e); } return 0; } /** * Gets the number of hours between the Epoch January 1, 1970, 00:00:00 GMT and the Date value for the passed in object. * * @param object * Object from which a Calendar object can be constructed. * * @return Hours between the Epoch and the date value of the object. */ public static long getHours(final Object object) { // whole number of hours from the Epoch January 1, 1970, 00:00:00 GMT try { return TimeUnit.HOURS.convert(Dates.getTime(object), TimeUnit.MILLISECONDS); } catch (final Exception e) { DominoUtils.handleException(e); } return 0; } /** * Gets the number of minutes between the Epoch January 1, 1970, 00:00:00 GMT and the Date value for the passed in object. * * @param object * Object from which a Calendar object can be constructed. * * @return Minutes between the Epoch and the date value of the object. */ public static long getMinutes(final Object object) { // whole number of minutes from the Epoch January 1, 1970, 00:00:00 GMT try { return TimeUnit.MINUTES.convert(Dates.getTime(object), TimeUnit.MILLISECONDS); } catch (final Exception e) { DominoUtils.handleException(e); } return 0; } /** * Gets the number of seconds between the Epoch January 1, 1970, 00:00:00 GMT and the Date value for the passed in object. * * @param object * Object from which a Calendar object can be constructed. * * @return Seconds between the Epoch and the date value of the object. */ public static long getSeconds(final Object object) { // whole number of seconds from the Epoch January 1, 1970, 00:00:00 GMT try { return TimeUnit.SECONDS.convert(Dates.getTime(object), TimeUnit.MILLISECONDS); } catch (final Exception e) { DominoUtils.handleException(e); } return 0; } /** * Gets an Hours and Minutes String for a specified number of minutes * * @param minutes * Number of minutes from which to generate an Hours and Minutes String * * @param delimiter * String used to delimit the Hours and Minutes in the result. * * @return String representing the Hours and Minutes, delimited by delimiter. */ public static String getHoursMinutes(final long minutes, final String delimiter) { final StringBuilder sb = new StringBuilder((minutes < 0) ? "-" : ""); try { final long absval = Math.abs(minutes); if (absval > 0) { final long hours = (absval / 60); final long remaining = (absval % 60); sb.append((hours > 0) ? "" + hours : "0"); if (remaining > 0) { sb.append((remaining > 9) ? delimiter + remaining : delimiter + "0" + remaining); } else { sb.append(delimiter + "00"); } } } catch (final Exception e) { DominoUtils.handleException(e); } return sb.toString(); } /** * Gets an Hours and Minutes String for a specified number of minutes * * @param minutes * Number of minutes from which to generate an Hours and Minutes String * * @return String representing the Hours and Minutes, delimited ":" */ public static String getHoursMinutes(final long minutes) { return Dates.getHoursMinutes(minutes, ":"); } /** * Gets an Hours and Minutes String representing the time between two Dates. * * Spawns Calendar objects from the arguments, and returns the number of days between them. Returns a negative value if the first * argument is after the second argument. * * @param object0 * First object from which a Calendar object can be constructed. * * @param object1 * Second object from which a Calendar object can be constructed. * * @return String representing the Hours and Minutes between two Dates. * */ public static String getHoursMinutesBetween(final Object object0, final Object object1) { final long minutes = Dates.getMinutesBetween(object0, object1); return Dates.getHoursMinutes(minutes); } /** * Gets the number of milliseconds between the Epoch January 1, 1970, 00:00:00 GMT and the Date value for the passed in object. * * @param object * Object from which a Calendar object can be constructed. * * @return Milliseconds between the Epoch and the date value of the object. */ public static long getTime(final Object object) { // whole number of milliseconds from Epoch January 1, 1970, 00:00:00 GMT try { return Dates.getDate(object).getTime(); } catch (final Exception e) { DominoUtils.handleException(e); } return 0; } /** * Gets the TimeFormatter for the associated key. * * Searches all TimeFormatters to find one which has a name or format equal to the key. If none found then searches all TimeFormatters * for one that successfully matches() the key. Returns the first one found. * * @param key * Key value to check for equality against the the TimeFormatter or a match to the TimeFormatter. * * @return First found TimeFormatter. Null if no name or format equality or match found. */ public static Dates get(final String key) { if (!Strings.isBlankString(key)) { for (final Dates result : Dates.values()) { if (result.name().equalsIgnoreCase(key) || result.getInstanceTimestampFormat().equalsIgnoreCase(key)) { return result; } } for (final Dates result : Dates.values()) { if (result.matches(key)) { return result; } } } return null; } /** * Gets a Calendar object. * * Creates or casts a Calendar from the passed in object. * * @param object * Source from which to create or cast a Calendar object. * * @return Newly created or casted Calendar from the source. Null on exception. */ public static Calendar getCalendar(final Object object) { String classname = ""; lotus.domino.DateTime datetime = null; final lotus.domino.Item item = null; try { if (null == object) { throw new IllegalArgumentException("object is null"); } classname = object.getClass().getName(); if (object instanceof Calendar) { return (Calendar) object; } if ((object instanceof String) || (classname.equalsIgnoreCase("java.lang.String"))) { return Dates.getCalendar(Dates.parse((String) object)); } Calendar result = null; if (object instanceof Date) { result = Calendar.getInstance(); final Date date = (Date) object; result.setTime(date); return result; } if (object instanceof DateTime) { result = Calendar.getInstance(); final DateTime obj = (DateTime) object; final Date date = obj.toJavaDate(); result.setTime(date); return result; } if (object instanceof lotus.domino.DateTime) { result = Calendar.getInstance(); datetime = (lotus.domino.DateTime) object; final Date date = datetime.toJavaDate(); result.setTime(date); return result; } if ((object instanceof Item) || (object instanceof lotus.domino.Item)) { return Dates.getCalendar(Dates.getDate(object)); } throw new IllegalArgumentException("Unsupported Class:" + classname); } catch (final Exception e) { DominoUtils.handleException(e); } finally { try { if (datetime != null) datetime.recycle(); if (item != null) item.recycle(); } catch (NotesException e) { e.printStackTrace(); } } return null; } /** * Gets a Calendar object. * * Creates a new Calendar object * * @return New Calendar object */ public static Calendar getCalendar() { return Dates.getCalendar(Dates.getDate()); } /** * Gets a Date object. * * Creates or casts a Date from the passed in object. * * @param object * Source from which to create or cast a Date object. * * @return Newly created or casted Date from the source. Null on exception * */ public static Date getDate(final Object object) { String classname = ""; lotus.domino.DateTime datetime = null; lotus.domino.Item item = null; try { if (null == object) { throw new IllegalArgumentException("object is null"); } classname = object.getClass().getName(); if (object instanceof Date) { return (Date) object; } if (object instanceof Calendar) { return ((Calendar) object).getTime(); } if (object instanceof String) { return Dates.parse((String) object); } if (object instanceof DateTime) { return ((DateTime) object).toJavaDate(); } if (object instanceof lotus.domino.DateTime) { datetime = (DateTime) object; return datetime.toJavaDate(); } if (object instanceof Item) { return Dates.getDate(((Item) object).getDateTimeValue()); } if (object instanceof lotus.domino.Item) { item = (lotus.domino.Item) object; return Dates.getDate(item.getDateTimeValue()); } throw new IllegalArgumentException("Unsupported Class:" + classname); } catch (final Exception e) { DominoUtils.handleException(e); } finally { try { if (datetime != null) datetime.recycle(); if (item != null) item.recycle(); } catch (NotesException e) { e.printStackTrace(); } } return null; } /** * Gets a Date object. * * Creates a New Date object from the passed in arguments. * * @param date * Source from which to get the DATE portion of the new Date object. If null then the value from time will be used. * * @param time * Source from which to get the TIME portion of the new Date object. If null then the value from date will be used. * * @return Newly created or cast Date from the source. * * @throws IllegalArgumentException * if both date nor time arguments are null. * @throws IllegalArgumentException * If both arguments cannot be processed as a date. */ public static Date getDate(final Object date, final Object time) throws NullPointerException, IllegalArgumentException { if ((null == date) && (null == time)) { throw new NullPointerException("Both DATE and TIME arguments are null"); } try { final Date dDate = (null == date) ? Dates.getDate(time) : Dates.getDate(date); if (null == dDate) { throw new RuntimeException("dDate is null"); } final Date dTime = (null == time) ? Dates.getDate(date) : Dates.getDate(time); if (null == dTime) { throw new RuntimeException("dTime is null"); } final Calendar cDate = Dates.getCalendar(dDate); final Calendar cTime = Dates.getCalendar(dTime); cDate.set(Calendar.HOUR_OF_DAY, cTime.get(Calendar.HOUR_OF_DAY)); cDate.set(Calendar.MINUTE, cTime.get(Calendar.MINUTE)); cDate.set(Calendar.SECOND, cTime.get(Calendar.SECOND)); return cDate.getTime(); } catch (final Exception e) { DominoUtils.handleException(e); throw new IllegalArgumentException("Neither DATE nor TIME argument could be processed as a Date object."); } } /** * Gets a Date object. * * Creates a new Date object * * @return New Date object */ public static Date getDate() { return new Date(); } /** * Gets a SimpleDateFormat object for the specified format. * * @param format * Format for which to generate a new SimpleDateFormat object. * * @return SimpleDateFormat object for the specified format */ public static SimpleDateFormat getSimpleDateFormat(final String format) { final SimpleDateFormat result = (Strings.isBlankString(format)) ? new SimpleDateFormat() : new SimpleDateFormat(format); result.setLenient(true); return result; } /** * Attempts to spawn a new Date by parsing a string. * * @param string * Value from which to attempt to construct a new Date object. * * @return new Date object constructed from the string. Null on error. */ public static Date parse(final String string) { try { if (Strings.isBlankString(string)) { throw new IllegalArgumentException("String to parse is null or blank"); } Dates tf = Dates.get(string); if ((null == tf) && (string.indexOf(" ") > 0)) { return Dates.parse(string.trim().replaceAll("\\s", "")); } if (null != tf) { return tf.parseInstance(string); } final SimpleDateFormat sdf = new SimpleDateFormat(); Date result = sdf.parse(string); if (null == result) { throw new ParseException("Unable to parse: " + string, 0); } return result; } catch (final Exception e) { DominoUtils.handleException(e); } return null; } /** * Attempts to spawn a new Date by parsing a string. * * @param dateText * Value from which to attempt to construct a new Date object. * * @param format * Format used to construct the SimpleDateFormatter object. * * @return new Date object constructed from the string. Null on error. */ public static Date parse(final String dateText, final String format) { if (null != dateText) { if (Strings.isBlankString(format)) { return Dates.parse(dateText); } try { return Dates.getSimpleDateFormat(format).parse(dateText); } catch (final Exception e) { DominoUtils.handleException(e); } } return null; } /** * Compares two Objects as Dates * * Arguments are first compared by existence, then by value. * * @param object0 * First date to compare. * * @param object1 * Second date to compare. * * @param descending * flags indicating comparison order. true = descending, false = ascending. * * @return a negative integer, zero, or a positive integer indicating if the first object is less than, equal to, or greater than the * second object. * * @throws RuntimeException * if a failure occurs comparing object0 and object1 as Date objects. * @see java.lang.Comparable#compareTo(Object) * @see DominoUtils#LESS_THAN * @see DominoUtils#EQUAL * @see DominoUtils#GREATER_THAN */ public static int compareDaysBetween(final Object object0, final Object object1, final boolean descending) { try { if (null == object0) { return (null == object1) ? DominoUtils.EQUAL : (descending) ? DominoUtils.GREATER_THAN : DominoUtils.LESS_THAN; } else if (null == object1) { return (descending) ? DominoUtils.LESS_THAN : DominoUtils.GREATER_THAN; } final Date date0 = Dates.getDate(object0); final Date date1 = Dates.getDate(object1); if (null == date0) { return (null == date1) ? DominoUtils.EQUAL : (descending) ? DominoUtils.GREATER_THAN : DominoUtils.LESS_THAN; } else if (null == date1) { return (descending) ? DominoUtils.LESS_THAN : DominoUtils.GREATER_THAN; } if (date0.equals(date1)) { return DominoUtils.EQUAL; } else { final int daysbetween = Dates.getDaysBetween(date0, date1); if (0 == daysbetween) { return DominoUtils.EQUAL; } final int temp = (daysbetween > 0) ? DominoUtils.LESS_THAN : (daysbetween < 0) ? DominoUtils.GREATER_THAN : DominoUtils.EQUAL; return (descending) ? -1 * temp : temp; } } catch (final Exception e) { DominoUtils.handleException(e); throw new RuntimeException("EXCEPTION in Dates.compareDaysBetween()"); } } /** * Compares two Objects as Dates * * Arguments are first compared by existence, then by value. * * @param object0 * First date to compare. * * @param object1 * Second date to compare. * * @return a negative integer, zero, or a positive integer indicating if the first object is less than, equal to, or greater than the * second object. * * @throws RuntimeException * if a failure occurs comparing object0 and object1 as Date objects. * * @see java.lang.Comparable#compareTo(Object) * @see DominoUtils#LESS_THAN * @see DominoUtils#EQUAL * @see DominoUtils#GREATER_THAN */ public static int compareDaysBetween(final Object object0, final Object object1) { return (Dates.compareDaysBetween(object0, object1, false)); } /** * Compares the ELAPSED days of two Date objects. * * Arguments are first compared by existence, then by value. * * @param object0 * First date to compare. * * @param object1 * Second date to compare. * * @param descending * flags indicating comparison order. true = descending, false = ascending. * * @return a negative integer, zero, or a positive integer indicating if the number of days elapsed since the first date is less than, * equal to, or greater than the number of days elapsed since the second date. * * @throws RuntimeException * if a failure occurs comparing object0 and object1 as Date objects. * * @see java.lang.Comparable#compareTo(Object) * @see DominoUtils#LESS_THAN * @see DominoUtils#EQUAL * @see DominoUtils#GREATER_THAN */ public static int compareElapsedDays(final Object object0, final Object object1, final boolean descending) { try { if (null == object0) { return (null == object1) ? DominoUtils.EQUAL : (descending) ? DominoUtils.GREATER_THAN : DominoUtils.LESS_THAN; } else if (null == object1) { return (descending) ? DominoUtils.LESS_THAN : DominoUtils.GREATER_THAN; } final Date date0 = Dates.getDate(object0); final Date date1 = Dates.getDate(object1); if (null == date0) { return (null == date1) ? DominoUtils.EQUAL : (descending) ? DominoUtils.GREATER_THAN : DominoUtils.LESS_THAN; } else if (null == date1) { return (descending) ? DominoUtils.LESS_THAN : DominoUtils.GREATER_THAN; } if (date0.equals(date1)) { return DominoUtils.EQUAL; } else { final Date now = Dates.getDate(); final int elapsed0 = Dates.getDaysBetween(date0, now); final int elapsed1 = Dates.getDaysBetween(date1, now); if (elapsed0 == elapsed1) { return DominoUtils.EQUAL; } final int temp = (elapsed0 < elapsed1) ? DominoUtils.GREATER_THAN : (elapsed0 > elapsed1) ? DominoUtils.LESS_THAN : DominoUtils.EQUAL; return (descending) ? -1 * temp : temp; } } catch (final Exception e) { DominoUtils.handleException(e); throw new RuntimeException("EXCEPTION in Dates.compareElapsedDays()"); } } /** * Compares two Objects as Dates * * Arguments are first compared by existence, then by value. * * @param object0 * First date to compare. * * @param object1 * Second date to compare. * * @return a negative integer, zero, or a positive integer indicating if the first object is less than, equal to, or greater than the * second object. * * @throws RuntimeException * if a failure occurs comparing object0 and object1 as Date objects. * * @see java.lang.Comparable#compareTo(Object) * @see DominoUtils#LESS_THAN * @see DominoUtils#EQUAL * @see DominoUtils#GREATER_THAN */ public static int compareElapsedDays(final Object object0, final Object object1) { return (Dates.compareElapsedDays(object0, object1, false)); } /** * Compares two Objects as Dates * * Arguments are first compared by existence, then by value. * * @param object0 * First date to compare. * * @param object1 * Second date to compare. * * @param descending * flags indicating comparison order. true = descending, false = ascending. * * @return a negative integer, zero, or a positive integer indicating if the first object is less than, equal to, or greater than the * second object. * * @throws RuntimeException * if a failure occurs comparing object0 and object1 as Date objects. * * @see java.lang.Comparable#compareTo(Object) * @see DominoUtils#LESS_THAN * @see DominoUtils#EQUAL * @see DominoUtils#GREATER_THAN */ public static int compareDates(final Object object0, final Object object1, final boolean descending) { try { if (null == object0) { return (null == object1) ? DominoUtils.EQUAL : (descending) ? DominoUtils.GREATER_THAN : DominoUtils.LESS_THAN; } else if (null == object1) { return (descending) ? DominoUtils.LESS_THAN : DominoUtils.GREATER_THAN; } final Date date0 = Dates.getDate(object0); final Date date1 = Dates.getDate(object1); if (null == date0) { return (null == date1) ? DominoUtils.EQUAL : (descending) ? DominoUtils.GREATER_THAN : DominoUtils.LESS_THAN; } else if (null == date1) { return (descending) ? DominoUtils.LESS_THAN : DominoUtils.GREATER_THAN; } return (date0.equals(date1)) ? DominoUtils.EQUAL : (descending) ? date1.compareTo(date0) : date0.compareTo(date1); } catch (final Exception e) { DominoUtils.handleException(e); throw new RuntimeException("EXCEPTION in Dates.compareDates()"); } } /* * *************************************************** * *************************************************** * * EPOCH methods * * *************************************************** * *************************************************** */ /** * Gets a Date object representing the epoch * * @return Date representing the epoch */ public static final Date getEpoch() { return new Date(0); } /** * Generates a Date object from the specified source, with all TIME values set to that of the epoch * * @param source * Object from which a Date object can be constructed. * * @return Date constructed from the source with all TIME values set to that of the epoch. */ public static Date getEpochedDate(final Object source) { final Date date = Dates.getDate(source); if (null == date) { return null; } else { final Calendar epoch = Calendar.getInstance(); epoch.setTime(Dates.getEpoch()); final Calendar result = Calendar.getInstance(); result.setTime(date); result.set(Calendar.HOUR_OF_DAY, epoch.get(Calendar.HOUR_OF_DAY)); result.set(Calendar.MINUTE, epoch.get(Calendar.MINUTE)); result.set(Calendar.SECOND, epoch.get(Calendar.SECOND)); result.set(Calendar.MILLISECOND, epoch.get(Calendar.MILLISECOND)); return result.getTime(); } } /** * Generates a Date object from the specified source, with all DATE values set to that of the epoch * * @param source * Object from which a Date object can be constructed. * * @return Date constructed from the source with all DATE values set to that of the epoch */ public static Date getEpochedTime(final Object source) { final Date date = Dates.getDate(source); if (null == date) { return null; } else { final Calendar epoch = Calendar.getInstance(); epoch.setTime(Dates.getEpoch()); final Calendar result = Calendar.getInstance(); result.setTime(date); result.set(Calendar.YEAR, epoch.get(Calendar.YEAR)); result.set(Calendar.DAY_OF_YEAR, epoch.get(Calendar.DAY_OF_YEAR)); return result.getTime(); } } }