2017-03-10 6 views
0

開始日、終了日、および周期性を考慮して、Joda Timeを使用して間隔のリストを取得できますか?毎週の期間とJoda Timeで指定された周期性を使用した間隔のリストを取得

例:

* start date: WED 2017-03-01 00:00 
* end date: TUE 2017-03-14 00:00 
* periodicity: MON 04:00 - WED 06:00 

結果は、開始日と終了日に収まるすべての期間も、その例にかかる必要があります。

WED 2017-03-01 00:00 - WED 2017-03-01 06:00 
MON 2017-03-06 04:00 - WED 2017-03-08 06:00 
MON 2017-03-13 04:00 - TUE 2017-03-14 00:00 

誰もが行う方法を知っていますそれはジョーダ時代?好ましくは一般的な、すなわち、 e。毎日/毎週/毎月/毎年のような期間の他のタイプと一緒に

ありがとう、あなたの専門知識のために!

答えて

0

ジョーダタイムを掘り下げた後、自分自身で解決策を見つけました。私はここにそれを掲示します、他の誰かがそれを必要とするかもしれません。 Joda Timeをよく知っている人がこれをチェックする場合は、コードを改善してください。

アルゴリズム:

  • が与えられた期間
  • を使用してパーシャルを作成期間開始日にパーシャルを適用すると、彼らは前になるよう
  • シフトに期間開始日と終了日の両方を、期間開始日と終了日を作成期間開始日の前にある場合は、
  • 期間開始までの期間を開始します日付は間隔の終了日の後です

私は実際に自分の計算をしたくないので、アルゴリズムはAPIのみを使用し、最適化を使用することができます。 g。曜日を取得するためのfor-loop)。

ので、場合には、誰もがコードを必要とし、ここにある:

Periodicity.java

import org.joda.time.DurationFieldType; 

/** 
* Supported periodicity: daily, weekly, yearly, week of year 
*/ 
public enum Periodicity { 

    DAILY(DurationFieldType.days(), 1), 
    WEEKLY(DurationFieldType.weeks(), 1), 
    YEARLY(DurationFieldType.years(), 1), 
    WEEK_OF_YEAR(DurationFieldType.weekyears(), 1), 
    ; 

    DurationFieldType durationFieldType; 
    int durationAmount; 

    private Periodicity(DurationFieldType durationFieldType, int durationAmount) { 
     this.durationFieldType = durationFieldType; 
     this.durationAmount = durationAmount; 
    } 

    public DurationFieldType getDurationFieldType() { 
     return durationFieldType; 
    } 

    public int getDurationAmount() { 
     return durationAmount; 
    } 

} 

IntervalCreator.java

import java.util.ArrayList; 
import java.util.List; 

import org.joda.time.DateTime; 
import org.joda.time.DateTimeConstants; 
import org.joda.time.DateTimeFieldType; 
import org.joda.time.DateTimeZone; 
import org.joda.time.DurationFieldType; 
import org.joda.time.Interval; 
import org.joda.time.MutableDateTime; 
import org.joda.time.Partial; 

public class IntervalCreator { 

    MutableDateTime startInstant; 
    MutableDateTime endInstant; 
    Partial startPartial; 
    Partial endPartial; 
    DurationFieldType durationFieldType; 
    int durationAmount; 

    MutableDateTime mutableStartInstant; 
    MutableDateTime mutableEndInstant; 

    public IntervalCreator(DateTime startInstant, DateTime endInstant, Partial startPartial, Partial endPartial, Periodicity periodicity) { 

     this.startInstant = new MutableDateTime(startInstant, DateTimeZone.UTC); 
     this.endInstant = new MutableDateTime(endInstant, DateTimeZone.UTC); 
     this.startPartial = startPartial; 
     this.endPartial = endPartial; 
     this.durationFieldType = periodicity.getDurationFieldType(); 
     this.durationAmount = periodicity.getDurationAmount(); 
    } 

    /** 
    * Apply partial datetime to given instant 
    * @param mutableInstant 
    * @param partial 
    */ 
    private void applyPartial(MutableDateTime mutableInstant, Partial partial) { 

     for (int i = 0; i < partial.getFields().length; i++) { 

      DateTimeFieldType fieldType = partial.getFieldTypes()[i]; 

      if (fieldType == DateTimeFieldType.dayOfWeek()) { 

       // find day of week by going backwards in time 
       // in opposite to DateTime the MutableDateTime doesn't have a withDayOfWeek() method 
       int dayOfWeek = partial.getValue(i); 

       while (mutableInstant.getDayOfWeek() != dayOfWeek) { 
        mutableInstant.addDays(-1); 
       } 

      } else if (fieldType == DateTimeFieldType.minuteOfDay()) { 

       mutableInstant.setMinuteOfHour(partial.getValue(i)); 

      } else if (fieldType == DateTimeFieldType.hourOfDay()) { 

       mutableInstant.setHourOfDay(partial.getValue(i)); 

      } else if (fieldType == DateTimeFieldType.dayOfMonth()) { 

       mutableInstant.setDayOfMonth(partial.getValue(i)); 

      } else if (fieldType == DateTimeFieldType.monthOfYear()) { 

       mutableInstant.setMonthOfYear(partial.getValue(i)); 

      } else if (fieldType == DateTimeFieldType.weekOfWeekyear()) { 

       mutableInstant.setWeekOfWeekyear(partial.getValue(i)); 
       mutableInstant.setDayOfWeek(DateTimeConstants.MONDAY); // reset weekday to monday 

      } else { 

       throw new IllegalArgumentException("Illegal DateTimeFieldType: " + fieldType); 

      } 
     } 

    } 

    /** 
    * Add specified duration 
    * @param instant 
    */ 
    private void nextInstant(MutableDateTime instant) { 
     addDuration(instant, durationAmount); 
    } 

    /** 
    * Subtract specified duration 
    * @param instant 
    */ 
    private void previousInstant(MutableDateTime instant) { 
     addDuration(instant, -durationAmount); 
    } 

    /** 
    * Convenience method to add a duration to an instant 
    * @param instant 
    * @param amount 
    */ 
    private void addDuration(MutableDateTime instant, int amount) { 

     if (durationFieldType == DurationFieldType.days()) { 
      instant.addDays(amount); 
     } else if (durationFieldType == DurationFieldType.weeks()) { 
      instant.addWeeks(amount); 
     } else if (durationFieldType == DurationFieldType.years()) { 
      instant.addYears(amount); 
     } else if (durationFieldType == DurationFieldType.weekyears()) { 
      instant.addWeekyears(amount); 
     } else { 
      throw new IllegalArgumentException("Illegal duration field type: " + durationFieldType); 
     } 

    } 

    /** 
    * Create interval slices 
    * @return 
    */ 
    public List<Interval> createIntervals() { 

     this.mutableStartInstant = new MutableDateTime(startInstant, DateTimeZone.UTC); 
     this.mutableEndInstant = new MutableDateTime(endInstant, DateTimeZone.UTC); 

     applyPartial(mutableStartInstant, startPartial); 
     applyPartial(mutableEndInstant, endPartial); 

     List<Interval> list = new ArrayList<>(); 

     // search previous valid start date before the global start date 
     while (mutableStartInstant.isAfter(startInstant)) { 
      previousInstant(mutableStartInstant); 
     } 

     // search previous valid end date 
     while (mutableEndInstant.isAfter(startInstant)) { 
      previousInstant(mutableEndInstant); 
     } 

     // correct the end date in case it is before the start date (e. g. if 
     // you have 22:00 - 02:00; or 00:00 - 00:00) 
     if (mutableEndInstant.compareTo(mutableStartInstant) <= 0) { 
      nextInstant(mutableEndInstant); 
     } 

     // advance in period steps until the local start date exceeds the 
     // global end date 
     while (mutableStartInstant.compareTo(endInstant) < 0) { 

      // clip local start date at global start date bounds, if 
      // necessary 
      MutableDateTime clippedStartDate = mutableStartInstant; 
      if (mutableStartInstant.compareTo(startInstant) <= 0 && mutableEndInstant.compareTo(startInstant) >= 0) { 
       clippedStartDate = startInstant; 
      } 

      // clip local end date at global end date bounds, if necessary 
      MutableDateTime clippedEndDate = mutableEndInstant; 
      if (mutableStartInstant.compareTo(endInstant) <= 0 && mutableEndInstant.compareTo(endInstant) >= 0) { 
       clippedEndDate = endInstant; 
      } 

      // create period; ensure the interval is valid (it might not be 
      // if the initial interval is entirely before the global start date 
      if (clippedStartDate.compareTo(startInstant) >= 0 && clippedEndDate.compareTo(endInstant) <= 0) { 

       Interval period = new Interval(clippedStartDate, clippedEndDate); 

       list.add(period); 

      } 

      // next duration 
      nextInstant(mutableStartInstant); 
      nextInstant(mutableEndInstant); 

     } 

     return list; 

    } 

} 

JodaTimeTestをテストするためのクラス.java

import java.util.List; 
import java.util.Locale; 

import org.joda.time.DateTime; 
import org.joda.time.DateTimeConstants; 
import org.joda.time.DateTimeFieldType; 
import org.joda.time.DateTimeZone; 
import org.joda.time.Interval; 
import org.joda.time.Partial; 
import org.joda.time.format.DateTimeFormat; 
import org.joda.time.format.DateTimeFormatter; 

public class JodaTimeTest { 

    public static DateTimeFormatter formatter = DateTimeFormat.forPattern("w E yyyy-MM-dd HH:mm"); 

    public static List<Interval> createDailyPeriod() { 

     DateTime startInstant = new DateTime(2017, 3, 22, 0, 0, 0, 0, DateTimeZone.UTC); 
     DateTime endInstant = new DateTime(2017, 3, 30, 0, 0, 0, 0, DateTimeZone.UTC); 

     DateTimeFieldType[] fields = new DateTimeFieldType[] { DateTimeFieldType.hourOfDay(), DateTimeFieldType.minuteOfDay() }; 
     Partial startPartial = new Partial(fields, new int[] { 23, 0 }); 
     Partial endPartial = new Partial(fields, new int[] { 2, 0 }); 

     IntervalCreator intervalCreator = new IntervalCreator(startInstant, endInstant, startPartial, endPartial, Periodicity.DAILY); 
     List<Interval> intervals = intervalCreator.createIntervals(); 

     log(intervals); 

     return intervals; 

    } 

    public static List<Interval> createWeeklyPeriod() { 

     DateTime startInstant = new DateTime(2017, 3, 1, 0, 0, 0, 0, DateTimeZone.UTC); 
     DateTime endInstant = new DateTime(2017, 3, 14, 0, 0, 0, 0, DateTimeZone.UTC); 

     DateTimeFieldType[] fields = new DateTimeFieldType[] { DateTimeFieldType.dayOfWeek(), DateTimeFieldType.hourOfDay(), DateTimeFieldType.minuteOfDay() }; 
     Partial startPartial = new Partial(fields, new int[] { DateTimeConstants.MONDAY, 4, 0 }); 
     Partial endPartial = new Partial(fields, new int[] { DateTimeConstants.WEDNESDAY, 6, 0 }); 

     IntervalCreator intervalCreator = new IntervalCreator(startInstant, endInstant, startPartial, endPartial, Periodicity.WEEKLY); 
     List<Interval> intervals = intervalCreator.createIntervals(); 

     log(intervals); 

     return intervals; 

    } 

    public static List<Interval> createYearlyPeriod() { 

     DateTime startInstant = new DateTime(2012, 3, 1, 0, 0, 0, 0, DateTimeZone.UTC); 
     DateTime endInstant = new DateTime(2017, 3, 14, 0, 0, 0, 0, DateTimeZone.UTC); 

     DateTimeFieldType[] fields = new DateTimeFieldType[] { DateTimeFieldType.monthOfYear(), DateTimeFieldType.dayOfMonth(), DateTimeFieldType.hourOfDay(), DateTimeFieldType.minuteOfDay() }; 
     Partial startPartial = new Partial(fields, new int[] { 2, 27, 4, 0 }); 
     Partial endPartial = new Partial(fields, new int[] { 3, 16, 6, 0 }); 

     IntervalCreator intervalCreator = new IntervalCreator(startInstant, endInstant, startPartial, endPartial, Periodicity.YEARLY); 
     List<Interval> intervals = intervalCreator.createIntervals(); 

     log(intervals); 

     return intervals; 

    } 

    public static List<Interval> createYearlyPeriodByCalendarWeek() { 

     DateTime startInstant = new DateTime(2012, 3, 1, 0, 0, 0, 0, DateTimeZone.UTC); 
     DateTime endInstant = new DateTime(2017, 1, 10, 0, 0, 0, 0, DateTimeZone.UTC); 

     DateTimeFieldType[] fields = new DateTimeFieldType[] { DateTimeFieldType.weekOfWeekyear(), DateTimeFieldType.hourOfDay(), DateTimeFieldType.minuteOfDay() }; 
     Partial startPartial = new Partial(fields, new int[] { 1, 2, 0 }); 
     Partial endPartial = new Partial(fields, new int[] { 3, 6, 0 }); 

     IntervalCreator intervalCreator = new IntervalCreator(startInstant, endInstant, startPartial, endPartial, Periodicity.WEEK_OF_YEAR); 
     List<Interval> intervals = intervalCreator.createIntervals(); 

     log(intervals); 

     return intervals; 

    } 

    private static void log(List<Interval> intervals) { 

     for (int i = 0; i < intervals.size(); i++) { 
      Interval interval = intervals.get(i); 
      System.out.println("Interval " + i + ": " + formatter.print(interval.getStart()) + " - " + formatter.print(interval.getEnd())); 
     } 

    } 


    public static void main(String[] args) { 

     Locale.setDefault(Locale.ENGLISH); 

     System.out.println("daily:"); 
     createDailyPeriod(); 

     System.out.println("\nweekly:"); 
     createWeeklyPeriod(); 

     System.out.println("\nyearly:"); 
     createYearlyPeriod(); 

     System.out.println("\nyearly by calendar week:"); 
     createYearlyPeriodByCalendarWeek(); 

     System.exit(0); 
    } 
} 

テスト出力:

daily: 
Interval 0: 12 Wed 2017-03-22 00:00 - 12 Wed 2017-03-22 02:00 
Interval 1: 12 Wed 2017-03-22 23:00 - 12 Thu 2017-03-23 02:00 
Interval 2: 12 Thu 2017-03-23 23:00 - 12 Fri 2017-03-24 02:00 
Interval 3: 12 Fri 2017-03-24 23:00 - 12 Sat 2017-03-25 02:00 
Interval 4: 12 Sat 2017-03-25 23:00 - 12 Sun 2017-03-26 02:00 
Interval 5: 12 Sun 2017-03-26 23:00 - 13 Mon 2017-03-27 02:00 
Interval 6: 13 Mon 2017-03-27 23:00 - 13 Tue 2017-03-28 02:00 
Interval 7: 13 Tue 2017-03-28 23:00 - 13 Wed 2017-03-29 02:00 
Interval 8: 13 Wed 2017-03-29 23:00 - 13 Thu 2017-03-30 00:00 

weekly: 
Interval 0: 9 Wed 2017-03-01 00:00 - 9 Wed 2017-03-01 06:00 
Interval 1: 10 Mon 2017-03-06 04:00 - 10 Wed 2017-03-08 06:00 
Interval 2: 11 Mon 2017-03-13 04:00 - 11 Tue 2017-03-14 00:00 

yearly: 
Interval 0: 9 Thu 2012-03-01 00:00 - 11 Fri 2012-03-16 06:00 
Interval 1: 9 Wed 2013-02-27 04:00 - 11 Sat 2013-03-16 06:00 
Interval 2: 9 Thu 2014-02-27 04:00 - 11 Sun 2014-03-16 06:00 
Interval 3: 9 Fri 2015-02-27 04:00 - 12 Mon 2015-03-16 06:00 
Interval 4: 8 Sat 2016-02-27 04:00 - 11 Wed 2016-03-16 06:00 
Interval 5: 9 Mon 2017-02-27 04:00 - 11 Tue 2017-03-14 00:00 

yearly by calendar week: 
Interval 0: 1 Mon 2012-12-31 02:00 - 3 Mon 2013-01-14 06:00 
Interval 1: 1 Mon 2013-12-30 02:00 - 3 Mon 2014-01-13 06:00 
Interval 2: 1 Mon 2014-12-29 02:00 - 3 Mon 2015-01-12 06:00 
Interval 3: 1 Mon 2016-01-04 02:00 - 3 Mon 2016-01-18 06:00 
Interval 4: 1 Mon 2017-01-02 02:00 - 2 Tue 2017-01-10 00:00 
関連する問題