97jaz / gregor

Date and time library for Racket
45 stars 10 forks source link

Period comparison and translation to seconds #13

Closed jackfirth closed 8 years ago

jackfirth commented 8 years ago

A period<? function for determining which of two periods is shorter would be nice, along with a period->seconds function. I'm writing a cron-like library and I need to know whether a period representing "how much time has elapsed" is greater than a period representing "how much time to wait before doing X", and if not enough time has passed I need to pass the difference to sleep. This would be easy with these two functions, and without them I'll have to roll my own.

97jaz commented 8 years ago

How many seconds is a period of 1 month? Or 1 year?

Joda-time makes a distinction between durations, which are represented as a concrete magnitude of N milliseconds, and periods, which are not. Gregor has the latter concept but not the former. It's easy enough to build the former, but I wouldn't want to conflate them.

97jaz commented 8 years ago

However, this question has an answer: "How many seconds is a period of 1 month, starting at time t?" And that might be what you need, since you mention "how much time has elapsed" and "how much time to wait before doing X." It sounds like both of these have an anchor point.

So, "how much time has elapsed [between t1 and t2]" can be computed by ([milli/micro/nano]seconds-between t1 t2). And "how much time to wait before doing X [after period p has passed since time t]" would be (*-between t (+period t p)).

97jaz commented 8 years ago

As for the original request -- period<? and period->seconds -- I hope it's clear that this can't be done in the general case without either:

The first makes me uncomfortable, because only period with months or years components would lose precision, and I can imagine users blithely assuming that it gives an exact result. The second seems more promising, but I don't know how useful people would find it. I'm thinking of something like:

(period->seconds p #:starting t) ; or #:ending

For period<? you'd want to be able to specify separate anchors for the two periods being compared. (And at that point you might just be better off using < and period->seconds.)

The implementation of period->seconds (with only a #:starting option) is:

(define (period->seconds p #:starting t)
  (seconds-between t (+period t p)))
97jaz commented 8 years ago

One more thought: time-period->seconds would be exact without an anchor point, if that's sufficient for your purpose.

jackfirth commented 8 years ago

This makes total sense, and in retrospect should have been obvious.

I ended up using a duration representation pairing a period with a starting moment and using that period->seconds function you provided. This seems like it might be common enough to warrant an addition to gregor. Using durations and providing a duration->seconds function mostly eliminates the need for period->seconds, because (period->seconds p #:starting t) would be equivalent to (duration->seconds (duration #:starting-at t #:period p)) and it makes more sense to encourage using durations when you want exact amounts of time.