package OpenRate.utils; import OpenRate.CommonConfig; import OpenRate.resource.ConversionCache; import OpenRate.resource.ResourceContext; import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; /** * This class offers conversion and formatting methods (primarily for dates), so * that we have a simple single set conversion handling methods. * * @author ian */ public class ConversionUtils { // This is the format used for converting dates on input private String InputDateFormat = CommonConfig.OR_DEFAULT_DATE_FORMAT; // This is the format used for converting dates on input private String OutputDateFormat = CommonConfig.OR_DEFAULT_DATE_FORMAT; // format used for input private SimpleDateFormat sdfIn = null; // format used for output private SimpleDateFormat sdfOut = null; // set that we are using integer (UTC) format private boolean integerFormat = false; // set that we are using long format (UTC + ms) private boolean longFormat = false; // set that we are using long format (UTC + ms) private boolean stringFormat = true; // used for general date manipulation private final Calendar cal; // Used to cache access to the conversion objects private static ConversionCache tmpConvCache = null; // Singleton instance private static ConversionUtils convUtilsObj; /** * constructor - initialise the internal formatting object */ public ConversionUtils() { // This is the date format we are using for the output sdfOut = new SimpleDateFormat(OutputDateFormat); sdfOut.setLenient(false); // This is the date format we are using for the input sdfIn = new SimpleDateFormat(InputDateFormat); sdfIn.setLenient(false); // used for date manipulation cal = new GregorianCalendar(); } /** * Get the access to the singleton conversion cache * * @return Conversion Cache Reference */ public static ConversionCache getConversionCache() { if (tmpConvCache == null) { // Get access to the conversion cache ResourceContext ctx = new ResourceContext(); // try the new Logging model. tmpConvCache = (ConversionCache) ctx.get(ConversionCache.RESOURCE_KEY); } return tmpConvCache; } /** * Get the access to the singleton conversion utils object * * @return Conversion Cache Reference */ public static ConversionUtils getConversionUtilsObject() { if(convUtilsObj == null) { convUtilsObj = new ConversionUtils(); } return convUtilsObj; } //------------------------------------------------------------------------------ //---------------------------- Date Utilities ---------------------------------- //------------------------------------------------------------------------------ /** * Convert an amorphic string to a UTC date representation for input * * @param amorphicDate the amorphic date string to read and convert * @return The short UTC date format * @throws ParseException */ public long convertInputDateToUTC(String amorphicDate) throws ParseException { long tmpUTCDate = 0; if (integerFormat) { return Integer.parseInt(amorphicDate); } else if (longFormat) { return Long.parseLong(amorphicDate) / 1000; } else if (stringFormat) { if (amorphicDate == null) { return 0; } else { tmpUTCDate = sdfIn.parse(amorphicDate).getTime() / 1000; } } return tmpUTCDate; } /** * This converts the UTC date into day of week * * @param UTCDateValue The long UTC date the convert * @return The integer day of the week */ public int getDayOfWeek(long UTCDateValue) { cal.setTimeInMillis(UTCDateValue*1000); return cal.get(Calendar.DAY_OF_WEEK); } /** * Utility function to get the minute of the day from a long UTC value * * @param UTCDateValue The long UTC date the convert * @return The minute of the day */ public int getMinuteOfDay(long UTCDateValue) { cal.setTimeInMillis(UTCDateValue*1000); return cal.get(Calendar.HOUR_OF_DAY) * 60 + cal.get(Calendar.MINUTE); } /** * Sets the standard overall date format for input to a new value for this * converter. The allowed values here are: * "Integer" - take a UTC date (without milliseconds), * "Long" - take a UTC date with milliseconds * Other - any other value that can be treated as a date string using the * SimpleDateFormat formatting strings. * * @param newFormat The new format to adopt * @return True if the change was successful otherwise false */ public boolean setInputDateFormat(String newFormat) { if (newFormat.equalsIgnoreCase("integer")) { // set UTC format integerFormat = true; longFormat = false; stringFormat = false; } else if (newFormat.equalsIgnoreCase("long")) { // set UTC long format with milliseconds integerFormat = false; longFormat = true; stringFormat = false; } else { sdfIn = new SimpleDateFormat(newFormat); // set a string format integerFormat = false; longFormat = false; stringFormat = true; } // set the input date format InputDateFormat = newFormat; return true; } /** * Gets the standard overall date format for input * * @return The current date format string */ public String getInputDateFormat() { return InputDateFormat; } /** * Sets the standard overall date format for input to a new value for this * converter. The allowed values here are: * "Integer" - take a UTC date (without milliseconds), * "Long" - take a UTC date with milliseconds * Other - any other value that can be treated as a date string using the * SimpleDateFormat formatting strings. * * @param newFormat The new format to adopt * @return True if the change was successful otherwise false */ public boolean setOutputDateFormat(String newFormat) { if (newFormat.equalsIgnoreCase("integer")) { // set UTC format integerFormat = true; longFormat = false; stringFormat = false; } else if (newFormat.equalsIgnoreCase("long")) { // set UTC long format with milliseconds integerFormat = false; longFormat = true; stringFormat = false; } else { sdfOut = new SimpleDateFormat(newFormat); // set a string format integerFormat = false; longFormat = false; stringFormat = true; } // set the input date format OutputDateFormat = newFormat; return true; } /** * Gets the standard overall date format for output * * @return The current date format string */ public String getOutputDateFormat() { return OutputDateFormat; } /** * This formats a date given as a long into a standard string format * * @param dateToFormat The long date * @return The formatted date string */ public String formatLongDate(long dateToFormat) { return sdfOut.format(new Date(dateToFormat*1000)); } /** * This formats a date given as a Date into a standard string format * * @param dateToFormat The date value to format * @return The formatted date string */ public String formatLongDate(Date dateToFormat) { if (dateToFormat == null) { return "Null Date"; } else { return sdfOut.format(dateToFormat); } } /** * Converts a string in the standard date format to a date * * @param DateToFormat The date in the string format * @return The converted dagte * @throws java.text.ParseException */ public Date getDatefromLongFormat(String DateToFormat) throws ParseException { Date tmpDate = sdfIn.parse(DateToFormat); return tmpDate; } /** * This function converts a date to a GMT date * * @param date The date to convert * @return The date at GMT */ public Date getGmtDate( Date date ) { TimeZone tz = TimeZone.getDefault(); Date ret = new Date( date.getTime() - tz.getRawOffset() ); // if we are now in DST, back off by the delta. Note that we are // checking the GMT date, this is the KEY. if ( tz.inDaylightTime( ret )) { Date dstDate = new Date( ret.getTime() - tz.getDSTSavings() ); // check to make sure we have not crossed back into standard time // this happens when we are on the cusp of DST (7pm the day before // the change for PDT) if ( tz.inDaylightTime( dstDate )) { ret = dstDate; } } return ret; } /** * This function sees if a date is in Daylight Savings Time (DST) * * @param date The date the check * @return True if the date is in DST otherwise false */ public boolean getDateInDST( Date date ) { TimeZone tz = TimeZone.getDefault(); boolean RetValue = tz.inDaylightTime(date); return RetValue; } /** * Gets the rounded start date of the month the given event date is in * * @param EventStartDate The date of the event * @return The UTC month start date */ public long getUTCMonthStart(Date EventStartDate) { Date roundedDate = getMonthStart(EventStartDate); cal.setTime(roundedDate); long validityMonthStart = cal.getTimeInMillis() / 1000; return validityMonthStart; } /** * Gets the rounded end date of the month the given event date is in * * @param EventStartDate The date of the event * @return The UTC month end date */ public long getUTCMonthEnd(Date EventStartDate) { Date roundedDate = getMonthEnd(EventStartDate); cal.setTime(roundedDate); long validityMonthEnd = cal.getTimeInMillis() / 1000; return validityMonthEnd; } /** * Gets the rounded start date of the month the given event date is in * * @param EventStartDate The date of the event * @return The UTC month start date */ public Date getMonthStart(Date EventStartDate) { // Get the montly counter validity periods for this CDR cal.setTime(EventStartDate); cal.set(Calendar.HOUR_OF_DAY,0); cal.set(Calendar.MINUTE,0); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); cal.set(Calendar.SECOND,0); cal.set(Calendar.DATE,1); return cal.getTime(); } /** * Gets the rounded end date of the month the given event date is in * * @param EventStartDate The date of the event * @return The UTC month end date */ public Date getMonthEnd(Date EventStartDate) { // Get the montly counter validity periods for this CDR cal.setTime(EventStartDate); cal.set(Calendar.HOUR_OF_DAY,0); cal.set(Calendar.MINUTE,0); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); cal.set(Calendar.DATE,1); cal.add(Calendar.MONTH,1); cal.add(Calendar.SECOND,-1); return cal.getTime(); } /** * Gets the rounded start date of the year the given event date is in * * @param EventStartDate * The date of the event * @return The UTC year start date */ public long getUTCYearStart(Date EventStartDate) { Date roundedDate = getYearStart(EventStartDate); cal.setTime(roundedDate); long validityYearStart = cal.getTimeInMillis() / 1000; return validityYearStart; } /** * Gets the rounded end date of the year the given event date is in * * @param EventStartDate * The date of the event * @return The UTC year end date */ public long getUTCYearEnd(Date EventStartDate) { Date roundedDate = getYearEnd(EventStartDate); cal.setTime(roundedDate); long validityYearEnd = cal.getTimeInMillis() / 1000; return validityYearEnd; } /** * Gets the rounded start date of the year the given event date is in * * @param EventStartDate * The date of the event * @return The year start date */ public Date getYearStart(Date EventStartDate) { // Get the yearly counter validity periods for this CDR cal.setTime(EventStartDate); cal.set(Calendar.DAY_OF_YEAR, 1); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); return cal.getTime(); } /** * Gets the rounded end date of the year the given event date is in * * @param EventStartDate * The date of the event * @return The year end date */ public Date getYearEnd(Date EventStartDate) { // Get the yearly counter validity periods for this CDR cal.setTime(EventStartDate); cal.set(Calendar.DAY_OF_YEAR, 366); // 366 for leap year cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.add(Calendar.SECOND, -1); return cal.getTime(); } /** * Gets the rounded start date of the month the given event date is in * * @param EventStartDate The date of the event * @return The UTC month start date */ public long getUTCDayStart(Date EventStartDate) { Date roundedDate = getDayStart(EventStartDate); cal.setTime(roundedDate); long validityDayStart = cal.getTimeInMillis() / 1000; return validityDayStart; } /** * Gets the rounded start date of the month the given event date is in * * @param EventStartDate The date of the event * @param offset The number of days to offset by * @return The UTC month start date */ public long getUTCDayStart(Date EventStartDate, int offset) { Date roundedDate = getDayEnd(EventStartDate,offset); cal.setTime(roundedDate); long validityDayStart = cal.getTimeInMillis() / 1000; return validityDayStart; } /** * Gets the UTC date of the given event date * * @param EventStartDate The date of the event * @return The UTC representation of the date */ public long getUTCDate(Date EventStartDate) { // Get the montly counter validity periods for this CDR cal.setTime(EventStartDate); long validityDayStart = cal.getTimeInMillis() / 1000; return validityDayStart; } /** * Gets the Java date of the given event date from the UTC Event Date * * @param EventStartDate The UTC date of the event * @return The start date */ public Date getDateFromUTC(long EventStartDate) { // Get the montly counter validity periods for this CDR cal.setTimeInMillis(EventStartDate*1000); return cal.getTime(); } /** * Gets the rounded end date of the month the given event date is in * * @param EventStartDate The date of the event * @return The UTC month end date */ public long getUTCDayEnd(Date EventStartDate) { Date roundedDate = getDayEnd(EventStartDate); cal.setTime(roundedDate); long validityDayEnd = cal.getTimeInMillis() / 1000; return validityDayEnd; } /** * Gets the rounded end date of the month the given event date is in * * @param EventStartDate The date of the event * @param offset The number of days in the future (past) to get the end date for * @return The UTC month end date */ public long getUTCDayEnd(Date EventStartDate, int offset) { Date roundedDate = getDayEnd(EventStartDate,offset); cal.setTime(roundedDate); long validityDayEnd = cal.getTimeInMillis() / 1000; return validityDayEnd; } /** * Gets the rounded start date of the month the given event date is in * * @param EventStartDate The date of the event * @param offset The number of days to offset by * @return The UTC month start date */ public Date getDayStart(Date EventStartDate , int offset) { // Get the montly counter validity periods for this CDR cal.setTime(EventStartDate); cal.set(Calendar.HOUR_OF_DAY,0); cal.set(Calendar.MINUTE,0); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); cal.add(Calendar.DAY_OF_MONTH,offset); return cal.getTime(); } /** * Gets the rounded end date of the month the given event date is in * * @param EventStartDate The date of the event * @param offset The number of days in the future (past) to get the end date for * @return The UTC month end date */ public Date getDayEnd(Date EventStartDate, int offset) { // Get the montly counter validity periods for this CDR cal.setTime(EventStartDate); cal.set(Calendar.HOUR_OF_DAY,0); cal.set(Calendar.MINUTE,0); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); cal.add(Calendar.DATE,1); cal.add(Calendar.SECOND,-1); cal.add(Calendar.DAY_OF_MONTH,offset); return cal.getTime(); } /** * Gets the rounded start date of the month the given event date is in * * @param EventStartDate The date of the event * @return The UTC month start date */ public Date getDayStart(Date EventStartDate ) { // Get the montly counter validity periods for this CDR cal.setTime(EventStartDate); cal.set(Calendar.HOUR_OF_DAY,0); cal.set(Calendar.MINUTE,0); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); return cal.getTime(); } /** * Gets the rounded end date of the month the given event date is in * * @param EventStartDate The date of the event * @return The UTC month end date */ public Date getDayEnd(Date EventStartDate) { // Get the montly counter validity periods for this CDR cal.setTime(EventStartDate); cal.set(Calendar.HOUR_OF_DAY,0); cal.set(Calendar.MINUTE,0); cal.set(Calendar.SECOND,0); cal.set(Calendar.MILLISECOND,0); cal.add(Calendar.DATE,1); cal.add(Calendar.SECOND,-1); return cal.getTime(); } /** * Return the current timestamp * * @return the current UTC date in millseconds */ public long getCurrentUTCms() { return Calendar.getInstance().getTimeInMillis(); } /** * Return the current timestamp * * @return the current UTC date in seconds */ public long getCurrentUTC() { return getCurrentUTCms() / 1000; } /** * Add seconds to a date to get a new date * * @param inputDate The date to adjust * @param duration The number of seconds offset * @return The adjusted date */ public Date addDateSeconds(Date inputDate, int duration) { cal.setTime(inputDate); cal.add(Calendar.SECOND, duration); return cal.getTime(); } /** * Add seconds to a date to get a new date * * @param inputDate The date to adjust * @param duration The number of seconds offset * @return The adjusted date */ public Date addDateSeconds(Date inputDate, long duration) { cal.setTime(inputDate); cal.add(Calendar.SECOND, (int) duration); return cal.getTime(); } /** * Add seconds to a date to get a new date * * @param inputDate The date to adjust * @param duration The number of seconds offset * @return The adjusted date */ public Date addDateSeconds(Date inputDate, double duration) { cal.setTime(inputDate); cal.add(Calendar.SECOND, (int) duration); return cal.getTime(); } //------------------------------------------------------------------------------ //----------------------- Floating Point Utilities ----------------------------- //------------------------------------------------------------------------------ /** * Perform standard rounding on a double value. This rounding rounds UP if * the last digit after the last decimal place to round is >=5 * * @param valueToRound The unrounded value * @param decimalPlaces The number of decimal places to round to * @return The rounded value */ public double getRoundedValue(double valueToRound, int decimalPlaces) { double helper; int exponent; // Because of rounding errors in the floating point, we round to // one more decimal place than required exponent = (int) Math.pow(10, decimalPlaces); helper = Math.round((Math.round(valueToRound*10*exponent) + 5) / 10); return helper/exponent; } /** * Perform standard rounding on a double value. This rounding rounds UP to the * next largest value (away from zero) * * @param valueToRound The unrounded value * @param decimalPlaces The number of decimal places to round to * @return The rounded value */ public double getRoundedValueRoundUp(double valueToRound, int decimalPlaces) { // Convert input value BigDecimal tmpValue = new BigDecimal(valueToRound); return tmpValue.setScale(decimalPlaces,BigDecimal.ROUND_UP).doubleValue(); } /** * Perform standard rounding on a double value. This rounding rounds DOWN to the * next smallest value (towards zero) * * @param valueToRound The unrounded value * @param decimalPlaces The number of decimal places to round to * @return The rounded value */ public double getRoundedValueRoundDown(double valueToRound, int decimalPlaces) { // Convert input value BigDecimal tmpValue = new BigDecimal(valueToRound); return tmpValue.setScale(decimalPlaces,BigDecimal.ROUND_DOWN).doubleValue(); } /** * Perform standard rounding on a double value. This rounding rounds HALF EVEN. * Half Even rounding is good for financial applications where the rounding * e.g. 2.12345 to 2.1235 would cause a bias over time. * * @param valueToRound The unrounded value * @param decimalPlaces The number of decimal places to round to * @return The rounded value */ public double getRoundedValueRoundHalfEven(double valueToRound, int decimalPlaces) { // Convert input value BigDecimal tmpValue = new BigDecimal(valueToRound); return tmpValue.setScale(decimalPlaces,BigDecimal.ROUND_HALF_EVEN).doubleValue(); } /** * For handling different time zone conversions. * * @param newTimeZone The tome zone to set */ public void setTimeZone(TimeZone newTimeZone) { cal.setTimeZone(newTimeZone); } }