开发者

high performance function for date arithmetic

I need to write the high performance function which calculates the new datetime based on given datetime and timeshift. It accept 2 arguments:

  1. String, representing the date in format YYYYMMDDHHmm
  2. Integer, representing the timeshift in hours

Function returns the string in format of 1st argument which is composed as result of applying the timeshift to 1st argument

It is known in advance that the first argument is always the same during the program lifetime.

My implementation has the following steps:

  • parsing 1st argument to extract the year,month,date, hours,min
  • creating GregorianCalendar(year, month, date, hours, min) object
  • 开发者_运维知识库
  • applying method GregorianCalendar.add(HOUR,timeshift)
  • applying SimpleDateFormat to convert result back into string

Issue is that I do not take advantage from the fact that 1st argument is always the same. If I will create a class member GregorianCalendar(year, month, date, hours, min), then after the 1st call to my function this object will be modified, which is not good, because I cannot reuse it for the following calls.


If you can, use the Joda-Time library, which makes date arithmetic very simple:

  DateTime dt = new DateTime();
  DateTime twoHoursLater = dt.plusHours(2);

They have a DateTimeFormatter class that you'd use to do the parsing of your input date-time string into a DateTime, eg:

  DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMddHHmm");
  DateTime dt = fmt.parseDateTime(myDateString);
  DateTime result = dt.plusHours(myTimeshiftInHours);

And Joda-Time interoperates well with java.util.Date too. I love it!


If the first argument is a value that will not change often, perhaps use a cache :

static private Map<String,Calendar> dateCache = new HashMap<String,Calendar>();

Then, in your method, check of the first argument (ex: String dateStr) is a key in the cache

Calendar cal;
if (dateCache.containsKey(dateStr)) {
    cal = (Calendar)(dateCache.get(dateStr)).clone();
} else {
    // parse date
    cal = new GregorianCalendar(...);
    dateCache.put(dateStr, (Calendar)cal.clone());
}

And add your timeshift value.


How about this,

  1. Parse and hold on to your fixed date, call it fixedDate
  2. Let timeShift be a time shift in hours, then Date shiftedDate = new Date(fixedDate.getTime() + (timeShift * 3600000)) would be your calculated shifted date (see this and this for understanding)
  3. Apply SimpleDateFormat to convert shiftedDate to string.

Repeat steps 2 and 3 indefinitely, fixedDate is not modified and can be reused.


I'd try simple memoisation:

// This is not thread safe.  Either give each thread has its own 
// (thread confined) converter object, or make the class threadsafe.
public class MyDateConverter {

    private String lastDate;
    private int lastShift;
    private String lastResult;

    public String shiftDate(String date, int shift) {
        if (shift == lastShift && date.equals(lastDate)) {
            return lastResult;
        }
        // Your existing code here
        lastDate = date; 
        lastShift = shift
        lastResult = result;
        return result;
    }
}

Note this simple approach is most effective if the shift and date values rarely change. If either changes frequently, you'd need a more complicated cache, the code will be more complicated and the overheads (for a cache miss) will be higher.


If you simply want to avoid repeating step 1 (and maybe 2) again and again, parse the date once, then save the Date you get. You can then apply this date to your Calendar (with setDate()) before each add step again (or create a new GregorianCalendar, measure if it matters).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜