2

想象一下,如果您想对非分数时间范围进行建模,则可以是以下任何一种:

"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 小时期间的基线。

另一个考虑因素是这些基线周期将存储在无 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;
}
4

1 回答 1

5

抽象

我认为你所描述的可以用Joda TimeInterval类来建模。它支持Instant s、Period s 和Duration s 的概念:

间隔表示从一个毫秒瞬间到另一个瞬间的时间间隔。这两个瞬间都是日期时间连续体中完全指定的瞬间,并带有时区。

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

周期表示以字段定义的时间段,例如 3 年 5 个月 2 天 7 小时。这与持续时间的不同之处在于它在毫秒方面是不精确的。一个周期只能通过指定它相对的瞬间(包括年表和时区)来解析为精确的毫秒数。

持续时间表示以毫秒为单位测量的持续时间。持续时间通常是从一个间隔中获得的。

此外,它的接口支持AbstractInterval中定义的重叠邻接间隙Interval关系方法。

您可能还想为您的方法考虑Partial ,这在此处进行了一般性解释。这将对您有所帮助,因为:

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

例子

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

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);
    }

}
于 2012-10-13T23:58:48.747 回答