Chrono date library

48 views
Skip to first unread message

Matt Moriarity

unread,
Mar 5, 2009, 5:57:27 PM3/5/09
to Clojure
This was posted about a little while ago, but a great deal more has
happened. Basically, Phil Hagelberg and I have been working on a nice
little date library for Clojure that doesn't rely on anything but the
Java date APIs. Last time I posted about this, a few people brought up
Joda time, which we are aware of. This library is meant for those who
want a nice Clojure API with no external dependencies and (usually) no
need to dip into Java. It supports:

- Creating dates
- Accessing date fields similar to maps
- Relative dates with earlier and later
- Getting the time between dates
- Formatting and parsing dates using multimethods

The code is available in either mine or Phil's github forks of clojure-
contrib:

http://github.com/cooldude127/clojure-contrib/
http://github.com/technomancy/clojure-contrib/

We'd like to hear opinions and whether people are willing to admit
this into clojure-contrib. Phil has already done his CA, I should
submit mine soon.

Phil Hagelberg

unread,
Mar 5, 2009, 6:08:46 PM3/5/09
to clo...@googlegroups.com
Matt Moriarity <matt.mo...@gmail.com> writes:

> The code is available in either mine or Phil's github forks of clojure-
> contrib:
>
> http://github.com/cooldude127/clojure-contrib/
> http://github.com/technomancy/clojure-contrib/
>
> We'd like to hear opinions and whether people are willing to admit
> this into clojure-contrib. Phil has already done his CA, I should
> submit mine soon.

I've attached a copy of the implementation as well as the tests so you
don't need to poke through our github repositories to find them. The
tests are relatively thorough and provide a good example of how the
library is meant to be used.

Date processing is a common enough task that I think support for it
should be included in contrib, especially considering how awkward the
java.util.Date API is to use directly. If it's agreed that this is a
good fit for contrib, we can create a Google Code issue and attach a
patch there.

Phil Hagelberg
http://technomancy.us

chrono.clj
test-chrono.clj

Cosmin Stejerean

unread,
Mar 5, 2009, 6:35:37 PM3/5/09
to clo...@googlegroups.com
I like the API so far, although I'll probably have to wait for timezone support before I can start using this.

If anyone else is interested here is a link to github for chrono.clj (syntax highlighting). For some reason I couldn't locate test-chrono.clj in the repo.

--
Cosmin Stejerean
http://offbytwo.com

Phil Hagelberg

unread,
Mar 5, 2009, 6:49:14 PM3/5/09
to clo...@googlegroups.com
Cosmin Stejerean <cstej...@gmail.com> writes:

> I like the API so far, although I'll probably have to wait for
> timezone support before I can start using this.

Would love some suggestions on what you'd expect the API to look like
for this. Failing test cases would be even better. I haven't given it
much thought yet.

> If anyone else is interested here is a link to github
> for chrono.clj (syntax highlighting). For some reason I couldn't
> locate test-chrono.clj in the repo.

The convention in contrib is to keep tests in
src/clojure/contrib/test_contrib/chrono.clj, but I didn't want to attach
two "chrono.clj" files, so I renamed it. Here's the link:

http://github.com/technomancy/clojure-contrib/blob/de4afee3dbfef2ed7f095ce1e7c2b7ea98e13e71/src/clojure/contrib/test_contrib/chrono.clj

-Phil

Allen Rohner

unread,
Mar 5, 2009, 6:54:56 PM3/5/09
to Clojure


On Mar 5, 5:49 pm, Phil Hagelberg <p...@hagelb.org> wrote:
> Cosmin Stejerean <cstejer...@gmail.com> writes:
> > I like the API so far, although I'll probably have to wait for
> > timezone support before I can start using this.
>
> Would love some suggestions on what you'd expect the API to look like
> for this. Failing test cases would be even better. I haven't given it
> much thought yet.
>
> > If anyone else is interested here is a link to github
> > for chrono.clj (syntax highlighting). For some reason I couldn't
> > locate test-chrono.clj in the repo.
>
> The convention in contrib is to keep tests in
> src/clojure/contrib/test_contrib/chrono.clj, but I didn't want to attach
> two "chrono.clj" files, so I renamed it. Here's the link:
>
> http://github.com/technomancy/clojure-contrib/blob/de4afee3dbfef2ed7f...
>
> -Phil

I strongly recommend that you make sure you understand where and why
Joda differs from the Java standard lib. If you don't handle the cases
that Joda already does, you *will* have bugs.

I would prefer having a dependency on an extra Jar vs. having bugs.
I'd also prefer having one obviously correct implementation vs.
multiple incorrect implementations and not knowing which one is least
broken, ala the python stdlib.

Joda correctly handles bugs I've personally encountered in java,
python, ruby and postgres.

I'm sorry if this sounds harsh, but I've spent too much time dealing
with Time bugs to suffer the creation of another broken
implementation, especially in my favorite language.

Allen

Phil Hagelberg

unread,
Mar 5, 2009, 7:10:57 PM3/5/09
to clo...@googlegroups.com
Allen Rohner <aro...@gmail.com> writes:

> I strongly recommend that you make sure you understand where and why
> Joda differs from the Java standard lib. If you don't handle the cases
> that Joda already does, you *will* have bugs.

Interesting. So far everyone I've talked to who recommended Joda did so
because the built-in Java classes had extremely awkward/limited APIs,
not because their behaviour was incorrect in some way.

I'm definitely interested in looking into this deeper, but what kind of
problems have you seen? Timezone-related bugs? Leap year problems?

Perhaps I should look through their test suite.

-Phil

Jeffrey Straszheim

unread,
Mar 5, 2009, 8:54:36 PM3/5/09
to clo...@googlegroups.com
I took a brief glance at Joda.  It appears they already use immutable objects to a large degree.  It looks like *exactly* the sort of library we can just use out of the box, unwrapped.

Allen Rohner

unread,
Mar 5, 2009, 11:25:02 PM3/5/09
to Clojure


On Mar 5, 6:10 pm, Phil Hagelberg <p...@hagelb.org> wrote:
A few links for more proof:

http://www.ociweb.com/jnb/jnbJul2008.html "As mentioned, one of the
problems with the JDK API is difficulty in calculating the number of
days between two different dates. To learn a bit about how to use Joda
Time, let's see how one can solve that problem a few different ways
using Joda Time. The example finds the number of days from January 1,
2008 to July 1, 2008 ... While this might seem a trivial problem, it
actually is not simple using just the JDK. The typical approach used
with the JDK is to compare the timestamps for the midnights of January
1 and July 1 and divide the result by the number of milliseconds in a
day. While this works in some cases, my computer would give 181.958333
using that approach instead of 182 for the given example. Why? Because
my computer is set to use Daylight Saving Time in the northern
hemisphere, and one hour was skipped in the first half of the year."

http://jcp.org/en/jsr/detail?id=310 This is the JSR for the
replacement of the java date/time libraries. The replacement is being
written by the author of Joda time, largely based on his experience in
Joda time. Section 2.5 of the JSR lists many current problems with the
java std lib time representation.

The javadocs for Date and Calendar are also worth reading:

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Date.html
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html

Additionally, the Joda library heavily emphasizes immutable objects.

HTH,

Allen

Phil Hagelberg

unread,
Mar 6, 2009, 12:39:23 AM3/6/09
to clo...@googlegroups.com

Allen Rohner <aro...@gmail.com> writes:

> http://www.ociweb.com/jnb/jnbJul2008.html "As mentioned, one of the
> problems with the JDK API is difficulty in calculating the number of
> days between two different dates. To learn a bit about how to use Joda
> Time, let's see how one can solve that problem a few different ways
> using Joda Time. The example finds the number of days from January 1,
> 2008 to July 1, 2008 ... While this might seem a trivial problem, it
> actually is not simple using just the JDK. The typical approach used
> with the JDK is to compare the timestamps for the midnights of January
> 1 and July 1 and divide the result by the number of milliseconds in a
> day. While this works in some cases, my computer would give 181.958333
> using that approach instead of 182 for the given example. Why? Because
> my computer is set to use Daylight Saving Time in the northern
> hemisphere, and one hour was skipped in the first half of the year."

> http://jcp.org/en/jsr/detail?id=310 This is the JSR for the
> replacement of the java date/time libraries. The replacement is being
> written by the author of Joda time, largely based on his experience in
> Joda time. Section 2.5 of the JSR lists many current problems with the
> java std lib time representation.

Very interesting; I will take a closer look. I'm not convinced the
problems can't be worked around once we are made aware of them, but it
definitely merits further investigation.

What's the status of this JSR? Is it possible the JDK 7 will include
more palatable date processing capabilities? I think it would be a shame
if external libraries were required to get sane date processing in
Clojure, but if the JDK 7 has potential to fix it, that's encouraging.

Most of the problems mentioned seem to be related to timezones. It seems
the worst case scenario is simply to have Chrono support no
timezone-aware operations out of the box on JDKs 5 and 6, but be able to
offer greater capabilities if either the JDK 7 or Joda time is
installed. I agree that having a more limited library is better than
having one that claims to have greater capabilities, but has bugs.

> Additionally, the Joda library heavily emphasizes immutable objects.

Everything in Chrono is immutable as well, provided you stick to the
functions in Chrono. You can still poke under the covers and get at the
underlying calendar objects, but there's no danger that someone would do
that without knowing what they were getting into.

It would be pretty easy to always return a copy of the underlying
calendar as well if providing (undocumented) access to the mutable
object turns out to be an issue.

-Phil

Allen Rohner

unread,
Mar 6, 2009, 12:04:24 PM3/6/09
to Clojure

>
> What's the status of this JSR? Is it possible the JDK 7 will include
> more palatable date processing capabilities? I think it would be a shame
> if external libraries were required to get sane date processing in
> Clojure, but if the JDK 7 has potential to fix it, that's encouraging.
>

As far as I can tell, the JSR was approved to go into Java 7, but
there is some risk of them not being done by the deadline. JSR-310 is
a complete re-write, I assume for licensing reasons.

> Most of the problems mentioned seem to be related to timezones. It seems
> the worst case scenario is simply to have Chrono support no
> timezone-aware operations out of the box on JDKs 5 and 6, but be able to
> offer greater capabilities if either the JDK 7 or Joda time is
> installed. I agree that having a more limited library is better than
> having one that claims to have greater capabilities, but has bugs.
>

Yes, most problems I've encountered and read about are timezone
problems. I'll keep going back to the "number of days between Jan 1
and June 1" problem, because it's easy and instructive. You cannot
answer that correctly without specifying a timezone. And if you "don't
support timezones", the only timezone where your library can be used
correctly is UTC.

One of the large advantages of Joda is that the API is constructed in
such a way that it is obvious what will happen. For example, there are
two ways to specify a duration, an Instant and a Partial. An Instant
is used to say "now + 86400 seconds". A partial is used to say "now +
1 week". Those are two different operations because they can have two
different results depending on the current year and timezone.

This is actually a very convenient time to write this note, because it
makes my examples easy. :-) Where I live, Daylight Savings Time
happens this Sunday, and my timezone will change from Central Standard
Time to Central Daylight Time. It is currently Friday Mar 6 10:40 am
CST. If I ask for "now + 7 days", the correct answer is "Friday Mar
13, 10:40 am CDT". But if I ask for "now + 86400 seconds", the correct
answer is "Friday Mar 13, 11:40 am CDT". Naively converting from
seconds to days/weeks/months/years is not a well defined operation in
most timezones.

> I'm not convinced the problems can't be worked around once we are made aware of them, but it definitely merits further investigation.

I'm sure the problems can be worked around once you're aware of them,
but a correct solution will end up with a lot of the same concepts as
Joda, and definitely won't have the same API as you do now. If you
base Chrono on Joda you can avoid all of that pain now.

Allen

Phil Hagelberg

unread,
Mar 6, 2009, 2:18:42 PM3/6/09
to clo...@googlegroups.com
Allen Rohner <aro...@gmail.com> writes:

> As far as I can tell, the JSR was approved to go into Java 7, but
> there is some risk of them not being done by the deadline. JSR-310 is
> a complete re-write, I assume for licensing reasons.

Interesting.

> One of the large advantages of Joda is that the API is constructed in
> such a way that it is obvious what will happen. For example, there are
> two ways to specify a duration, an Instant and a Partial. An Instant
> is used to say "now + 86400 seconds". A partial is used to say "now +
> 1 week". Those are two different operations because they can have two
> different results depending on the current year and timezone.

What this means to me is that the earlier, later, and time-between
functions will need to behave differently if the units used are
variable-length (days and up) vs invariable (seconds, minutes, hours).

> This is actually a very convenient time to write this note, because it
> makes my examples easy. :-) Where I live, Daylight Savings Time
> happens this Sunday, and my timezone will change from Central Standard
> Time to Central Daylight Time. It is currently Friday Mar 6 10:40 am
> CST. If I ask for "now + 7 days", the correct answer is "Friday Mar
> 13, 10:40 am CDT". But if I ask for "now + 86400 seconds", the correct
> answer is "Friday Mar 13, 11:40 am CDT". Naively converting from
> seconds to days/weeks/months/years is not a well defined operation in
> most timezones.

I don't think it would be too hard to remove naive conversions between
days/weeks etc and seconds from Chrono. But I do agree that it shouldn't
be adopted for any use until this is done. And it may be harder than I
suspect. We'll see.

>> I'm not convinced the problems can't be worked around once we are
>> made aware of them, but it definitely merits further investigation.
>
> I'm sure the problems can be worked around once you're aware of them,
> but a correct solution will end up with a lot of the same concepts as
> Joda, and definitely won't have the same API as you do now. If you
> base Chrono on Joda you can avoid all of that pain now.

Yes, but any library that requires third-party jars can't be used out of
the box in contrib, and I think a language that doesn't support
date-processing out of the box is at a severe disadvantage.

-Phil

Michael Wood

unread,
Mar 6, 2009, 4:48:38 PM3/6/09
to clo...@googlegroups.com
On Fri, Mar 6, 2009 at 9:18 PM, Phil Hagelberg <ph...@hagelb.org> wrote:
>
> Allen Rohner <aro...@gmail.com> writes:
[...]

>> One of the large advantages of Joda is that the API is constructed in
>> such a way that it is obvious what will happen. For example, there are
>> two ways to specify a duration, an Instant and a Partial. An Instant
>> is used to say "now + 86400 seconds". A partial is used to say "now +
>> 1 week". Those are two different operations because they can have two
>> different results depending on the current year and timezone.
>
> What this means to me is that the earlier, later, and time-between
> functions will need to behave differently if the units used are
> variable-length (days and up) vs invariable (seconds, minutes, hours).
[...]

Just to be pedantic, minutes are also occasionally variable:
http://en.wikipedia.org/wiki/Leap_second

--
Michael Wood <esio...@gmail.com>

Allen Rohner

unread,
Mar 7, 2009, 2:26:24 PM3/7/09
to Clojure
>
> Yes, but any library that requires third-party jars can't be used out of
> the box in contrib, and I think a language that doesn't support
> date-processing out of the box is at a severe disadvantage.
>

One of the primary reasons Clojure is on the JVM is to re-use Java
libraries. Date & Time calculations are

1) notoriously tricky
2) broken or incomplete in almost every language's standard library
3) solved fairly well in Joda

I don't think it's unreasonable to put a dependency on a third party
jar when it solves the problem better than other attempts.

Allen
Reply all
Reply to author
Forward
0 new messages