Searching for a "TimeInterval" type...

  • Thread starter Andreas Leitgeb
  • Start date
A

Andreas Leitgeb

My application will maintain Calendar instances, and I need another type
to hold "intervals", such as (5 months, 4 days and 30 minutes) that I
could conveniently "add" to a Calendar instance.

My first thought was using another Calendar, and do a loop for the
add-operation:
Calendar cal = ...; Calendar intvl = ...;
for (int i=0; i<Calendar.FIELD_COUNT; i++) {
if (intvl.isSet(i)) { cal.add(i,intvl.get(i)); }
}
which would be fine for simple cases, but wouldn't work, if I
wanted to represent "100 days", which definitely isn't equivalent
to "3 months and 10/9 days" (depending on leapyear). If I just
don't call "complete()", then according to the docs get() would
bomb on me, for the days-value being out of bounds.

One alternative could be to just wrap a new int[Calendar.FIELD_COUNT],
and use the Calendar-constants to index into the array, but I wonder,
if I'm perhaps missing something more elegant. It's hard for me to
believe, that there wasn't any common need for representing intervals
of time in a mixture of units, and not just seconds.

Right now I'm optimizing for elegance not for performance.
 
M

markspace

It's hard for me to
believe, that there wasn't any common need for representing intervals
of time in a mixture of units, and not just seconds.


I think the new JOGL stuff has an interval (they call it a Duration).
But I don't think you're missing anything. The Calendar class is pretty
widely derided as missing a lot of important features, afaik.
 
M

Marcel Müller

My application will maintain Calendar instances, and I need another type
to hold "intervals", such as (5 months, 4 days and 30 minutes) that I
could conveniently "add" to a Calendar instance.

There is no such class in Java. The natural representation of time span
is an integer, in doubt a long, holding he difference of Calendar.getTime().

However, there are some non-unique definitions of time spans in
business. E.g. one month. It may mean anything between 28 and 31 days as
well as an undefined time period, e.g. if you add one month to Jan. 30th.
My first thought was using another Calendar, and do a loop for the
add-operation:
Calendar cal = ...; Calendar intvl = ...;
for (int i=0; i<Calendar.FIELD_COUNT; i++) {
if (intvl.isSet(i)) { cal.add(i,intvl.get(i)); }
}
which would be fine for simple cases, but wouldn't work, if I
wanted to represent "100 days", which definitely isn't equivalent
to "3 months and 10/9 days" (depending on leapyear). If I just
don't call "complete()", then according to the docs get() would
bomb on me, for the days-value being out of bounds.

That's the problem. You first need a /complete/ definition what should
happen, removing all undefined constellations.
One alternative could be to just wrap a new int[Calendar.FIELD_COUNT],
and use the Calendar-constants to index into the array, but I wonder,
if I'm perhaps missing something more elegant.

You missed nothing. You do not even need so much fields. In general
three fields should be sufficient with respect to the Gregorian
Calendar. Years, months and everything else. Have a look at the oracle
PL/SQL interval types.

However, for business this might sill be insufficient. There are terms
like 'after three business days'. The result might be different from
country to country.
It's hard for me to
believe, that there wasn't any common need for representing intervals
of time in a mixture of units, and not just seconds.

There are many needs for time intervals. There is just no unique
definition of the requirement.


Marcel
 
S

Silvio

My application will maintain Calendar instances, and I need another type
to hold "intervals", such as (5 months, 4 days and 30 minutes) that I
could conveniently "add" to a Calendar instance.

My first thought was using another Calendar, and do a loop for the
add-operation:
Calendar cal = ...; Calendar intvl = ...;
for (int i=0; i<Calendar.FIELD_COUNT; i++) {
if (intvl.isSet(i)) { cal.add(i,intvl.get(i)); }
}
which would be fine for simple cases, but wouldn't work, if I
wanted to represent "100 days", which definitely isn't equivalent
to "3 months and 10/9 days" (depending on leapyear). If I just
don't call "complete()", then according to the docs get() would
bomb on me, for the days-value being out of bounds.

One alternative could be to just wrap a new int[Calendar.FIELD_COUNT],
and use the Calendar-constants to index into the array, but I wonder,
if I'm perhaps missing something more elegant. It's hard for me to
believe, that there wasn't any common need for representing intervals
of time in a mixture of units, and not just seconds.

Right now I'm optimizing for elegance not for performance.

There is little point in a duration type using a value that represents
mixed number of units. Year and month are not universal time units and
can not be used to hold general durations.

The difference between two specific points in time can be expressed in a
mixed number of units, a general duration can not.

Use something like seconds or milliseconds. Calendar has a convenient
way of adding or subtracting such durations. If you need to express a
relative duration between two specific points in time you can create
some fancy function using Calendar and its fields or use an existing one.
 
A

Arne Vajhøj

My application will maintain Calendar instances, and I need another type
to hold "intervals", such as (5 months, 4 days and 30 minutes) that I
could conveniently "add" to a Calendar instance.

My first thought was using another Calendar, and do a loop for the
add-operation:
Calendar cal = ...; Calendar intvl = ...;
for (int i=0; i<Calendar.FIELD_COUNT; i++) {
if (intvl.isSet(i)) { cal.add(i,intvl.get(i)); }
}
which would be fine for simple cases, but wouldn't work, if I
wanted to represent "100 days", which definitely isn't equivalent
to "3 months and 10/9 days" (depending on leapyear). If I just
don't call "complete()", then according to the docs get() would
bomb on me, for the days-value being out of bounds.

One alternative could be to just wrap a new int[Calendar.FIELD_COUNT],
and use the Calendar-constants to index into the array, but I wonder,
if I'm perhaps missing something more elegant. It's hard for me to
believe, that there wasn't any common need for representing intervals
of time in a mixture of units, and not just seconds.

Right now I'm optimizing for elegance not for performance.

I would be tempted to go for the simple solution with a class
that contains two ints: number of units and a Calendar
unit identifier.

Arne
 
S

Sebastian

Am 01.10.2013 20:22, schrieb markspace:
I really loused that up. It's JODA time, and the class is Period.

<http://download.java.net/jdk8/docs/api/java/time/Period.html>
One nice thing about using Joda would be that your code will stand a
good chance of being easily portable to the new Data and Time API in the
upcoming Java 8 release, which is mostly inspired by Joda time.
Personally, I'd not start anything new based on the current Calendar
class and its relatives.

-- Sebastian
 
A

Andreas Leitgeb

Thanks to mark, Arne & Sebastian for pointing towards Joda and
future Java 8. It's good to know that this swamp is getting dried,
but I'll probably not hold my breath for it, and I'll probably stay
with Calendar for now, but at least I'm now aware to not fully embrace
it, but only pick minimal functionality from it. I hope I will then be
able to eventually translate to new date-API once Java 8 arrives.

Also, I actually (unfortunately) do need to represent mixes of units
and a day definitely isn't the same as 86400 seconds. Calendar seems
to support most of what I need. Now, that I know I didn't just miss a
standard class, I'll do my own for the type of intervals I need. (and
it seems to me (after looking at mark's link) as if neither Period nor
Duration fits my bill completely, anyway.)
 
A

Andreas Leitgeb

Marcel Müller said:
However, there are some non-unique definitions of time spans in
business. E.g. one month. It may mean anything between 28 and 31 days as
well as an undefined time period, e.g. if you add one month to Jan. 30th.

Calendar fortunately deals quite well with my needs, already.
My intervals do not translate into numbers of seconds.
One alternative could be to just wrap a new int[Calendar.FIELD_COUNT],
and use the Calendar-constants to index into the array, but I wonder,
if I'm perhaps missing something more elegant.
You missed nothing. [...]

I noticed that GregorianCalendar is not final, so I'm now extending my
Interval type from that, overriding those methods that would "prematurely"
do calls to "complete()", or check valid ranges. Among others I'm overriding
getMinimum and getMaximum to return Integer.MIN_VALUE and .MAX_VALUE .

I'll see if that is enough to allow "100 days" be represented without
unintended propagation to months.
However, for business this might sill be insufficient. There are terms
like 'after three business days'. The result might be different from
country to country.

Business day logic is not part of my task. (It might be later implemented
on top of Calendar and my interval-class, though)

Thanks for pointing out the pitfalls with date&interval-arithmetics.
 
A

Andreas Leitgeb

Arne Vajhøj said:
I would be tempted to go for the simple solution with a class
that contains two ints: number of units and a Calendar
unit identifier.

Unfortunately, that would be too simple for my needs.

Some example interval of what I'm going to deal with can be
described as "tomorrow one (wall-clock)hour earlier". This just
isn't the same as in "23 hours" (nor as "82800 seconds").

Thanks anyway for answering (also to Silvio, who also suggested
simply going for seconds-based durations).
 
J

Jukka Lahtinen

Andreas Leitgeb said:
Some example interval of what I'm going to deal with can be
described as "tomorrow one (wall-clock)hour earlier". This just
isn't the same as in "23 hours" (nor as "82800 seconds").

What will that be when called between midnight and 01:00?
 
S

Silvio

Unfortunately, that would be too simple for my needs.

Some example interval of what I'm going to deal with can be
described as "tomorrow one (wall-clock)hour earlier". This just
isn't the same as in "23 hours" (nor as "82800 seconds").

Thanks anyway for answering (also to Silvio, who also suggested
simply going for seconds-based durations).

What you are describing is not a duration or interval in the general
sense but a stylized way of expressing the time between two specific
points in time, not unlike a the numerous ways there are for expressing
a specific point in time.

General durations are mathematical numerical value types that support
normal binary numerical operations like addition/subtraction (duration
versus duration) and multiplication/division (duration versus numerical)
and comparisons (d vs. d).
 
A

Andreas Leitgeb

Jukka Lahtinen said:
What will that be when called between midnight and 01:00?

It would be the same day between 23:00 and midnight, even if the
day itself is a DST-switch-day.

The other question: what that would be "one day minus one hour" after
a timestamp between 3am and 4am of the saturday before Spring DST day?
Answer: I don't care. That would be a weekend, and I happen not to care
about weekends for my task ;-)
It's just not specified. If a solution works for all other cases, it'll
be fine for the spec, even if it gave me a date in year 42 BCE for that
particular situation. (ditto for Autumn, although I'd personally tend to
prefer the second one of the two "2am-3am" hours then)
 
A

Andreas Leitgeb

Silvio said:
What you are describing is not a duration or interval in the general
sense but a stylized way of expressing the time between two specific
points in time, not unlike a the numerous ways there are for expressing
a specific point in time.

Yes, kind of. I never claimed to expect algebraic field properties.

If I had my way, I'd slow down earth-spin and accellerate it's movement
around the sun, until we reach an exact 100 days year. ;-)
My days are all too short, anyway... (that's why I'm writing this at 2am)
 
A

Arne Vajhøj

Unfortunately, that would be too simple for my needs.

Some example interval of what I'm going to deal with can be
described as "tomorrow one (wall-clock)hour earlier". This just
isn't the same as in "23 hours" (nor as "82800 seconds").

Maybe two classes RelativeTime and AbsoluteTime so your
problem could be one RelativeTime with 1 HOUR and one
AbsoluteTime with HOUR X (where X is now hour minus one).

Arne
 
D

Daniele Futtorovic

Thanks to mark, Arne & Sebastian for pointing towards Joda and
future Java 8. It's good to know that this swamp is getting dried,
but I'll probably not hold my breath for it, and I'll probably stay
with Calendar for now, but at least I'm now aware to not fully embrace
it, but only pick minimal functionality from it. I hope I will then be
able to eventually translate to new date-API once Java 8 arrives.

Also, I actually (unfortunately) do need to represent mixes of units
and a day definitely isn't the same as 86400 seconds. Calendar seems
to support most of what I need. Now, that I know I didn't just miss a
standard class, I'll do my own for the type of intervals I need. (and
it seems to me (after looking at mark's link) as if neither Period nor
Duration fits my bill completely, anyway.)

Having worked with with JODA in the past, I *strongly* recommend you
made use of it, regardless of the circumstances.
 
J

Jukka Lahtinen

It would be the same day between 23:00 and midnight, even if the
day itself is a DST-switch-day.

In that case it isn't tomorrow, so "tomorrow one (wall-clock)hour
earlier" is a bit misleading 1 hour in every 24. That is over 4% of
time.
The other question: what that would be "one day minus one hour" after
a timestamp between 3am and 4am of the saturday before Spring DST day?
Answer: I don't care. That would be a weekend, and I happen not to care
about weekends for my task ;-)

Logically it would probably skip one hour in Spring and use one hour
twice in Fall, when called near the time of the change. And the other
way round when the result would be near the time of the change.
(Or is it the other way round..)
And apparently this doesn't matter.
 
A

Andreas Leitgeb

Jukka Lahtinen said:
In that case it isn't tomorrow, so "tomorrow one (wall-clock)hour
earlier" is a bit misleading 1 hour in every 24. That is over 4% of
time.

The only thing that may have been misleading was my short verbal
representation. A (slightly) more precise one could have been:
"next day same wallclock time, but then one hour earlier"

(making the "next day same wallclock time" merely a landmark on the
route to the target time. Fortunately, we're smart enough to arrive
there without waiting for next day same time and then needing to go
one hour backwards in time)

A really exact description of that concept of mixed units timespans
is implemented by my GregorianCalendar-derived Interval class, although
I didn't test it yet. So little time, so much to do ;-)
 
J

Jukka Lahtinen

The only thing that may have been misleading was my short verbal
representation. A (slightly) more precise one could have been:
"next day same wallclock time, but then one hour earlier"

Or just changing the order of words to "one hour before the same time
tomorrow".
Well, working with computers you learn to nitpick and tend to check what
is really meant with ambiguous expressions..
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top