如何对通常的时间范围进行建模,以允许任何时间段或更具体的时间段的范围

时间:2012-10-13 23:51:43

标签: java time data-modeling baseline

想象一下,如果你想模拟一个非分数时间范围,可能是以下任何一个:

"1 hour" (all/any 1 hour period)
"1 hour, starting 1pm")  (all/any 1 hour periods that start at 1pm)
"1 hour, starting 1pm, on Wednesdays" (all/any 1 hour periods that start at 1pm on wednesdays)
"1 hour, starting 1pm, on 3rd Wednesday in November"
"1 week, starting the first week in November"

你明白了。另一个目标是轻松有效地计算这些范围的重叠和子集。例如“1小时,从星期三下午1点开始”与“1小时,从下午1点开始”重叠

其他信息:这适用于基线系统中的时间段。我希望基线段具有多个粒度的时间段。如同下午1点的任何1小时时段的基线或11月3日星期三下午1点开始的1小时时段的基线。

另外一个考虑因素是这些基线周期将存储在no-sql存储中,并且以存储中存在的最小粒度有效地细化周期会很好。 (特定的日 - 周 - 小时期间是否存在?不,周小时怎么样?,不是?如何只是一小时的时间段 - 如果这是有道理的。也许是某种树状的层次结构。

编辑:存储和查询部分可能是最重要的要求。将存储数十亿个时间段,并且需要尽可能快地查找它们(找到最精细的粒度)。我很乐意为了提高速度而牺牲完整性。

编辑:考虑更多,以及如何将其存储在数据存储区中,树状结构可能有利于高效查找。我可以沿着树走下去,以获得最好的粒度。

          1hr
          /
       1hr@1pm
       /
     1hr@1pm@wednesday
     /
   1hr@1pm@wednesday@November

这是我想出来的,但我觉得它很弱。我将继续摆弄它并在这里进行更新,但我很想知道是否有人有更聪明的方法对此进行建模。

public class DateRange {

    Integer fTimeSpan;
    TimeUnit fTimeUnit;
    Integer fStartHour;
    Integer fStartDay;
    Integer fStartWeek;
    Integer fStartMonth;

    boolean intersects(DateRange other) { ... }

}
enum TimeUnit {
    HOURS,
    DAYS,
    WEEKS,
    MONTHS;

}

编辑:基于树的结构(就像我上面的编辑一样)会简单得多。没有未使用的字段用于大粒度跨度。粒度将在树中,而不是在数据结构中......

public class RangeTreeNode {

    TimeUnit fTimeUnit;
    int fStartTime;
    int fSpanTime;
    List<RangeTreeNode> fChildren;
}

1 个答案:

答案 0 :(得分:5)

抽象

我认为您所描述的内容可以使用Joda TimeInterval课程进行建模。它支持Instant s,PeriodDuration s的概念:

  

间隔表示从1开始的时间间隔   毫秒瞬间到另一个瞬间。两个时刻都是完整的   日期时间连续统中的指定时刻,包括时区。

     

瞬间表示时间线上的精确点,但仅限于毫秒精度。

     

期间表示按术语定义的时间段   田地,例如,3年5个月2天7小时。这个   不同于持续时间,因为它是不精确的   毫秒。句点只能解析为确切的数字   指定瞬间(包括时间顺序和时间)的毫秒数   区域)它是相对的。

     

持续时间表示测量的持续时间   毫秒。持续时间通常是从一个区间获得的。

此外,它的界面支持overlap中定义的abutsgapAbstractInterval和其他Interval关系方法。

您可能还需要考虑Partial的方法,一般用here来解释。这将对您有所帮助:

  

部分未完全指定日期时间中的单个点   连续体,但可以匹配多个点(部分+缺失字段+时区=即时)

实施例

与您原始问题相关的一些示例:

import static org.joda.time.DateTimeConstants.NOVEMBER;
import static org.joda.time.DateTimeConstants.WEDNESDAY;
import static org.joda.time.DateTimeFieldType.dayOfMonth;
import static org.joda.time.DateTimeFieldType.dayOfWeek;
import static org.joda.time.DateTimeFieldType.hourOfDay;
import static org.joda.time.DateTimeFieldType.monthOfYear;
import static org.joda.time.Duration.standardDays;
import static org.joda.time.Duration.standardHours;

import org.joda.time.Duration;
import org.joda.time.Partial;

public class Periods {

    public static void main(String[] args) {

        // "1 hour" (all/any 1 hour period)
        Duration d1 = standardHours(1);
        Partial p1 = new Partial();

        // "1 hour, starting 1pm" (all/any 1 hour periods that start at 1pm)
        Duration d2 = standardHours(1);
        Partial p2 = new Partial().withField(hourOfDay(), 13);

        // "1 hour, starting 1pm, on Wednesdays" (all/any 1 hour periods that start at 1pm on Eednesdays)
        Duration d3 = standardHours(1);
        Partial p4 = new Partial().withField(hourOfDay(), 13).withField(hourOfDay(), 1).withField(dayOfWeek(), WEDNESDAY);

        // "1 hour, starting 1pm, on Wednesday in November"
        Duration d4 = standardHours(1);
        Partial p3 = new Partial().withField(hourOfDay(), 13).withField(hourOfDay(), 1).withField(dayOfWeek(), WEDNESDAY).withField(monthOfYear(), NOVEMBER);

        // "1 week, starting the first week in November"
        Duration d5 = standardDays(7);
        Partial p5 = new Partial().withField(dayOfMonth(), 1).withField(monthOfYear(), NOVEMBER);
    }

}