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クラスでモデル化できると思います。InstantPeriod、およびDurationの概念をサポートしています。

間隔は、あるミリ秒の瞬間から別の瞬間までの時間間隔を表します。両方のインスタントは、日時連続体の完全に指定されたインスタントであり、タイム ゾーンを備えています。

インスタントはタイムライン上の正確なポイントを表しますが、ミリ秒の精度に制限されています。

期間は、フィールドに関して定義された期間を表します。たとえば、3 年 5 か月 2 日 7 時間です。これは、ミリ秒単位では不正確であるという点で期間とは異なります。期間は、それが相対的な瞬間 (暦とタイムゾーンを含む) を指定することによってのみ、正確なミリ秒数に解決できます。

期間は、ミリ秒単位で測定された期間を表します。継続時間は、多くの場合、間隔から取得されます。

さらに、そのインターフェースは、overlapabutsgap 、および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 に答える