I need to write the high performance function which calculates the new datetime based on given datetime and timeshift. It accept 2 arguments:
- String, representing the date in format YYYYMMDDHHmm
- 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,
- Parse and hold on to your fixed date, call it
fixedDate
- Let
timeShift
be a time shift in hours, thenDate shiftedDate = new Date(fixedDate.getTime() + (timeShift * 3600000))
would be your calculated shifted date (see this and this for understanding) - 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).
精彩评论