2017-03-10 1 views
0

시작 날짜, 종료 날짜 및주기를 고려하여 Joda 시간을 사용하여 간격 목록을 가져올 수 있습니까? 주간 기간Joda 시간에서 주어진 주기성을 사용하여 간격 목록을 얻으십시오.

예 :

* 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 

은 사람이하는 방법을 알고 있나요 조다 시간에? 일반적으로 바람직하다. 이자형. 매일/주간/월간/연간/기타와 같은 다른 유형의 기간이 포함됩니다.

감사합니다.

답변

0

Joda Time을 파고 들자 해결책을 찾았습니다. 나는 그것을 여기에 게시한다. 누군가 다른 사람에게도 필요할지도 모른다. Joda Time에 익숙한 사람이 이것을 확인하면 코드를 개선하십시오.

알고리즘 :

  • 간격 시작일 파셜을 적용주기 시작 및 종료일을 작성 주어진 기간을 이용하여 부분 지문을 생성
  • 기간의 시작 및 종료 날짜를 둘 수 있도록 그들 앞에있는
  • 시프트 간격 시작 날짜
  • 기간 종료 날짜가 기간 시작 날짜보다 이전 인 경우, 1 지속 기간 간격만큼 앞당겨니다.
  • 기간 시작 단계까지의 진행 기간 날짜가 간격 종료 날짜 이후 임

나는 내 자신의 계산을 정말로 원하지 않으므로 알고리즘은 API 만 사용하므로 최적화 (예 : 지. 요일을 얻기위한 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

,515,
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 
관련 문제