2

Is there an easy way to get to human centric style periods in Joda Time?

For instance, if I wanted the last 4 days and by that I mean, give me a period (or interval might be more apt) 3 full days and the current in progress day up to the current time. So I would expect, an interval of 1 day, 1 day, 1 day, n number of ms up to the current time.

Or for the last 5 weeks, give me 4 full weeks and the current in progress week up to the current time.

I've spent some time with this and the difficult part is try to "normalize" a period to the human definitions of the end of the period. So for day to date you need to normalize to the start of the day (which is always midnight) and then find the interval between that and now. For Months, which are crazy tricky, you would need to normalize to the start of the month and go to now... etc. To make this even more difficult I'm trying to avoid writing a giant case statement with Period specific normalization logic and I am racking my brain trying find a generic approach.

Here is my current code (in Groovy)

static List generatePreviousIntervals(BaseSingleFieldPeriod period,
                              int count,
                              DateTime end = DateTime.now()) {

    if (count < 1) {
        return []
    }

    def intervals = []
    Interval last
    count.times {
        def finish = last?.start ?: end
        def next = new Interval(period, finish)

        intervals.add(next)
        last = next
    }

    // reverse so intervals are in normal progression order
    intervals.reverse()
}

Is that something Joda Time can do easily? Or do I have to have a lot of logic around hand rolling specific intervals of time?

James McMahon
  • 48,506
  • 64
  • 207
  • 283
  • FYI, the [Joda-Time](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [java.time](http://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). Also, the *ThreeTen-Extra* library might help with this problem. – Basil Bourque Jan 02 '18 at 00:12

2 Answers2

2

This is what I ended up doing, I wasn't clever enough to avoid a case statement, but fortunately I was using a small amount of the period types, so it wasn't as huge as I thought it would be,

/**
 * Reset Joda DateTime by normalize it back to the beginning of the period
 */
static DateTime resetDate(BaseSingleFieldPeriod period,
                                DateTime date) {
    LocalDate out = new LocalDate(date)
    switch (period) {
        case Years.ONE:
            out = out.withMonthOfYear(1).withDayOfMonth(1)
            break;
        case Months.ONE:
            out = out.withDayOfMonth(1)
            break;
        case Weeks.ONE:
            // adjust day of week because Joda uses ISO standard Monday
            // as start of the week
            out = out.withDayOfWeek(1).minusDays(1)
            break;
        case Days.ONE:
            // nothing to for days as we have already removed time by
            // converting to local date
            break;
        default:
            throw new UnsupportedOperationException("Unsupported period $period")
    }

    // convert to date minute to avoid giving specific time
    out.toDateMidnight().toDateTime()
}

If anyone has a more elegant solution let me know.

James McMahon
  • 48,506
  • 64
  • 207
  • 283
0

Soounds like you need an interval : http://joda-time.sourceforge.net/apidocs/org/joda/time/Interval.html

And use the minusdays method. (yes it easy, very much so compared to the vanilla java date/calendar)

To get the time of day :

int hour = dt.getHourOfDay();
int min = dt.getMinuteOfHour();
int sec = dt.getSecondOfMinute();
NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
  • So I have to hand roll those intervals or is there something built in to facilitate this? – James McMahon Jun 18 '13 at 14:31
  • Yeah I have a method right now to generate intervals for me, only thing that sucks is that you have to have specific logic for each period so it can create the interval between the end of last period and now(). – James McMahon Jun 18 '13 at 14:39
  • all sounds pretty elegant to me, especialyl compared to the default java date api – NimChimpsky Jun 18 '13 at 14:41
  • Could you give me an example of how to manually roll this up? For example, if I had a DateTime now, and I wanted to get the amount of time between that and the end of the last day, how would I actually do that? – James McMahon Jun 18 '13 at 19:16
  • when you say the last day, you mean you mean the previous day ? That would just be getting the time ... see update. I am not sure what the problem is, you'll have to "hand roll" something ... but jodatime makes it all pretty easy. – NimChimpsky Jun 18 '13 at 21:11
  • you can get the number of seconds between two datetimes in three lines ... http://stackoverflow.com/questions/15134927/difference-in-seconds-between-two-dates-using-joda-time – NimChimpsky Jun 18 '13 at 21:19