/*******************************************************************************
* Copyright © 2012-2015 eBay Software Foundation
* This program is dual licensed under the MIT and Apache 2.0 licenses.
* Please see LICENSE for more information.
*******************************************************************************/
/**
*
*/
package com.ebay.jetstream.util;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* Miscellaneous date-time support routines.
*
*
*/
public class DateUtil {
/**
* Parses a specific ISO 8601 extended-format date-time string, format == "yyyy-MM-dd'T'HH:mm:ss" and returns the
* resulting Date object.
*
* FIX: In order to make EPL nested calls like:
* com.ebay.jetstream.util.DateUtil.getMillisFromISO8601(com.ebay.jetstream.epl
* .EPLUtilities.getAttributeValue(attributes.values, 'marketplace.transaction_date')) possible, we need this guy to
* be able to accept Object which is a string actually
*
* FIX for 5827 - we have support both 'T'-separated and ' '-separated formats
*
* FIX for 11878 - now supported all 4 possible formats
*
* @param iso8601
* an extended format ISO 8601 date-time string.
*
* @return the Date object for the ISO 8601 date-time string.
*
* @throws ParseException
* if the date could not be parsed.
*/
private static final SimpleDateFormat[] s_formats = { new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"),
new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss'Z'"), new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"),
new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss") };
private static final SimpleDateFormat[] s_formatsYMD = { new SimpleDateFormat("yyyy-MM-dd"),
new SimpleDateFormat("yyyy-MM") };
public static Date getDateFromISO8601(Object iso8601) throws ParseException {
if (iso8601 == null)
return null;
String sdate = iso8601.toString();
// "2009-12-04T23:29:06" -> 0 1 -> 2
// "2009-12-04 23:29:06" -> 0 0 -> 3
// "2009-12-04T23:29:06Z" -> 2 1 -> 0
// "2009-12-04 23:29:06Z" -> 2 0 -> 1
final int a = sdate.indexOf('Z') >= 0 ? 2 : 0;
final int b = sdate.indexOf('T') >= 0 ? 1 : 0;
SimpleDateFormat formatter = s_formats[3 - a - b];
synchronized (formatter) {
return formatter.parse(sdate);
}
// I did check this option too. It's slightly worse in terms of performance
// and much worse in terms of memory consumption, thus synchronized option was chosen.
// SimpleDateFormat is quite heavy guy to instantiate it every time, that's why.
// And it's not thread safe. :(
// return new SimpleDateFormat(s_formats[3 - a - b]).parse(sdate);
}
/**
*
* FIX: In order to make EPL nested calls, we need this guy to be able to accept Object which is a string actually
*
* @param rfc822
* An rfc 822 (section 5) date-time string.
*
* @return the Unix epoch date-time for the given RFC 822 date-time string.
*
* @throws ParseException
* if the date could not be parsed.
*/
public static Date getDateFromRFC822String(Object rfc822) throws ParseException {
return rfc822 == null ? null : new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy").parse(rfc822.toString());
}
/**
* Helper parsing two kinds of dates:<br>
* 1. YYYY-MM-DD -> returns 00:00:00 (midnight) of this day <br>
* 2. YYYY-MM -> returns 23:59:59 of THE LAST DAY of this month - this is for credit card expirations<br>
*
* @param yyyymmdd
* @return Date
* @throws ParseException
*/
public static Date getDateYYYYMMDD(Object yyyymmdd) throws ParseException {
if (yyyymmdd == null)
return null;
String sdate = yyyymmdd.toString();
if (sdate.lastIndexOf('-') > sdate.indexOf('-')) {
SimpleDateFormat formatter = s_formatsYMD[0];
synchronized (formatter) { // yes, it's better: see comment in getDateFromISO8601
return formatter.parse(sdate);
}
}
// otherwise we get the very last second credit card is valid at
Calendar calendar = Calendar.getInstance();
SimpleDateFormat formatter = s_formatsYMD[1];
synchronized (formatter) { // yes, it's better: see comment in getDateFromISO8601
calendar.setTime(formatter.parse(sdate));
}
int lastDay = calendar.getActualMaximum(Calendar.DATE);
calendar.set(Calendar.DATE, lastDay);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
return calendar.getTime();
}
/**
*
* FIX: In order to make EPL nested calls like:
* com.ebay.jetstream.util.DateUtil.getMillisFromISO8601(com.ebay.jetstream.epl
* .EPLUtilities.getAttributeValue(attributes.values, 'marketplace.transaction_date')) possible, we need this guy to
* be able to accept Object which is a string actually
*
*
* @param iso8601
* an extended format ISO 8601 date-time string.
*
* @return the Unix epoch date-time for the given ISO 8601 date-time string.
*
* @throws ParseException
* if the date could not be parsed.
*/
public static Long getMillisFromISO8601(Object iso8601) throws ParseException {
Date iso8601Date = getDateFromISO8601(iso8601);
return iso8601Date == null ? null : iso8601Date.getTime();
}
/**
*
* FIX: In order to make EPL nested calls, we need this guy to be able to accept Object which is a string actually
*
* @param rfc822
* An rfc 822 (section 5) date-time string.
*
* @return the Unix epoch date-time for the given RFC 822 date-time string.
*
* @throws ParseException
* if the date could not be parsed.
*/
public static Long getMillisFromRFC822String(Object rfc822) throws ParseException {
Date rfc822Date = getDateFromRFC822String(rfc822);
return rfc822Date == null ? null : rfc822Date.getTime();
}
/**
* Helper parsing two kinds of dates:<br>
* 1. YYYY-MM-DD -> returns 00:00:00 (midnight) of this day <br>
* 2. YYYY-MM -> returns 23:59:59 of THE LAST DAY of this month - this is for credit card expirations<br>
*
* @param yyyymmdd
* @return Long (milliseconds)
* @throws ParseException
*/
public static Long getMillisFromYYYYMMDD(Object yyyymmdd) throws ParseException {
Date date = getDateYYYYMMDD(yyyymmdd);
return date == null ? null : date.getTime();
}
/**
* Returns current time in milliseconds for EPL
*
* @return Long
*/
public static Long getTimeInMillis() {
Calendar calendar = Calendar.getInstance();
return calendar.getTimeInMillis();
}
private DateUtil() {
}
}