问题描述
|
例如
日期范围从2月9日到5月19日为一个间隔。映射中还有另一个键值的有效日期列表,例如从此日期开始返回该对象的日期(1月1日,对象x,2月1日,对象y,3月1日,对象z)(4月1日,对象a)(5月1日,对象u),(6月1日,对象n)等
算法需要采取2月1日至6月19日的日期范围,并获取有效日期范围的相邻日期,例如
该方法将是
TreeMapreturnTemporalAdjacentInterval(间隔时间)
结果应为树图,按(Feb9-march1,对象y)(march1-April1,对象z)(April1-May1,对象a)(May1-May19,对象u)的相邻间隔进行排序
这就像马丁·福勒斯的时间收集,但是更多的是时间相邻间隔检索。语言是Java joda-time Interval建议用于返回的时间间隔。
解决方法
这是一个受Martin Fowlers时空对象启发的示例类,具有用于返回相邻间隔的方法实现。
public HashMap<Interval,Object> getAdjacentIntervals(Interval when)
这显示了具有一定复杂度的算法。更快版本上的任何输入。下面的单元测试显示了针对对象的测试并记录了更好的上下文
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.Interval;
public class TemporalCollection {
private Map<DateTime,Object> contents = new HashMap<DateTime,Object>();
private List<DateTime> _milestoneCache;
public Object get(DateTime when) {
/** returns the value that was effective on the given date */
Iterator<DateTime> it = milestones().iterator();
while (it.hasNext()) {
DateTime thisDate = it.next();
if (thisDate.isBefore(when) || thisDate.equals(when))
return contents.get(thisDate);
}
throw new IllegalArgumentException(\"no records that early\");
}
public HashMap<Interval,Object> getAdjacentIntervals(Interval when) {
// start to get the start date object
DateTime startDate = when.getStart();
DateTime endDate = when.getEnd();
HashMap<Interval,Object> result = new HashMap<Interval,Object>();
Iterator<DateTime> it = milestones().iterator();
DateTime endDateToCompare = endDate;
DateTime startDateToCompare = startDate;
while (it.hasNext()) {
DateTime thisDate = it.next();
if (thisDate.isBefore(endDateToCompare)
|| thisDate.equals(endDateToCompare)) {
Interval adjacentIntervalPart;
if (thisDate.isAfter(startDateToCompare) && !thisDate.equals(endDateToCompare)) {
// we have hit upper end of the range
// upper end of the adjacent interval is as follows
adjacentIntervalPart = new Interval(thisDate,endDateToCompare);
result.put(adjacentIntervalPart,contents.get(thisDate));
endDateToCompare = endDateToCompare.minus(new Duration(
thisDate,endDateToCompare));
} else {
// we have reached the last range
adjacentIntervalPart = new Interval(startDate,endDateToCompare);
result.put(adjacentIntervalPart,contents.get(thisDate));
return result;
}
}
}
throw new IllegalArgumentException(\"no records that early for an Interval\");
}
public void put(DateTime at,Object item) {
/** the item is valid and effective from the supplied date onwards */
contents.put(at,item);
clearMilestoneCache();
}
private List<DateTime> milestones() {
/**
* a list of all the dates where the value changed,returned in order
* latest first
*/
if (_milestoneCache == null)
calculateMilestones();
return _milestoneCache;
}
private void calculateMilestones() {
_milestoneCache = new ArrayList<DateTime>(contents.size());
_milestoneCache.addAll(contents.keySet());
Collections.sort(_milestoneCache,Collections.reverseOrder());
}
private void clearMilestoneCache() {
_milestoneCache = null;
}
}
单元测试类如下
import java.util.HashMap;
import java.util.Iterator;
import org.joda.money.Money;
import org.joda.time.DateMidnight;
import org.joda.time.Days;
import org.joda.time.Interval;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.vrntmgr.server.utils.StringUtils;
public class TemporalCollectionTest {
TemporalCollection rates;
@Before
public void setup() {
rates = new TemporalCollection();
rates.put(new DateMidnight(2010,1,1).toDateTime(),Money.parse(\"USD 900\"));
rates.put(new DateMidnight(2010,2,Money.parse(\"USD 1000\"));
rates.put(new DateMidnight(2010,3,Money.parse(\"USD 2000\"));
}
@Test
public void testTemporalRetreival() {
Interval intrvl = new Interval(new DateMidnight(2010,15),new DateMidnight(2010,15));
HashMap<Interval,Object> myMap = rates.getAdjacentIntervals(intrvl);
// System.out.println(StringUtils.toString(myMap.keySet()));
Iterator<Interval> it = myMap.keySet().iterator();
Assert.assertEquals(it.next(),new Interval(new DateMidnight(2010,1),15)));
Assert.assertEquals(it.next(),1)));
Assert.assertEquals(it.next(),1)));
}
@Test
public void testEndDayAfterRange() {
Interval intrvl = new Interval(new DateMidnight(2010,1));
HashMap<Interval,Object> myMap = rates.getAdjacentIntervals(intrvl);
Iterator<Interval> it = myMap.keySet().iterator();
Interval res = it.next();
Assert.assertEquals(res,1)));
System.out.println(\"days are\" + Days.daysIn(res));
}
}