package er.ajax.example2.util;
import java.util.Calendar;
import java.util.Date;
import com.webobjects.eocontrol.EOAndQualifier;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSTimeZone;
import com.webobjects.foundation.NSTimestamp;
import com.webobjects.foundation.NSTimestampFormatter;
import er.ajax.example2.helper.NSTimestampHelper;
import er.extensions.eof.ERXQ;
import er.extensions.qualifiers.ERXAndQualifier;
import er.extensions.qualifiers.ERXKeyValueQualifier;
import er.extensions.qualifiers.ERXOrQualifier;
public class DateUtils {
public static final NSTimestampFormatter MONTH_NAME_AND_YEAR_FORMATTER = new NSTimestampFormatter("%B %Y");
public static final NSTimestampFormatter MONTH_NAME_FORMATTER = new NSTimestampFormatter("%B");
public static final NSTimestampFormatter SHORT_MONTH_NAME_FORMATTER = new NSTimestampFormatter("%b");
public static final NSTimestampFormatter SHORT_MONTH_NAME_AND_YEAR_FORMATTER = new NSTimestampFormatter("%b %y");
public static final NSTimestampFormatter SHORT_MONTH_NAME_AND_DAY_OF_WEEK_AND_YEAR_FORMATTER = new NSTimestampFormatter("%a, %b %d %y");
public static final NSTimestampFormatter SHORT_MONTH_NAME_AND_DAY_OF_WEEK_FORMATTER = new NSTimestampFormatter("%a, %b %d");
public static final NSTimestampFormatter SHORT_TIME_FORMATTER = new NSTimestampFormatter("%I:%M%p");
public static final NSTimestampFormatter URL_FRIENDLY_FORMATTER = new NSTimestampFormatter("%Y%m%dT%H%M%S");
public static final String[] DAYS_OF_WEEK = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
public static final String[] MONTHS = new String[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
static {
MONTH_NAME_AND_YEAR_FORMATTER.setDefaultFormatTimeZone(NSTimeZone.getGMT());
MONTH_NAME_FORMATTER.setDefaultFormatTimeZone(NSTimeZone.getGMT());
SHORT_MONTH_NAME_FORMATTER.setDefaultFormatTimeZone(NSTimeZone.getGMT());
SHORT_MONTH_NAME_AND_YEAR_FORMATTER.setDefaultFormatTimeZone(NSTimeZone.getGMT());
SHORT_MONTH_NAME_AND_DAY_OF_WEEK_AND_YEAR_FORMATTER.setDefaultFormatTimeZone(NSTimeZone.getGMT());
SHORT_MONTH_NAME_AND_DAY_OF_WEEK_FORMATTER.setDefaultFormatTimeZone(NSTimeZone.getGMT());
SHORT_TIME_FORMATTER.setDefaultFormatTimeZone(NSTimeZone.getGMT());
}
public static EOQualifier dateWithinKeypathRangeQualifier(String startDateKey, String endDateKey, NSTimestamp date, boolean exclusive) {
NSMutableArray<EOQualifier> startQualifiers = new NSMutableArray<EOQualifier>();
if (exclusive) {
startQualifiers.addObject(new ERXKeyValueQualifier(startDateKey, EOQualifier.QualifierOperatorLessThan, date));
}
else {
startQualifiers.addObject(new ERXKeyValueQualifier(startDateKey, EOQualifier.QualifierOperatorEqual, null));
startQualifiers.addObject(new ERXKeyValueQualifier(startDateKey, EOQualifier.QualifierOperatorLessThanOrEqualTo, date));
}
EOQualifier startQualifier = new ERXOrQualifier(startQualifiers);
NSMutableArray<EOQualifier> endQualifiers = new NSMutableArray<EOQualifier>();
if (exclusive) {
endQualifiers.addObject(new ERXKeyValueQualifier(endDateKey, EOQualifier.QualifierOperatorGreaterThan, date));
}
else {
endQualifiers.addObject(new ERXKeyValueQualifier(endDateKey, EOQualifier.QualifierOperatorEqual, null));
endQualifiers.addObject(new ERXKeyValueQualifier(endDateKey, EOQualifier.QualifierOperatorGreaterThanOrEqualTo, date));
}
EOQualifier endQualifier = new ERXOrQualifier(endQualifiers);
EOAndQualifier qualifier = new ERXAndQualifier(new NSArray<EOQualifier>(new EOQualifier[] { startQualifier, endQualifier }));
return qualifier;
/*
System.out.println("DateUtils.dateWithinKeypathRangeQualifier: " + startDateKey + ", " + endDateKey + ", " + date);
EOQualifier startKeyBeforeDate = ERXQ.lessThan(startDateKey, date);
EOQualifier startKeyOnDate = ERXQ.equals(startDateKey, date);
EOQualifier startKeyAfterDate = ERXQ.greaterThan(startDateKey, date);
EOQualifier endKeyBeforeDate = ERXQ.lessThan(endDateKey, date);
EOQualifier endKeyOnDate = ERXQ.equals(endDateKey, date);
EOQualifier endKeyAfterDate = ERXQ.greaterThan(endDateKey, date);
EOQualifier qualifier;
if(exclusive) {
qualifier = ERXQ.and(startKeyBeforeDate, endKeyAfterDate);
} else {
qualifier = ERXQ.and(ERXQ.or(startKeyBeforeDate, startKeyOnDate), ERXQ.or(endKeyAfterDate, endKeyOnDate));
}
return qualifier;
*/
}
public static EOQualifier dateRangeOverlapsKeypathRangeQualifier(String startDateKey, String endDateKey, NSTimestamp startDate, NSTimestamp endDate, boolean exclusive) {
if (endDate == null) {
return DateUtils.dateWithinKeypathRangeQualifier(startDateKey, endDateKey, startDate, exclusive);
}
else if (startDate == null) {
return DateUtils.dateWithinKeypathRangeQualifier(startDateKey, endDateKey, endDate, exclusive);
}
else if (endDate.before(startDate)) {
throw new IllegalArgumentException("End date must be after start date (start date = " + startDate + ", end date = " + endDate + ")");
}
EOQualifier startKeyBeforeStartDate = ERXQ.lessThan(startDateKey, startDate);
EOQualifier startKeyBeforeEndDate = ERXQ.lessThan(startDateKey, endDate);
EOQualifier startKeyOnStartDate = ERXQ.equals(startDateKey, startDate);
EOQualifier startKeyOnEndDate = ERXQ.equals(startDateKey, endDate);
EOQualifier startKeyAfterStartDate = ERXQ.greaterThan(startDateKey, startDate);
EOQualifier startKeyAfterEndDate = ERXQ.greaterThan(startDateKey, endDate);
EOQualifier endKeyBeforeStartDate = ERXQ.lessThan(endDateKey, startDate);
EOQualifier endKeyBeforeEndDate = ERXQ.lessThan(endDateKey, endDate);
EOQualifier endKeyOnStartDate = ERXQ.equals(endDateKey, startDate);
EOQualifier endKeyOnEndDate = ERXQ.equals(endDateKey, endDate);
EOQualifier endKeyAfterStartDate = ERXQ.greaterThan(endDateKey, startDate);
EOQualifier endKeyAfterEndDate = ERXQ.greaterThan(endDateKey, endDate);
// Around Start
EOQualifier aroundStart = ERXQ.and(startKeyAfterStartDate, startKeyBeforeEndDate);
// Ends At Start
EOQualifier endsAtStart = ERXQ.and(startKeyAfterStartDate, startKeyOnEndDate);
// Surrounding
EOQualifier surrounding = ERXQ.and(startKeyBeforeStartDate, endKeyAfterEndDate);
// Directly Overlapping
EOQualifier directlyOverlapping = ERXQ.and(startKeyOnStartDate, endKeyOnEndDate);
// In Between
EOQualifier inBetween = ERXQ.and(startKeyBeforeStartDate, endKeyAfterStartDate, endKeyAfterStartDate, endKeyAfterEndDate);
// Around End
EOQualifier aroundEnd = ERXQ.and(endKeyAfterStartDate, endKeyBeforeEndDate);
// Starts At End
EOQualifier startsAtEnd = ERXQ.and(endKeyOnStartDate, endKeyBeforeEndDate);
EOQualifier qualifier;
if (exclusive) {
qualifier = ERXQ.or(aroundStart, surrounding, directlyOverlapping, inBetween, aroundEnd);
}
else {
qualifier = ERXQ.or(aroundStart, startKeyOnStartDate, endKeyOnStartDate, endsAtStart, surrounding, directlyOverlapping, inBetween, aroundEnd, endKeyOnEndDate, startsAtEnd, startKeyOnEndDate);
}
return qualifier;
}
public static EOQualifier keypathWithinDateRangeQualifier(String _startDateKey, NSTimestamp _startDate, NSTimestamp _endDate) {
if (_startDate != null) {
if (_endDate != null) {
EOQualifier qualifier1 = new ERXKeyValueQualifier(_startDateKey, EOQualifier.QualifierOperatorGreaterThanOrEqualTo, _startDate);
EOQualifier qualifier2 = new ERXKeyValueQualifier(_startDateKey, EOQualifier.QualifierOperatorLessThanOrEqualTo, _endDate);
return new ERXAndQualifier(new NSArray<EOQualifier>(new EOQualifier[] { qualifier1, qualifier2 }));
}
return new ERXKeyValueQualifier(_startDateKey, EOQualifier.QualifierOperatorGreaterThanOrEqualTo, _startDate);
}
else if (_endDate != null) {
return new ERXKeyValueQualifier(_startDateKey, EOQualifier.QualifierOperatorLessThanOrEqualTo, _endDate);
}
return null;
}
public static NSTimestamp timestamp(int _year, int _month, int _day, int _hour, int _minute, int _second, int _millisecond) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, _year);
cal.set(Calendar.MONTH, _month - 1);
cal.set(Calendar.DAY_OF_MONTH, _day);
cal.set(Calendar.HOUR_OF_DAY, _hour);
cal.set(Calendar.MINUTE, _minute);
cal.set(Calendar.SECOND, _second);
cal.set(Calendar.MILLISECOND, _millisecond);
NSTimestamp timestamp = new NSTimestamp(cal.getTime().getTime());
return timestamp;
}
public static NSArray years(int _offset, int _count) {
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
return DateUtils.years(year, _offset, _count);
}
public static NSArray<Integer> years(int _year, int _offset, int _count) {
NSMutableArray<Integer> years = new NSMutableArray<Integer>();
for (int i = 0; i < _count; i++) {
years.addObject(Integer.valueOf(_year + _offset + i));
}
return years;
}
public static int getDurationInDays(Day _startDay, Day _endDay, boolean _inWeekDaysOnly) {
int days = 0;
Calendar start = _startDay.startCalendar();
Calendar end = _endDay.startCalendar();
while (!start.after(end)) {
int dayOfWeek = start.get(Calendar.DAY_OF_WEEK);
boolean weekend = (dayOfWeek == Calendar.SUNDAY || dayOfWeek == Calendar.SATURDAY);
if (!_inWeekDaysOnly || !weekend) {
days++;
}
start.add(Calendar.DATE, 1);
}
return days;
}
public static String getDurationAsString(NSTimestamp _startTime, NSTimestamp _endTime) {
StringBuilder buff = new StringBuilder();
long seconds = getDurationInSeconds(_startTime, _endTime);
long hours = seconds / 3600;
long minutes = (seconds % 3600) / 60;
buff.append(hours);
buff.append(":");
buff.append(minutes);
buff.append(":");
buff.append(seconds % 60);
return buff.toString();
}
public static long getDurationInDays(NSTimestamp _startTime, NSTimestamp _endTime) {
Calendar start = getCalendarFromTimestamp(_startTime);
Calendar end = getCalendarFromTimestamp(_endTime);
long millis = end.getTimeInMillis() - start.getTimeInMillis();
return millis / 1000 / 60 / 60 / 24;
}
public static long getDurationInHours(NSTimestamp _startTime, NSTimestamp _endTime) {
Calendar start = getCalendarFromTimestamp(_startTime);
Calendar end = getCalendarFromTimestamp(_endTime);
long millis = end.getTimeInMillis() - start.getTimeInMillis();
return millis / 1000 / 60 / 60;
}
public static long getDurationInMinutes(NSTimestamp _startTime, NSTimestamp _endTime) {
Calendar start = getCalendarFromTimestamp(_startTime);
Calendar end = getCalendarFromTimestamp(_endTime);
long seconds = end.getTimeInMillis() - start.getTimeInMillis();
return seconds / 1000 / 60;
}
public static long getDurationInSeconds(NSTimestamp _startTime, NSTimestamp _endTime) {
Calendar start = getCalendarFromTimestamp(_startTime);
Calendar end = getCalendarFromTimestamp(_endTime);
long seconds = end.getTimeInMillis() - start.getTimeInMillis();
return seconds / 1000;
}
public static Calendar getCalendarFromTimestamp(Date timestamp) {
Calendar cal = Calendar.getInstance();
cal.setTime(timestamp);
return cal;
}
public static NSTimestamp daysFrom(int numberOfDays, Date timestamp) {
Calendar cal = getCalendarFromTimestamp(timestamp);
cal.add(Calendar.DATE, numberOfDays);
return new NSTimestamp(cal.getTime());
}
/**
* This method tells whether two timestamps are on the same day, reguardless of time.
*
* @param aTime
* @param anotherTime
* @return
*/
public static boolean isOnTheSameDay(NSTimestamp aTime, NSTimestamp anotherTime) {
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(aTime);
cal2.setTime(anotherTime);
return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH) && cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH);
}
/**
* Returns the difference in units of calendarField (Calendar.MONTH, Calendar.DAY_OF_MONTH, etc) between the two dates. This will return the ceil() value, so one second past 1 month = 2 months.
*
* @param start
* the start date
* @param end
* the end date
* @param calendarField
* the calendar field to diff
* @return the difference between two dates
*/
public static int difference(NSTimestamp start, NSTimestamp end, int calendarField) {
Calendar startCal;
Calendar endCal;
if (start.after(end)) {
endCal = DateUtils.getCalendarFromTimestamp(start);
startCal = DateUtils.getCalendarFromTimestamp(end);
}
else {
startCal = DateUtils.getCalendarFromTimestamp(start);
endCal = DateUtils.getCalendarFromTimestamp(end);
}
long startMillis = startCal.getTimeInMillis();
long endMillis = endCal.getTimeInMillis();
double diffMillis = endMillis - startMillis;
double skipRateDouble = 10.0;
if (calendarField == Calendar.ERA) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0 * 365.0);
}
else if (calendarField == Calendar.YEAR) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0 * 365.0);
}
else if (calendarField == Calendar.MONTH) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0 * 30.0);
}
else if (calendarField == Calendar.WEEK_OF_YEAR) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0 * 7);
}
else if (calendarField == Calendar.WEEK_OF_MONTH) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0 * 7);
}
else if (calendarField == Calendar.DATE) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0);
}
else if (calendarField == Calendar.DAY_OF_MONTH) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0);
}
else if (calendarField == Calendar.DAY_OF_YEAR) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0);
}
else if (calendarField == Calendar.DAY_OF_WEEK) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0);
}
else if (calendarField == Calendar.DAY_OF_WEEK_IN_MONTH) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 24.0);
}
else if (calendarField == Calendar.AM_PM) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0 * 12.0);
}
else if (calendarField == Calendar.HOUR) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0);
}
else if (calendarField == Calendar.HOUR_OF_DAY) {
skipRateDouble = diffMillis / (1000.0 * 60.0 * 60.0);
}
else if (calendarField == Calendar.MINUTE) {
skipRateDouble = diffMillis / (1000.0 * 60.0);
}
else if (calendarField == Calendar.SECOND) {
skipRateDouble = diffMillis / (1000.0);
}
else if (calendarField == Calendar.MILLISECOND) {
skipRateDouble = diffMillis;
}
else {
throw new IllegalArgumentException("Unknown calendar field: " + calendarField + ".");
}
boolean done = false;
int skipRate = (int) Math.max(skipRateDouble, 1.0);
int difference = 0;
do {
while (startCal.before(endCal) || startCal.equals(endCal)) {
startCal.add(calendarField, skipRate);
difference += skipRate;
}
if (skipRate > 1) {
difference -= skipRate;
startCal.add(calendarField, -skipRate);
skipRate -= Math.ceil(skipRate / 2.0);
skipRate = Math.max(skipRate, 1);
}
else {
done = true;
}
} while (!done);
return difference;
}
public static String timestampString(NSTimestamp timestamp, boolean includeTime) {
String timestampString;
if (includeTime) {
if (timestamp != null) {
timestampString = new NSTimestampHelper().format(timestamp);
}
else {
timestampString = "";
}
}
else {
if (timestamp != null) {
timestampString = new NSTimestampHelper().mdy(timestamp);
}
else {
timestampString = "";
}
}
return timestampString;
}
public static String timeFrom(NSTimestamp time, NSTimestamp baseTime) {
return DurationNamer.timeFrom(time, baseTime);
}
public static String timeFromNow(NSTimestamp time) {
return DurationNamer.timeFromNow(time);
}
@SuppressWarnings("unchecked")
public static NSArray<Day> daysBetween(NSTimestamp start, NSTimestamp end) {
if (start == null && end == null) {
throw new IllegalArgumentException("Both start and end dates cannot be null");
}
if (start == null) {
return new NSArray(new Day(end));
}
if (end == null) {
return new NSArray(new Day(start));
}
if (DateUtils.isOnTheSameDay(start, end)) {
return new NSArray(new Day(start));
}
if (end.before(start)) {
NSTimestamp temp = start;
start = end;
end = temp;
}
NSMutableArray dates = new NSMutableArray();
Day loopDay = new Day(start);
Day startDay = new Day(start);
Day endDay = new Day(end);
while (loopDay.before(endDay)) {
dates.addObject(loopDay);
loopDay = loopDay.next();
}
dates.addObject(endDay);
return dates;
}
public static String durationStringForURL(NSTimestamp start, NSTimestamp end) {
int minutes = difference(start, end, Calendar.MINUTE);
int hours = minutes / 60;
minutes = minutes % 60;
String results = "";
results += String.format("%02d", Integer.valueOf(hours));
results += String.format("%02d", Integer.valueOf(minutes));
return results;
}
public static void main(String[] args) {
NSTimestamp start = new NSTimestamp();
NSTimestamp end = new NSTimestamp().timestampByAddingGregorianUnits(0, 0, 0, 0, 15, 0);
System.out.println("start: " + start);
System.out.println("end: " + end);
System.out.println("duration: " + DateUtils.durationStringForURL(start, end));
}
public static NSTimestamp nearestQuarterHour(NSTimestamp time) {
Calendar cal = Calendar.getInstance();
cal.setTime(time);
int minute = cal.get(Calendar.MINUTE);
int base = minute / 15;
if (minute % 15 > 7)
minute = 15;
else
minute = 0;
cal.set(Calendar.MINUTE, (base * 15) + minute);
return new NSTimestamp(cal.getTime());
}
public static NSTimestamp set(NSTimestamp timestamp, int calendarField, int value) {
Calendar cal = Calendar.getInstance();
cal.setTime(timestamp);
cal.set(calendarField, value);
return new NSTimestamp(cal.getTime());
}
public static NSTimestamp add(NSTimestamp timestamp, int calendarField, int value) {
Calendar cal = Calendar.getInstance();
cal.setTime(timestamp);
cal.add(calendarField, value);
return new NSTimestamp(cal.getTime());
}
}