有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用Joda时间中给定的周期性获取间隔列表

在给定开始日期、结束日期和周期的情况下,是否可以使用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

有人知道在乔达时代该怎么做吗?最好是通用的,即与其他类型的周期,如每日/每周/每月/每年/等

非常感谢您的专业知识


共 (1) 个答案

  1. # 1 楼答案

    在深入研究了乔达的时间之后,我自己找到了解决办法。我把它贴在这里,也许其他人也需要它。如果任何更熟悉Joda Time的人检查了这一点,请随时改进代码

    算法:

    • 使用给定的句点创建partials
    • 将部分应用于间隔开始日期,并创建期间开始和结束日期
    • 将期间开始日期和结束日期都偏移,使其早于间隔开始日期
    • 如果期间结束日期早于期间开始日期,则将其提前1个持续时间步长
    • 按持续时间步长提前时段,直到时段开始日期晚于时段结束日期

    我真的不想做自己的计算,所以算法只使用api,因此可以使用优化(例如,获取星期几的for循环)

    因此,如果有人需要代码,请参阅:

    周期性。爪哇

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

    间隙创造者。爪哇

    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。爪哇

    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