/**
* See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Board of Regents of the University of Wisconsin System
* licenses this file to you 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.microsoft.exchange;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import net.fortuna.ical4j.model.DateTime;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.Interval;
import org.joda.time.Period;
/**
* @author Nicholas Blair
*/
public class DateHelp {
protected static final Log log = LogFactory.getLog(DateHelp.class);
public static final Period MAX_PERIOD = Period.days(3660);
protected static final String DATE_TIME_FORMAT = "yyyyMMdd-HHmm";
private static final String DATE_FORMAT = "yyyy-MM-dd";
/**
* @return a new instance of {@link SimpleDateFormat} that uses this application's common Date/Time format ("yyyyMMdd-HHmm").
*/
public static SimpleDateFormat getDateTimeFormat() {
return new SimpleDateFormat(DATE_TIME_FORMAT);
}
/**
* Convert a {@link String} in the common date/time format for this application into a {@link Date}.
*
* @param timePhrase format: "yyyyMMdd-HHmm"
* @return the corresponding date
* @throws IllegalArgumentException
*/
public static Date parseDateTimePhrase(final String timePhrase) {
if(timePhrase == null) {
return null;
}
try {
Date time = getDateTimeFormat().parse(timePhrase);
time = DateUtils.truncate(time, Calendar.MINUTE);
return time;
} catch (ParseException e) {
throw new IllegalArgumentException("cannot parse date/time phrase " + timePhrase, e);
}
}
/**
*
* @param date
* @return
*/
public static XMLGregorianCalendar convertDateToXMLGregorianCalendar(final Date date) {
return convertDateToXMLGregorianCalendar(date,null);
}
public static XMLGregorianCalendar convertDateToXMLGregorianCalendar(final Date date, TimeZone tz) {
if(date == null) {
return null;
}
DateTime dt = new DateTime(date);
GregorianCalendar calendar = new GregorianCalendar();
// calendar.setTime(date);
calendar.setTimeInMillis(dt.getTime());
if(tz != null){
calendar.setTimeZone(tz);
}
XMLGregorianCalendar xmlDate = null;
try {
xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar);
} catch (DatatypeConfigurationException e) {
throw new IllegalStateException("unable to invoke DatatypeFactory.newInstance", e);
}
if(tz == null) xmlDate.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
long msDiff = Math.abs(xmlDate.toGregorianCalendar().getTime().getTime() - date.getTime());
org.apache.commons.lang.Validate.isTrue(msDiff < 1000, "original time ("+xmlDate.toGregorianCalendar().getTime()+") differs from converted time ("+date+") by more than 1000ms. Check the Timezones?");
return xmlDate;
}
public static DateTime convertXMLGregorianCalendarToDateTime(XMLGregorianCalendar calendar){
return new DateTime(calendar.toGregorianCalendar().getTime());
}
/**
*
* @param value
* @return
*/
public static Date makeDate(String value) {
SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT);
try {
Date date = df.parse(value);
return DateUtils.truncate(date, java.util.Calendar.DATE);
} catch (ParseException e) {
throw new IllegalArgumentException(value + " does not match expected format " + DATE_FORMAT, e);
}
}
/**
*
* @param value
* @return
*/
public static Date makeDateTime(String value) {
SimpleDateFormat df = new SimpleDateFormat(DATE_TIME_FORMAT);
try {
Date date = df.parse(value);
return DateUtils.truncate(date, java.util.Calendar.MINUTE);
} catch (ParseException e) {
throw new IllegalArgumentException(value + " does not match expected format " + DATE_FORMAT, e);
}
}
public static List<Interval> generateIntervals(org.joda.time.DateTime start, org.joda.time.DateTime end, Period period){
if(period.getDays()>MAX_PERIOD.getDays()) {
period = MAX_PERIOD;
}
List<Interval> list = new ArrayList<Interval>();
org.joda.time.DateTime intervalEnd = start.plus(period);
while(intervalEnd.isBefore(end)){
list.add(new Interval(start, intervalEnd));
start = intervalEnd;
intervalEnd = intervalEnd.plus(period);
}
if(start.isBefore(end)) {
list.add(new Interval(start,end));
}
return list;
}
/**
* will always return at least two intervals.
*
* @param start
* @param end
* @param count
* @return
*/
public static List<Interval> generateMultipleIntervals(Date start, Date end, int count){
List<Interval> intervals = generateIntervals(start, end);
int actualCount = intervals.size();
if(count > actualCount) {
while(actualCount < count) {
List<Interval> tIntervals = new ArrayList<Interval>();
for(Interval i: intervals) {
tIntervals.addAll(generateIntervals(i.getStart().toDate(), i.getEnd().toDate()));
}
intervals = tIntervals;
actualCount = intervals.size();
}
}
return intervals;
}
public static List<Interval> generateIntervals(Date start, Date end){
org.apache.commons.lang.Validate.isTrue(end.after(start));
long startInstant = start.getTime();
long endInstant = end.getTime();
long midInstant = startInstant + (endInstant - startInstant)/2;
Interval a = new Interval(startInstant,midInstant);
Interval b = new Interval(midInstant,endInstant);
List<Interval> intervals = new ArrayList<Interval>();
intervals.add(a);
intervals.add(b);
return intervals;
}
/**
* @return
* @throws DatatypeConfigurationException
*/
public static XMLGregorianCalendar getXMLGregorianCalendarNow() throws DatatypeConfigurationException {
GregorianCalendar gregorianCalendar = new GregorianCalendar();
return getXMLGregorianCalendar(gregorianCalendar);
}
public static XMLGregorianCalendar getXMLGregorianCalendarNow(TimeZone timeZone) throws DatatypeConfigurationException {
GregorianCalendar gregorianCalendar = new GregorianCalendar(timeZone);
return getXMLGregorianCalendar(gregorianCalendar);
}
private static XMLGregorianCalendar getXMLGregorianCalendar(GregorianCalendar gregorianCalendar) throws DatatypeConfigurationException{
DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
XMLGregorianCalendar now = datatypeFactory.newXMLGregorianCalendar(gregorianCalendar);
return now;
}
public static boolean withinOneSecond(XMLGregorianCalendar a, XMLGregorianCalendar b){
if(a == null || b == null) return false;
GregorianCalendar aCalendar = a.toGregorianCalendar();
GregorianCalendar bCalendar = b.toGregorianCalendar();
if(aCalendar == null || bCalendar == null) return false;
long aInMillis = aCalendar.getTimeInMillis();
long bInMillis = bCalendar.getTimeInMillis();
long diff = Math.abs(aInMillis - bInMillis);
log.info("dates differ by "+diff+" (ms) ");
return (diff < 1000);
}
}